Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/unwind/src/Registers.hpp
12346 views
1
//===----------------------------- Registers.hpp --------------------------===//
2
//
3
// The LLVM Compiler Infrastructure
4
//
5
// This file is dual licensed under the MIT and the University of Illinois Open
6
// Source Licenses. See LICENSE.TXT for details.
7
//
8
//
9
// Models register sets for supported processors.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#ifndef __REGISTERS_HPP__
14
#define __REGISTERS_HPP__
15
16
#include <stdint.h>
17
#include <string.h>
18
19
#include "libunwind.h"
20
#include "config.h"
21
22
namespace libunwind {
23
24
// For emulating 128-bit registers
25
struct v128 { uint32_t vec[4]; };
26
27
enum {
28
REGISTERS_X86,
29
REGISTERS_X86_64,
30
REGISTERS_PPC,
31
REGISTERS_PPC64,
32
REGISTERS_ARM64,
33
REGISTERS_ARM,
34
REGISTERS_OR1K,
35
REGISTERS_MIPS_O32,
36
REGISTERS_MIPS_NEWABI,
37
REGISTERS_SPARC,
38
};
39
40
#if defined(_LIBUNWIND_TARGET_I386)
41
/// Registers_x86 holds the register state of a thread in a 32-bit intel
42
/// process.
43
class _LIBUNWIND_HIDDEN Registers_x86 {
44
public:
45
Registers_x86();
46
Registers_x86(const void *registers);
47
48
bool validRegister(int num) const;
49
uint32_t getRegister(int num) const;
50
void setRegister(int num, uint32_t value);
51
bool validFloatRegister(int) const { return false; }
52
double getFloatRegister(int num) const;
53
void setFloatRegister(int num, double value);
54
bool validVectorRegister(int) const { return false; }
55
v128 getVectorRegister(int num) const;
56
void setVectorRegister(int num, v128 value);
57
static const char *getRegisterName(int num);
58
void jumpto();
59
static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86; }
60
static int getArch() { return REGISTERS_X86; }
61
62
uint32_t getSP() const { return _registers.__esp; }
63
void setSP(uint32_t value) { _registers.__esp = value; }
64
uint32_t getIP() const { return _registers.__eip; }
65
void setIP(uint32_t value) { _registers.__eip = value; }
66
uint32_t getEBP() const { return _registers.__ebp; }
67
void setEBP(uint32_t value) { _registers.__ebp = value; }
68
uint32_t getEBX() const { return _registers.__ebx; }
69
void setEBX(uint32_t value) { _registers.__ebx = value; }
70
uint32_t getECX() const { return _registers.__ecx; }
71
void setECX(uint32_t value) { _registers.__ecx = value; }
72
uint32_t getEDX() const { return _registers.__edx; }
73
void setEDX(uint32_t value) { _registers.__edx = value; }
74
uint32_t getESI() const { return _registers.__esi; }
75
void setESI(uint32_t value) { _registers.__esi = value; }
76
uint32_t getEDI() const { return _registers.__edi; }
77
void setEDI(uint32_t value) { _registers.__edi = value; }
78
79
private:
80
struct GPRs {
81
unsigned int __eax;
82
unsigned int __ebx;
83
unsigned int __ecx;
84
unsigned int __edx;
85
unsigned int __edi;
86
unsigned int __esi;
87
unsigned int __ebp;
88
unsigned int __esp;
89
unsigned int __ss;
90
unsigned int __eflags;
91
unsigned int __eip;
92
unsigned int __cs;
93
unsigned int __ds;
94
unsigned int __es;
95
unsigned int __fs;
96
unsigned int __gs;
97
};
98
99
GPRs _registers;
100
};
101
102
inline Registers_x86::Registers_x86(const void *registers) {
103
static_assert((check_fit<Registers_x86, unw_context_t>::does_fit),
104
"x86 registers do not fit into unw_context_t");
105
memcpy(&_registers, registers, sizeof(_registers));
106
}
107
108
inline Registers_x86::Registers_x86() {
109
memset(&_registers, 0, sizeof(_registers));
110
}
111
112
inline bool Registers_x86::validRegister(int regNum) const {
113
if (regNum == UNW_REG_IP)
114
return true;
115
if (regNum == UNW_REG_SP)
116
return true;
117
if (regNum < 0)
118
return false;
119
if (regNum > 7)
120
return false;
121
return true;
122
}
123
124
inline uint32_t Registers_x86::getRegister(int regNum) const {
125
switch (regNum) {
126
case UNW_REG_IP:
127
return _registers.__eip;
128
case UNW_REG_SP:
129
return _registers.__esp;
130
case UNW_X86_EAX:
131
return _registers.__eax;
132
case UNW_X86_ECX:
133
return _registers.__ecx;
134
case UNW_X86_EDX:
135
return _registers.__edx;
136
case UNW_X86_EBX:
137
return _registers.__ebx;
138
#if !defined(__APPLE__)
139
case UNW_X86_ESP:
140
#else
141
case UNW_X86_EBP:
142
#endif
143
return _registers.__ebp;
144
#if !defined(__APPLE__)
145
case UNW_X86_EBP:
146
#else
147
case UNW_X86_ESP:
148
#endif
149
return _registers.__esp;
150
case UNW_X86_ESI:
151
return _registers.__esi;
152
case UNW_X86_EDI:
153
return _registers.__edi;
154
}
155
_LIBUNWIND_ABORT("unsupported x86 register");
156
}
157
158
inline void Registers_x86::setRegister(int regNum, uint32_t value) {
159
switch (regNum) {
160
case UNW_REG_IP:
161
_registers.__eip = value;
162
return;
163
case UNW_REG_SP:
164
_registers.__esp = value;
165
return;
166
case UNW_X86_EAX:
167
_registers.__eax = value;
168
return;
169
case UNW_X86_ECX:
170
_registers.__ecx = value;
171
return;
172
case UNW_X86_EDX:
173
_registers.__edx = value;
174
return;
175
case UNW_X86_EBX:
176
_registers.__ebx = value;
177
return;
178
#if !defined(__APPLE__)
179
case UNW_X86_ESP:
180
#else
181
case UNW_X86_EBP:
182
#endif
183
_registers.__ebp = value;
184
return;
185
#if !defined(__APPLE__)
186
case UNW_X86_EBP:
187
#else
188
case UNW_X86_ESP:
189
#endif
190
_registers.__esp = value;
191
return;
192
case UNW_X86_ESI:
193
_registers.__esi = value;
194
return;
195
case UNW_X86_EDI:
196
_registers.__edi = value;
197
return;
198
}
199
_LIBUNWIND_ABORT("unsupported x86 register");
200
}
201
202
inline const char *Registers_x86::getRegisterName(int regNum) {
203
switch (regNum) {
204
case UNW_REG_IP:
205
return "ip";
206
case UNW_REG_SP:
207
return "esp";
208
case UNW_X86_EAX:
209
return "eax";
210
case UNW_X86_ECX:
211
return "ecx";
212
case UNW_X86_EDX:
213
return "edx";
214
case UNW_X86_EBX:
215
return "ebx";
216
case UNW_X86_EBP:
217
return "ebp";
218
case UNW_X86_ESP:
219
return "esp";
220
case UNW_X86_ESI:
221
return "esi";
222
case UNW_X86_EDI:
223
return "edi";
224
default:
225
return "unknown register";
226
}
227
}
228
229
inline double Registers_x86::getFloatRegister(int) const {
230
_LIBUNWIND_ABORT("no x86 float registers");
231
}
232
233
inline void Registers_x86::setFloatRegister(int, double) {
234
_LIBUNWIND_ABORT("no x86 float registers");
235
}
236
237
inline v128 Registers_x86::getVectorRegister(int) const {
238
_LIBUNWIND_ABORT("no x86 vector registers");
239
}
240
241
inline void Registers_x86::setVectorRegister(int, v128) {
242
_LIBUNWIND_ABORT("no x86 vector registers");
243
}
244
#endif // _LIBUNWIND_TARGET_I386
245
246
247
#if defined(_LIBUNWIND_TARGET_X86_64)
248
/// Registers_x86_64 holds the register state of a thread in a 64-bit intel
249
/// process.
250
class _LIBUNWIND_HIDDEN Registers_x86_64 {
251
public:
252
Registers_x86_64();
253
Registers_x86_64(const void *registers);
254
255
bool validRegister(int num) const;
256
uint64_t getRegister(int num) const;
257
void setRegister(int num, uint64_t value);
258
bool validFloatRegister(int) const { return false; }
259
double getFloatRegister(int num) const;
260
void setFloatRegister(int num, double value);
261
bool validVectorRegister(int) const;
262
v128 getVectorRegister(int num) const;
263
void setVectorRegister(int num, v128 value);
264
static const char *getRegisterName(int num);
265
void jumpto();
266
static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86_64; }
267
static int getArch() { return REGISTERS_X86_64; }
268
269
uint64_t getSP() const { return _registers.__rsp; }
270
void setSP(uint64_t value) { _registers.__rsp = value; }
271
uint64_t getIP() const { return _registers.__rip; }
272
void setIP(uint64_t value) { _registers.__rip = value; }
273
uint64_t getRBP() const { return _registers.__rbp; }
274
void setRBP(uint64_t value) { _registers.__rbp = value; }
275
uint64_t getRBX() const { return _registers.__rbx; }
276
void setRBX(uint64_t value) { _registers.__rbx = value; }
277
uint64_t getR12() const { return _registers.__r12; }
278
void setR12(uint64_t value) { _registers.__r12 = value; }
279
uint64_t getR13() const { return _registers.__r13; }
280
void setR13(uint64_t value) { _registers.__r13 = value; }
281
uint64_t getR14() const { return _registers.__r14; }
282
void setR14(uint64_t value) { _registers.__r14 = value; }
283
uint64_t getR15() const { return _registers.__r15; }
284
void setR15(uint64_t value) { _registers.__r15 = value; }
285
286
private:
287
struct GPRs {
288
uint64_t __rax;
289
uint64_t __rbx;
290
uint64_t __rcx;
291
uint64_t __rdx;
292
uint64_t __rdi;
293
uint64_t __rsi;
294
uint64_t __rbp;
295
uint64_t __rsp;
296
uint64_t __r8;
297
uint64_t __r9;
298
uint64_t __r10;
299
uint64_t __r11;
300
uint64_t __r12;
301
uint64_t __r13;
302
uint64_t __r14;
303
uint64_t __r15;
304
uint64_t __rip;
305
uint64_t __rflags;
306
uint64_t __cs;
307
uint64_t __fs;
308
uint64_t __gs;
309
#if defined(_WIN64)
310
uint64_t __padding; // 16-byte align
311
#endif
312
};
313
GPRs _registers;
314
#if defined(_WIN64)
315
v128 _xmm[16];
316
#endif
317
};
318
319
inline Registers_x86_64::Registers_x86_64(const void *registers) {
320
static_assert((check_fit<Registers_x86_64, unw_context_t>::does_fit),
321
"x86_64 registers do not fit into unw_context_t");
322
memcpy(&_registers, registers, sizeof(_registers));
323
}
324
325
inline Registers_x86_64::Registers_x86_64() {
326
memset(&_registers, 0, sizeof(_registers));
327
}
328
329
inline bool Registers_x86_64::validRegister(int regNum) const {
330
if (regNum == UNW_REG_IP)
331
return true;
332
if (regNum == UNW_REG_SP)
333
return true;
334
if (regNum < 0)
335
return false;
336
if (regNum > 15)
337
return false;
338
return true;
339
}
340
341
inline uint64_t Registers_x86_64::getRegister(int regNum) const {
342
switch (regNum) {
343
case UNW_REG_IP:
344
return _registers.__rip;
345
case UNW_REG_SP:
346
return _registers.__rsp;
347
case UNW_X86_64_RAX:
348
return _registers.__rax;
349
case UNW_X86_64_RDX:
350
return _registers.__rdx;
351
case UNW_X86_64_RCX:
352
return _registers.__rcx;
353
case UNW_X86_64_RBX:
354
return _registers.__rbx;
355
case UNW_X86_64_RSI:
356
return _registers.__rsi;
357
case UNW_X86_64_RDI:
358
return _registers.__rdi;
359
case UNW_X86_64_RBP:
360
return _registers.__rbp;
361
case UNW_X86_64_RSP:
362
return _registers.__rsp;
363
case UNW_X86_64_R8:
364
return _registers.__r8;
365
case UNW_X86_64_R9:
366
return _registers.__r9;
367
case UNW_X86_64_R10:
368
return _registers.__r10;
369
case UNW_X86_64_R11:
370
return _registers.__r11;
371
case UNW_X86_64_R12:
372
return _registers.__r12;
373
case UNW_X86_64_R13:
374
return _registers.__r13;
375
case UNW_X86_64_R14:
376
return _registers.__r14;
377
case UNW_X86_64_R15:
378
return _registers.__r15;
379
}
380
_LIBUNWIND_ABORT("unsupported x86_64 register");
381
}
382
383
inline void Registers_x86_64::setRegister(int regNum, uint64_t value) {
384
switch (regNum) {
385
case UNW_REG_IP:
386
_registers.__rip = value;
387
return;
388
case UNW_REG_SP:
389
_registers.__rsp = value;
390
return;
391
case UNW_X86_64_RAX:
392
_registers.__rax = value;
393
return;
394
case UNW_X86_64_RDX:
395
_registers.__rdx = value;
396
return;
397
case UNW_X86_64_RCX:
398
_registers.__rcx = value;
399
return;
400
case UNW_X86_64_RBX:
401
_registers.__rbx = value;
402
return;
403
case UNW_X86_64_RSI:
404
_registers.__rsi = value;
405
return;
406
case UNW_X86_64_RDI:
407
_registers.__rdi = value;
408
return;
409
case UNW_X86_64_RBP:
410
_registers.__rbp = value;
411
return;
412
case UNW_X86_64_RSP:
413
_registers.__rsp = value;
414
return;
415
case UNW_X86_64_R8:
416
_registers.__r8 = value;
417
return;
418
case UNW_X86_64_R9:
419
_registers.__r9 = value;
420
return;
421
case UNW_X86_64_R10:
422
_registers.__r10 = value;
423
return;
424
case UNW_X86_64_R11:
425
_registers.__r11 = value;
426
return;
427
case UNW_X86_64_R12:
428
_registers.__r12 = value;
429
return;
430
case UNW_X86_64_R13:
431
_registers.__r13 = value;
432
return;
433
case UNW_X86_64_R14:
434
_registers.__r14 = value;
435
return;
436
case UNW_X86_64_R15:
437
_registers.__r15 = value;
438
return;
439
}
440
_LIBUNWIND_ABORT("unsupported x86_64 register");
441
}
442
443
inline const char *Registers_x86_64::getRegisterName(int regNum) {
444
switch (regNum) {
445
case UNW_REG_IP:
446
return "rip";
447
case UNW_REG_SP:
448
return "rsp";
449
case UNW_X86_64_RAX:
450
return "rax";
451
case UNW_X86_64_RDX:
452
return "rdx";
453
case UNW_X86_64_RCX:
454
return "rcx";
455
case UNW_X86_64_RBX:
456
return "rbx";
457
case UNW_X86_64_RSI:
458
return "rsi";
459
case UNW_X86_64_RDI:
460
return "rdi";
461
case UNW_X86_64_RBP:
462
return "rbp";
463
case UNW_X86_64_RSP:
464
return "rsp";
465
case UNW_X86_64_R8:
466
return "r8";
467
case UNW_X86_64_R9:
468
return "r9";
469
case UNW_X86_64_R10:
470
return "r10";
471
case UNW_X86_64_R11:
472
return "r11";
473
case UNW_X86_64_R12:
474
return "r12";
475
case UNW_X86_64_R13:
476
return "r13";
477
case UNW_X86_64_R14:
478
return "r14";
479
case UNW_X86_64_R15:
480
return "r15";
481
case UNW_X86_64_XMM0:
482
return "xmm0";
483
case UNW_X86_64_XMM1:
484
return "xmm1";
485
case UNW_X86_64_XMM2:
486
return "xmm2";
487
case UNW_X86_64_XMM3:
488
return "xmm3";
489
case UNW_X86_64_XMM4:
490
return "xmm4";
491
case UNW_X86_64_XMM5:
492
return "xmm5";
493
case UNW_X86_64_XMM6:
494
return "xmm6";
495
case UNW_X86_64_XMM7:
496
return "xmm7";
497
case UNW_X86_64_XMM8:
498
return "xmm8";
499
case UNW_X86_64_XMM9:
500
return "xmm9";
501
case UNW_X86_64_XMM10:
502
return "xmm10";
503
case UNW_X86_64_XMM11:
504
return "xmm11";
505
case UNW_X86_64_XMM12:
506
return "xmm12";
507
case UNW_X86_64_XMM13:
508
return "xmm13";
509
case UNW_X86_64_XMM14:
510
return "xmm14";
511
case UNW_X86_64_XMM15:
512
return "xmm15";
513
default:
514
return "unknown register";
515
}
516
}
517
518
inline double Registers_x86_64::getFloatRegister(int) const {
519
_LIBUNWIND_ABORT("no x86_64 float registers");
520
}
521
522
inline void Registers_x86_64::setFloatRegister(int, double) {
523
_LIBUNWIND_ABORT("no x86_64 float registers");
524
}
525
526
inline bool Registers_x86_64::validVectorRegister(int regNum) const {
527
#if defined(_WIN64)
528
if (regNum < UNW_X86_64_XMM0)
529
return false;
530
if (regNum > UNW_X86_64_XMM15)
531
return false;
532
return true;
533
#else
534
(void)regNum; // suppress unused parameter warning
535
return false;
536
#endif
537
}
538
539
inline v128 Registers_x86_64::getVectorRegister(int regNum) const {
540
#if defined(_WIN64)
541
assert(validVectorRegister(regNum));
542
return _xmm[regNum - UNW_X86_64_XMM0];
543
#else
544
(void)regNum; // suppress unused parameter warning
545
_LIBUNWIND_ABORT("no x86_64 vector registers");
546
#endif
547
}
548
549
inline void Registers_x86_64::setVectorRegister(int regNum, v128 value) {
550
#if defined(_WIN64)
551
assert(validVectorRegister(regNum));
552
_xmm[regNum - UNW_X86_64_XMM0] = value;
553
#else
554
(void)regNum; (void)value; // suppress unused parameter warnings
555
_LIBUNWIND_ABORT("no x86_64 vector registers");
556
#endif
557
}
558
#endif // _LIBUNWIND_TARGET_X86_64
559
560
561
#if defined(_LIBUNWIND_TARGET_PPC)
562
/// Registers_ppc holds the register state of a thread in a 32-bit PowerPC
563
/// process.
564
class _LIBUNWIND_HIDDEN Registers_ppc {
565
public:
566
Registers_ppc();
567
Registers_ppc(const void *registers);
568
569
bool validRegister(int num) const;
570
uint32_t getRegister(int num) const;
571
void setRegister(int num, uint32_t value);
572
bool validFloatRegister(int num) const;
573
double getFloatRegister(int num) const;
574
void setFloatRegister(int num, double value);
575
bool validVectorRegister(int num) const;
576
v128 getVectorRegister(int num) const;
577
void setVectorRegister(int num, v128 value);
578
static const char *getRegisterName(int num);
579
void jumpto();
580
static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC; }
581
static int getArch() { return REGISTERS_PPC; }
582
583
uint64_t getSP() const { return _registers.__r1; }
584
void setSP(uint32_t value) { _registers.__r1 = value; }
585
uint64_t getIP() const { return _registers.__srr0; }
586
void setIP(uint32_t value) { _registers.__srr0 = value; }
587
588
private:
589
struct ppc_thread_state_t {
590
unsigned int __srr0; /* Instruction address register (PC) */
591
unsigned int __srr1; /* Machine state register (supervisor) */
592
unsigned int __r0;
593
unsigned int __r1;
594
unsigned int __r2;
595
unsigned int __r3;
596
unsigned int __r4;
597
unsigned int __r5;
598
unsigned int __r6;
599
unsigned int __r7;
600
unsigned int __r8;
601
unsigned int __r9;
602
unsigned int __r10;
603
unsigned int __r11;
604
unsigned int __r12;
605
unsigned int __r13;
606
unsigned int __r14;
607
unsigned int __r15;
608
unsigned int __r16;
609
unsigned int __r17;
610
unsigned int __r18;
611
unsigned int __r19;
612
unsigned int __r20;
613
unsigned int __r21;
614
unsigned int __r22;
615
unsigned int __r23;
616
unsigned int __r24;
617
unsigned int __r25;
618
unsigned int __r26;
619
unsigned int __r27;
620
unsigned int __r28;
621
unsigned int __r29;
622
unsigned int __r30;
623
unsigned int __r31;
624
unsigned int __cr; /* Condition register */
625
unsigned int __xer; /* User's integer exception register */
626
unsigned int __lr; /* Link register */
627
unsigned int __ctr; /* Count register */
628
unsigned int __mq; /* MQ register (601 only) */
629
unsigned int __vrsave; /* Vector Save Register */
630
};
631
632
struct ppc_float_state_t {
633
double __fpregs[32];
634
635
unsigned int __fpscr_pad; /* fpscr is 64 bits, 32 bits of rubbish */
636
unsigned int __fpscr; /* floating point status register */
637
};
638
639
ppc_thread_state_t _registers;
640
ppc_float_state_t _floatRegisters;
641
v128 _vectorRegisters[32]; // offset 424
642
};
643
644
inline Registers_ppc::Registers_ppc(const void *registers) {
645
static_assert((check_fit<Registers_ppc, unw_context_t>::does_fit),
646
"ppc registers do not fit into unw_context_t");
647
memcpy(&_registers, static_cast<const uint8_t *>(registers),
648
sizeof(_registers));
649
static_assert(sizeof(ppc_thread_state_t) == 160,
650
"expected float register offset to be 160");
651
memcpy(&_floatRegisters,
652
static_cast<const uint8_t *>(registers) + sizeof(ppc_thread_state_t),
653
sizeof(_floatRegisters));
654
static_assert(sizeof(ppc_thread_state_t) + sizeof(ppc_float_state_t) == 424,
655
"expected vector register offset to be 424 bytes");
656
memcpy(_vectorRegisters,
657
static_cast<const uint8_t *>(registers) + sizeof(ppc_thread_state_t) +
658
sizeof(ppc_float_state_t),
659
sizeof(_vectorRegisters));
660
}
661
662
inline Registers_ppc::Registers_ppc() {
663
memset(&_registers, 0, sizeof(_registers));
664
memset(&_floatRegisters, 0, sizeof(_floatRegisters));
665
memset(&_vectorRegisters, 0, sizeof(_vectorRegisters));
666
}
667
668
inline bool Registers_ppc::validRegister(int regNum) const {
669
if (regNum == UNW_REG_IP)
670
return true;
671
if (regNum == UNW_REG_SP)
672
return true;
673
if (regNum == UNW_PPC_VRSAVE)
674
return true;
675
if (regNum < 0)
676
return false;
677
if (regNum <= UNW_PPC_R31)
678
return true;
679
if (regNum == UNW_PPC_MQ)
680
return true;
681
if (regNum == UNW_PPC_LR)
682
return true;
683
if (regNum == UNW_PPC_CTR)
684
return true;
685
if ((UNW_PPC_CR0 <= regNum) && (regNum <= UNW_PPC_CR7))
686
return true;
687
return false;
688
}
689
690
inline uint32_t Registers_ppc::getRegister(int regNum) const {
691
switch (regNum) {
692
case UNW_REG_IP:
693
return _registers.__srr0;
694
case UNW_REG_SP:
695
return _registers.__r1;
696
case UNW_PPC_R0:
697
return _registers.__r0;
698
case UNW_PPC_R1:
699
return _registers.__r1;
700
case UNW_PPC_R2:
701
return _registers.__r2;
702
case UNW_PPC_R3:
703
return _registers.__r3;
704
case UNW_PPC_R4:
705
return _registers.__r4;
706
case UNW_PPC_R5:
707
return _registers.__r5;
708
case UNW_PPC_R6:
709
return _registers.__r6;
710
case UNW_PPC_R7:
711
return _registers.__r7;
712
case UNW_PPC_R8:
713
return _registers.__r8;
714
case UNW_PPC_R9:
715
return _registers.__r9;
716
case UNW_PPC_R10:
717
return _registers.__r10;
718
case UNW_PPC_R11:
719
return _registers.__r11;
720
case UNW_PPC_R12:
721
return _registers.__r12;
722
case UNW_PPC_R13:
723
return _registers.__r13;
724
case UNW_PPC_R14:
725
return _registers.__r14;
726
case UNW_PPC_R15:
727
return _registers.__r15;
728
case UNW_PPC_R16:
729
return _registers.__r16;
730
case UNW_PPC_R17:
731
return _registers.__r17;
732
case UNW_PPC_R18:
733
return _registers.__r18;
734
case UNW_PPC_R19:
735
return _registers.__r19;
736
case UNW_PPC_R20:
737
return _registers.__r20;
738
case UNW_PPC_R21:
739
return _registers.__r21;
740
case UNW_PPC_R22:
741
return _registers.__r22;
742
case UNW_PPC_R23:
743
return _registers.__r23;
744
case UNW_PPC_R24:
745
return _registers.__r24;
746
case UNW_PPC_R25:
747
return _registers.__r25;
748
case UNW_PPC_R26:
749
return _registers.__r26;
750
case UNW_PPC_R27:
751
return _registers.__r27;
752
case UNW_PPC_R28:
753
return _registers.__r28;
754
case UNW_PPC_R29:
755
return _registers.__r29;
756
case UNW_PPC_R30:
757
return _registers.__r30;
758
case UNW_PPC_R31:
759
return _registers.__r31;
760
case UNW_PPC_LR:
761
return _registers.__lr;
762
case UNW_PPC_CR0:
763
return (_registers.__cr & 0xF0000000);
764
case UNW_PPC_CR1:
765
return (_registers.__cr & 0x0F000000);
766
case UNW_PPC_CR2:
767
return (_registers.__cr & 0x00F00000);
768
case UNW_PPC_CR3:
769
return (_registers.__cr & 0x000F0000);
770
case UNW_PPC_CR4:
771
return (_registers.__cr & 0x0000F000);
772
case UNW_PPC_CR5:
773
return (_registers.__cr & 0x00000F00);
774
case UNW_PPC_CR6:
775
return (_registers.__cr & 0x000000F0);
776
case UNW_PPC_CR7:
777
return (_registers.__cr & 0x0000000F);
778
case UNW_PPC_VRSAVE:
779
return _registers.__vrsave;
780
}
781
_LIBUNWIND_ABORT("unsupported ppc register");
782
}
783
784
inline void Registers_ppc::setRegister(int regNum, uint32_t value) {
785
//fprintf(stderr, "Registers_ppc::setRegister(%d, 0x%08X)\n", regNum, value);
786
switch (regNum) {
787
case UNW_REG_IP:
788
_registers.__srr0 = value;
789
return;
790
case UNW_REG_SP:
791
_registers.__r1 = value;
792
return;
793
case UNW_PPC_R0:
794
_registers.__r0 = value;
795
return;
796
case UNW_PPC_R1:
797
_registers.__r1 = value;
798
return;
799
case UNW_PPC_R2:
800
_registers.__r2 = value;
801
return;
802
case UNW_PPC_R3:
803
_registers.__r3 = value;
804
return;
805
case UNW_PPC_R4:
806
_registers.__r4 = value;
807
return;
808
case UNW_PPC_R5:
809
_registers.__r5 = value;
810
return;
811
case UNW_PPC_R6:
812
_registers.__r6 = value;
813
return;
814
case UNW_PPC_R7:
815
_registers.__r7 = value;
816
return;
817
case UNW_PPC_R8:
818
_registers.__r8 = value;
819
return;
820
case UNW_PPC_R9:
821
_registers.__r9 = value;
822
return;
823
case UNW_PPC_R10:
824
_registers.__r10 = value;
825
return;
826
case UNW_PPC_R11:
827
_registers.__r11 = value;
828
return;
829
case UNW_PPC_R12:
830
_registers.__r12 = value;
831
return;
832
case UNW_PPC_R13:
833
_registers.__r13 = value;
834
return;
835
case UNW_PPC_R14:
836
_registers.__r14 = value;
837
return;
838
case UNW_PPC_R15:
839
_registers.__r15 = value;
840
return;
841
case UNW_PPC_R16:
842
_registers.__r16 = value;
843
return;
844
case UNW_PPC_R17:
845
_registers.__r17 = value;
846
return;
847
case UNW_PPC_R18:
848
_registers.__r18 = value;
849
return;
850
case UNW_PPC_R19:
851
_registers.__r19 = value;
852
return;
853
case UNW_PPC_R20:
854
_registers.__r20 = value;
855
return;
856
case UNW_PPC_R21:
857
_registers.__r21 = value;
858
return;
859
case UNW_PPC_R22:
860
_registers.__r22 = value;
861
return;
862
case UNW_PPC_R23:
863
_registers.__r23 = value;
864
return;
865
case UNW_PPC_R24:
866
_registers.__r24 = value;
867
return;
868
case UNW_PPC_R25:
869
_registers.__r25 = value;
870
return;
871
case UNW_PPC_R26:
872
_registers.__r26 = value;
873
return;
874
case UNW_PPC_R27:
875
_registers.__r27 = value;
876
return;
877
case UNW_PPC_R28:
878
_registers.__r28 = value;
879
return;
880
case UNW_PPC_R29:
881
_registers.__r29 = value;
882
return;
883
case UNW_PPC_R30:
884
_registers.__r30 = value;
885
return;
886
case UNW_PPC_R31:
887
_registers.__r31 = value;
888
return;
889
case UNW_PPC_MQ:
890
_registers.__mq = value;
891
return;
892
case UNW_PPC_LR:
893
_registers.__lr = value;
894
return;
895
case UNW_PPC_CTR:
896
_registers.__ctr = value;
897
return;
898
case UNW_PPC_CR0:
899
_registers.__cr &= 0x0FFFFFFF;
900
_registers.__cr |= (value & 0xF0000000);
901
return;
902
case UNW_PPC_CR1:
903
_registers.__cr &= 0xF0FFFFFF;
904
_registers.__cr |= (value & 0x0F000000);
905
return;
906
case UNW_PPC_CR2:
907
_registers.__cr &= 0xFF0FFFFF;
908
_registers.__cr |= (value & 0x00F00000);
909
return;
910
case UNW_PPC_CR3:
911
_registers.__cr &= 0xFFF0FFFF;
912
_registers.__cr |= (value & 0x000F0000);
913
return;
914
case UNW_PPC_CR4:
915
_registers.__cr &= 0xFFFF0FFF;
916
_registers.__cr |= (value & 0x0000F000);
917
return;
918
case UNW_PPC_CR5:
919
_registers.__cr &= 0xFFFFF0FF;
920
_registers.__cr |= (value & 0x00000F00);
921
return;
922
case UNW_PPC_CR6:
923
_registers.__cr &= 0xFFFFFF0F;
924
_registers.__cr |= (value & 0x000000F0);
925
return;
926
case UNW_PPC_CR7:
927
_registers.__cr &= 0xFFFFFFF0;
928
_registers.__cr |= (value & 0x0000000F);
929
return;
930
case UNW_PPC_VRSAVE:
931
_registers.__vrsave = value;
932
return;
933
// not saved
934
return;
935
case UNW_PPC_XER:
936
_registers.__xer = value;
937
return;
938
case UNW_PPC_AP:
939
case UNW_PPC_VSCR:
940
case UNW_PPC_SPEFSCR:
941
// not saved
942
return;
943
}
944
_LIBUNWIND_ABORT("unsupported ppc register");
945
}
946
947
inline bool Registers_ppc::validFloatRegister(int regNum) const {
948
if (regNum < UNW_PPC_F0)
949
return false;
950
if (regNum > UNW_PPC_F31)
951
return false;
952
return true;
953
}
954
955
inline double Registers_ppc::getFloatRegister(int regNum) const {
956
assert(validFloatRegister(regNum));
957
return _floatRegisters.__fpregs[regNum - UNW_PPC_F0];
958
}
959
960
inline void Registers_ppc::setFloatRegister(int regNum, double value) {
961
assert(validFloatRegister(regNum));
962
_floatRegisters.__fpregs[regNum - UNW_PPC_F0] = value;
963
}
964
965
inline bool Registers_ppc::validVectorRegister(int regNum) const {
966
if (regNum < UNW_PPC_V0)
967
return false;
968
if (regNum > UNW_PPC_V31)
969
return false;
970
return true;
971
}
972
973
inline v128 Registers_ppc::getVectorRegister(int regNum) const {
974
assert(validVectorRegister(regNum));
975
v128 result = _vectorRegisters[regNum - UNW_PPC_V0];
976
return result;
977
}
978
979
inline void Registers_ppc::setVectorRegister(int regNum, v128 value) {
980
assert(validVectorRegister(regNum));
981
_vectorRegisters[regNum - UNW_PPC_V0] = value;
982
}
983
984
inline const char *Registers_ppc::getRegisterName(int regNum) {
985
switch (regNum) {
986
case UNW_REG_IP:
987
return "ip";
988
case UNW_REG_SP:
989
return "sp";
990
case UNW_PPC_R0:
991
return "r0";
992
case UNW_PPC_R1:
993
return "r1";
994
case UNW_PPC_R2:
995
return "r2";
996
case UNW_PPC_R3:
997
return "r3";
998
case UNW_PPC_R4:
999
return "r4";
1000
case UNW_PPC_R5:
1001
return "r5";
1002
case UNW_PPC_R6:
1003
return "r6";
1004
case UNW_PPC_R7:
1005
return "r7";
1006
case UNW_PPC_R8:
1007
return "r8";
1008
case UNW_PPC_R9:
1009
return "r9";
1010
case UNW_PPC_R10:
1011
return "r10";
1012
case UNW_PPC_R11:
1013
return "r11";
1014
case UNW_PPC_R12:
1015
return "r12";
1016
case UNW_PPC_R13:
1017
return "r13";
1018
case UNW_PPC_R14:
1019
return "r14";
1020
case UNW_PPC_R15:
1021
return "r15";
1022
case UNW_PPC_R16:
1023
return "r16";
1024
case UNW_PPC_R17:
1025
return "r17";
1026
case UNW_PPC_R18:
1027
return "r18";
1028
case UNW_PPC_R19:
1029
return "r19";
1030
case UNW_PPC_R20:
1031
return "r20";
1032
case UNW_PPC_R21:
1033
return "r21";
1034
case UNW_PPC_R22:
1035
return "r22";
1036
case UNW_PPC_R23:
1037
return "r23";
1038
case UNW_PPC_R24:
1039
return "r24";
1040
case UNW_PPC_R25:
1041
return "r25";
1042
case UNW_PPC_R26:
1043
return "r26";
1044
case UNW_PPC_R27:
1045
return "r27";
1046
case UNW_PPC_R28:
1047
return "r28";
1048
case UNW_PPC_R29:
1049
return "r29";
1050
case UNW_PPC_R30:
1051
return "r30";
1052
case UNW_PPC_R31:
1053
return "r31";
1054
case UNW_PPC_F0:
1055
return "fp0";
1056
case UNW_PPC_F1:
1057
return "fp1";
1058
case UNW_PPC_F2:
1059
return "fp2";
1060
case UNW_PPC_F3:
1061
return "fp3";
1062
case UNW_PPC_F4:
1063
return "fp4";
1064
case UNW_PPC_F5:
1065
return "fp5";
1066
case UNW_PPC_F6:
1067
return "fp6";
1068
case UNW_PPC_F7:
1069
return "fp7";
1070
case UNW_PPC_F8:
1071
return "fp8";
1072
case UNW_PPC_F9:
1073
return "fp9";
1074
case UNW_PPC_F10:
1075
return "fp10";
1076
case UNW_PPC_F11:
1077
return "fp11";
1078
case UNW_PPC_F12:
1079
return "fp12";
1080
case UNW_PPC_F13:
1081
return "fp13";
1082
case UNW_PPC_F14:
1083
return "fp14";
1084
case UNW_PPC_F15:
1085
return "fp15";
1086
case UNW_PPC_F16:
1087
return "fp16";
1088
case UNW_PPC_F17:
1089
return "fp17";
1090
case UNW_PPC_F18:
1091
return "fp18";
1092
case UNW_PPC_F19:
1093
return "fp19";
1094
case UNW_PPC_F20:
1095
return "fp20";
1096
case UNW_PPC_F21:
1097
return "fp21";
1098
case UNW_PPC_F22:
1099
return "fp22";
1100
case UNW_PPC_F23:
1101
return "fp23";
1102
case UNW_PPC_F24:
1103
return "fp24";
1104
case UNW_PPC_F25:
1105
return "fp25";
1106
case UNW_PPC_F26:
1107
return "fp26";
1108
case UNW_PPC_F27:
1109
return "fp27";
1110
case UNW_PPC_F28:
1111
return "fp28";
1112
case UNW_PPC_F29:
1113
return "fp29";
1114
case UNW_PPC_F30:
1115
return "fp30";
1116
case UNW_PPC_F31:
1117
return "fp31";
1118
case UNW_PPC_LR:
1119
return "lr";
1120
default:
1121
return "unknown register";
1122
}
1123
1124
}
1125
#endif // _LIBUNWIND_TARGET_PPC
1126
1127
#if defined(_LIBUNWIND_TARGET_PPC64)
1128
/// Registers_ppc64 holds the register state of a thread in a 64-bit PowerPC
1129
/// process.
1130
class _LIBUNWIND_HIDDEN Registers_ppc64 {
1131
public:
1132
Registers_ppc64();
1133
Registers_ppc64(const void *registers);
1134
1135
bool validRegister(int num) const;
1136
uint64_t getRegister(int num) const;
1137
void setRegister(int num, uint64_t value);
1138
bool validFloatRegister(int num) const;
1139
double getFloatRegister(int num) const;
1140
void setFloatRegister(int num, double value);
1141
bool validVectorRegister(int num) const;
1142
v128 getVectorRegister(int num) const;
1143
void setVectorRegister(int num, v128 value);
1144
static const char *getRegisterName(int num);
1145
void jumpto();
1146
static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC64; }
1147
static int getArch() { return REGISTERS_PPC64; }
1148
1149
uint64_t getSP() const { return _registers.__r1; }
1150
void setSP(uint64_t value) { _registers.__r1 = value; }
1151
uint64_t getIP() const { return _registers.__srr0; }
1152
void setIP(uint64_t value) { _registers.__srr0 = value; }
1153
1154
private:
1155
struct ppc64_thread_state_t {
1156
uint64_t __srr0; // Instruction address register (PC)
1157
uint64_t __srr1; // Machine state register (supervisor)
1158
uint64_t __r0;
1159
uint64_t __r1;
1160
uint64_t __r2;
1161
uint64_t __r3;
1162
uint64_t __r4;
1163
uint64_t __r5;
1164
uint64_t __r6;
1165
uint64_t __r7;
1166
uint64_t __r8;
1167
uint64_t __r9;
1168
uint64_t __r10;
1169
uint64_t __r11;
1170
uint64_t __r12;
1171
uint64_t __r13;
1172
uint64_t __r14;
1173
uint64_t __r15;
1174
uint64_t __r16;
1175
uint64_t __r17;
1176
uint64_t __r18;
1177
uint64_t __r19;
1178
uint64_t __r20;
1179
uint64_t __r21;
1180
uint64_t __r22;
1181
uint64_t __r23;
1182
uint64_t __r24;
1183
uint64_t __r25;
1184
uint64_t __r26;
1185
uint64_t __r27;
1186
uint64_t __r28;
1187
uint64_t __r29;
1188
uint64_t __r30;
1189
uint64_t __r31;
1190
uint64_t __cr; // Condition register
1191
uint64_t __xer; // User's integer exception register
1192
uint64_t __lr; // Link register
1193
uint64_t __ctr; // Count register
1194
uint64_t __vrsave; // Vector Save Register
1195
};
1196
1197
union ppc64_vsr_t {
1198
struct asfloat_s {
1199
double f;
1200
uint64_t v2;
1201
} asfloat;
1202
v128 v;
1203
};
1204
1205
ppc64_thread_state_t _registers;
1206
ppc64_vsr_t _vectorScalarRegisters[64];
1207
1208
static int getVectorRegNum(int num);
1209
};
1210
1211
inline Registers_ppc64::Registers_ppc64(const void *registers) {
1212
static_assert((check_fit<Registers_ppc64, unw_context_t>::does_fit),
1213
"ppc64 registers do not fit into unw_context_t");
1214
memcpy(&_registers, static_cast<const uint8_t *>(registers),
1215
sizeof(_registers));
1216
static_assert(sizeof(_registers) == 312,
1217
"expected vector scalar register offset to be 312");
1218
memcpy(&_vectorScalarRegisters,
1219
static_cast<const uint8_t *>(registers) + sizeof(_registers),
1220
sizeof(_vectorScalarRegisters));
1221
static_assert(sizeof(_registers) +
1222
sizeof(_vectorScalarRegisters) == 1336,
1223
"expected vector register offset to be 1336 bytes");
1224
}
1225
1226
inline Registers_ppc64::Registers_ppc64() {
1227
memset(&_registers, 0, sizeof(_registers));
1228
memset(&_vectorScalarRegisters, 0, sizeof(_vectorScalarRegisters));
1229
}
1230
1231
inline bool Registers_ppc64::validRegister(int regNum) const {
1232
switch (regNum) {
1233
case UNW_REG_IP:
1234
case UNW_REG_SP:
1235
case UNW_PPC64_XER:
1236
case UNW_PPC64_LR:
1237
case UNW_PPC64_CTR:
1238
case UNW_PPC64_VRSAVE:
1239
return true;
1240
}
1241
1242
if (regNum >= UNW_PPC64_R0 && regNum <= UNW_PPC64_R31)
1243
return true;
1244
if (regNum >= UNW_PPC64_CR0 && regNum <= UNW_PPC64_CR7)
1245
return true;
1246
1247
return false;
1248
}
1249
1250
inline uint64_t Registers_ppc64::getRegister(int regNum) const {
1251
switch (regNum) {
1252
case UNW_REG_IP:
1253
return _registers.__srr0;
1254
case UNW_PPC64_R0:
1255
return _registers.__r0;
1256
case UNW_PPC64_R1:
1257
case UNW_REG_SP:
1258
return _registers.__r1;
1259
case UNW_PPC64_R2:
1260
return _registers.__r2;
1261
case UNW_PPC64_R3:
1262
return _registers.__r3;
1263
case UNW_PPC64_R4:
1264
return _registers.__r4;
1265
case UNW_PPC64_R5:
1266
return _registers.__r5;
1267
case UNW_PPC64_R6:
1268
return _registers.__r6;
1269
case UNW_PPC64_R7:
1270
return _registers.__r7;
1271
case UNW_PPC64_R8:
1272
return _registers.__r8;
1273
case UNW_PPC64_R9:
1274
return _registers.__r9;
1275
case UNW_PPC64_R10:
1276
return _registers.__r10;
1277
case UNW_PPC64_R11:
1278
return _registers.__r11;
1279
case UNW_PPC64_R12:
1280
return _registers.__r12;
1281
case UNW_PPC64_R13:
1282
return _registers.__r13;
1283
case UNW_PPC64_R14:
1284
return _registers.__r14;
1285
case UNW_PPC64_R15:
1286
return _registers.__r15;
1287
case UNW_PPC64_R16:
1288
return _registers.__r16;
1289
case UNW_PPC64_R17:
1290
return _registers.__r17;
1291
case UNW_PPC64_R18:
1292
return _registers.__r18;
1293
case UNW_PPC64_R19:
1294
return _registers.__r19;
1295
case UNW_PPC64_R20:
1296
return _registers.__r20;
1297
case UNW_PPC64_R21:
1298
return _registers.__r21;
1299
case UNW_PPC64_R22:
1300
return _registers.__r22;
1301
case UNW_PPC64_R23:
1302
return _registers.__r23;
1303
case UNW_PPC64_R24:
1304
return _registers.__r24;
1305
case UNW_PPC64_R25:
1306
return _registers.__r25;
1307
case UNW_PPC64_R26:
1308
return _registers.__r26;
1309
case UNW_PPC64_R27:
1310
return _registers.__r27;
1311
case UNW_PPC64_R28:
1312
return _registers.__r28;
1313
case UNW_PPC64_R29:
1314
return _registers.__r29;
1315
case UNW_PPC64_R30:
1316
return _registers.__r30;
1317
case UNW_PPC64_R31:
1318
return _registers.__r31;
1319
case UNW_PPC64_CR0:
1320
return (_registers.__cr & 0xF0000000);
1321
case UNW_PPC64_CR1:
1322
return (_registers.__cr & 0x0F000000);
1323
case UNW_PPC64_CR2:
1324
return (_registers.__cr & 0x00F00000);
1325
case UNW_PPC64_CR3:
1326
return (_registers.__cr & 0x000F0000);
1327
case UNW_PPC64_CR4:
1328
return (_registers.__cr & 0x0000F000);
1329
case UNW_PPC64_CR5:
1330
return (_registers.__cr & 0x00000F00);
1331
case UNW_PPC64_CR6:
1332
return (_registers.__cr & 0x000000F0);
1333
case UNW_PPC64_CR7:
1334
return (_registers.__cr & 0x0000000F);
1335
case UNW_PPC64_XER:
1336
return _registers.__xer;
1337
case UNW_PPC64_LR:
1338
return _registers.__lr;
1339
case UNW_PPC64_CTR:
1340
return _registers.__ctr;
1341
case UNW_PPC64_VRSAVE:
1342
return _registers.__vrsave;
1343
}
1344
_LIBUNWIND_ABORT("unsupported ppc64 register");
1345
}
1346
1347
inline void Registers_ppc64::setRegister(int regNum, uint64_t value) {
1348
switch (regNum) {
1349
case UNW_REG_IP:
1350
_registers.__srr0 = value;
1351
return;
1352
case UNW_PPC64_R0:
1353
_registers.__r0 = value;
1354
return;
1355
case UNW_PPC64_R1:
1356
case UNW_REG_SP:
1357
_registers.__r1 = value;
1358
return;
1359
case UNW_PPC64_R2:
1360
_registers.__r2 = value;
1361
return;
1362
case UNW_PPC64_R3:
1363
_registers.__r3 = value;
1364
return;
1365
case UNW_PPC64_R4:
1366
_registers.__r4 = value;
1367
return;
1368
case UNW_PPC64_R5:
1369
_registers.__r5 = value;
1370
return;
1371
case UNW_PPC64_R6:
1372
_registers.__r6 = value;
1373
return;
1374
case UNW_PPC64_R7:
1375
_registers.__r7 = value;
1376
return;
1377
case UNW_PPC64_R8:
1378
_registers.__r8 = value;
1379
return;
1380
case UNW_PPC64_R9:
1381
_registers.__r9 = value;
1382
return;
1383
case UNW_PPC64_R10:
1384
_registers.__r10 = value;
1385
return;
1386
case UNW_PPC64_R11:
1387
_registers.__r11 = value;
1388
return;
1389
case UNW_PPC64_R12:
1390
_registers.__r12 = value;
1391
return;
1392
case UNW_PPC64_R13:
1393
_registers.__r13 = value;
1394
return;
1395
case UNW_PPC64_R14:
1396
_registers.__r14 = value;
1397
return;
1398
case UNW_PPC64_R15:
1399
_registers.__r15 = value;
1400
return;
1401
case UNW_PPC64_R16:
1402
_registers.__r16 = value;
1403
return;
1404
case UNW_PPC64_R17:
1405
_registers.__r17 = value;
1406
return;
1407
case UNW_PPC64_R18:
1408
_registers.__r18 = value;
1409
return;
1410
case UNW_PPC64_R19:
1411
_registers.__r19 = value;
1412
return;
1413
case UNW_PPC64_R20:
1414
_registers.__r20 = value;
1415
return;
1416
case UNW_PPC64_R21:
1417
_registers.__r21 = value;
1418
return;
1419
case UNW_PPC64_R22:
1420
_registers.__r22 = value;
1421
return;
1422
case UNW_PPC64_R23:
1423
_registers.__r23 = value;
1424
return;
1425
case UNW_PPC64_R24:
1426
_registers.__r24 = value;
1427
return;
1428
case UNW_PPC64_R25:
1429
_registers.__r25 = value;
1430
return;
1431
case UNW_PPC64_R26:
1432
_registers.__r26 = value;
1433
return;
1434
case UNW_PPC64_R27:
1435
_registers.__r27 = value;
1436
return;
1437
case UNW_PPC64_R28:
1438
_registers.__r28 = value;
1439
return;
1440
case UNW_PPC64_R29:
1441
_registers.__r29 = value;
1442
return;
1443
case UNW_PPC64_R30:
1444
_registers.__r30 = value;
1445
return;
1446
case UNW_PPC64_R31:
1447
_registers.__r31 = value;
1448
return;
1449
case UNW_PPC64_CR0:
1450
_registers.__cr &= 0x0FFFFFFF;
1451
_registers.__cr |= (value & 0xF0000000);
1452
return;
1453
case UNW_PPC64_CR1:
1454
_registers.__cr &= 0xF0FFFFFF;
1455
_registers.__cr |= (value & 0x0F000000);
1456
return;
1457
case UNW_PPC64_CR2:
1458
_registers.__cr &= 0xFF0FFFFF;
1459
_registers.__cr |= (value & 0x00F00000);
1460
return;
1461
case UNW_PPC64_CR3:
1462
_registers.__cr &= 0xFFF0FFFF;
1463
_registers.__cr |= (value & 0x000F0000);
1464
return;
1465
case UNW_PPC64_CR4:
1466
_registers.__cr &= 0xFFFF0FFF;
1467
_registers.__cr |= (value & 0x0000F000);
1468
return;
1469
case UNW_PPC64_CR5:
1470
_registers.__cr &= 0xFFFFF0FF;
1471
_registers.__cr |= (value & 0x00000F00);
1472
return;
1473
case UNW_PPC64_CR6:
1474
_registers.__cr &= 0xFFFFFF0F;
1475
_registers.__cr |= (value & 0x000000F0);
1476
return;
1477
case UNW_PPC64_CR7:
1478
_registers.__cr &= 0xFFFFFFF0;
1479
_registers.__cr |= (value & 0x0000000F);
1480
return;
1481
case UNW_PPC64_XER:
1482
_registers.__xer = value;
1483
return;
1484
case UNW_PPC64_LR:
1485
_registers.__lr = value;
1486
return;
1487
case UNW_PPC64_CTR:
1488
_registers.__ctr = value;
1489
return;
1490
case UNW_PPC64_VRSAVE:
1491
_registers.__vrsave = value;
1492
return;
1493
}
1494
_LIBUNWIND_ABORT("unsupported ppc64 register");
1495
}
1496
1497
inline bool Registers_ppc64::validFloatRegister(int regNum) const {
1498
return regNum >= UNW_PPC64_F0 && regNum <= UNW_PPC64_F31;
1499
}
1500
1501
inline double Registers_ppc64::getFloatRegister(int regNum) const {
1502
assert(validFloatRegister(regNum));
1503
return _vectorScalarRegisters[regNum - UNW_PPC64_F0].asfloat.f;
1504
}
1505
1506
inline void Registers_ppc64::setFloatRegister(int regNum, double value) {
1507
assert(validFloatRegister(regNum));
1508
_vectorScalarRegisters[regNum - UNW_PPC64_F0].asfloat.f = value;
1509
}
1510
1511
inline bool Registers_ppc64::validVectorRegister(int regNum) const {
1512
#ifdef PPC64_HAS_VMX
1513
if (regNum >= UNW_PPC64_VS0 && regNum <= UNW_PPC64_VS31)
1514
return true;
1515
if (regNum >= UNW_PPC64_VS32 && regNum <= UNW_PPC64_VS63)
1516
return true;
1517
#else
1518
if (regNum >= UNW_PPC64_V0 && regNum <= UNW_PPC64_V31)
1519
return true;
1520
#endif
1521
return false;
1522
}
1523
1524
inline int Registers_ppc64::getVectorRegNum(int num)
1525
{
1526
if (num >= UNW_PPC64_VS0 && num <= UNW_PPC64_VS31)
1527
return num - UNW_PPC64_VS0;
1528
else
1529
return num - UNW_PPC64_VS32 + 32;
1530
}
1531
1532
inline v128 Registers_ppc64::getVectorRegister(int regNum) const {
1533
assert(validVectorRegister(regNum));
1534
return _vectorScalarRegisters[getVectorRegNum(regNum)].v;
1535
}
1536
1537
inline void Registers_ppc64::setVectorRegister(int regNum, v128 value) {
1538
assert(validVectorRegister(regNum));
1539
_vectorScalarRegisters[getVectorRegNum(regNum)].v = value;
1540
}
1541
1542
inline const char *Registers_ppc64::getRegisterName(int regNum) {
1543
switch (regNum) {
1544
case UNW_REG_IP:
1545
return "ip";
1546
case UNW_REG_SP:
1547
return "sp";
1548
case UNW_PPC64_R0:
1549
return "r0";
1550
case UNW_PPC64_R1:
1551
return "r1";
1552
case UNW_PPC64_R2:
1553
return "r2";
1554
case UNW_PPC64_R3:
1555
return "r3";
1556
case UNW_PPC64_R4:
1557
return "r4";
1558
case UNW_PPC64_R5:
1559
return "r5";
1560
case UNW_PPC64_R6:
1561
return "r6";
1562
case UNW_PPC64_R7:
1563
return "r7";
1564
case UNW_PPC64_R8:
1565
return "r8";
1566
case UNW_PPC64_R9:
1567
return "r9";
1568
case UNW_PPC64_R10:
1569
return "r10";
1570
case UNW_PPC64_R11:
1571
return "r11";
1572
case UNW_PPC64_R12:
1573
return "r12";
1574
case UNW_PPC64_R13:
1575
return "r13";
1576
case UNW_PPC64_R14:
1577
return "r14";
1578
case UNW_PPC64_R15:
1579
return "r15";
1580
case UNW_PPC64_R16:
1581
return "r16";
1582
case UNW_PPC64_R17:
1583
return "r17";
1584
case UNW_PPC64_R18:
1585
return "r18";
1586
case UNW_PPC64_R19:
1587
return "r19";
1588
case UNW_PPC64_R20:
1589
return "r20";
1590
case UNW_PPC64_R21:
1591
return "r21";
1592
case UNW_PPC64_R22:
1593
return "r22";
1594
case UNW_PPC64_R23:
1595
return "r23";
1596
case UNW_PPC64_R24:
1597
return "r24";
1598
case UNW_PPC64_R25:
1599
return "r25";
1600
case UNW_PPC64_R26:
1601
return "r26";
1602
case UNW_PPC64_R27:
1603
return "r27";
1604
case UNW_PPC64_R28:
1605
return "r28";
1606
case UNW_PPC64_R29:
1607
return "r29";
1608
case UNW_PPC64_R30:
1609
return "r30";
1610
case UNW_PPC64_R31:
1611
return "r31";
1612
case UNW_PPC64_CR0:
1613
return "cr0";
1614
case UNW_PPC64_CR1:
1615
return "cr1";
1616
case UNW_PPC64_CR2:
1617
return "cr2";
1618
case UNW_PPC64_CR3:
1619
return "cr3";
1620
case UNW_PPC64_CR4:
1621
return "cr4";
1622
case UNW_PPC64_CR5:
1623
return "cr5";
1624
case UNW_PPC64_CR6:
1625
return "cr6";
1626
case UNW_PPC64_CR7:
1627
return "cr7";
1628
case UNW_PPC64_XER:
1629
return "xer";
1630
case UNW_PPC64_LR:
1631
return "lr";
1632
case UNW_PPC64_CTR:
1633
return "ctr";
1634
case UNW_PPC64_VRSAVE:
1635
return "vrsave";
1636
case UNW_PPC64_F0:
1637
return "fp0";
1638
case UNW_PPC64_F1:
1639
return "fp1";
1640
case UNW_PPC64_F2:
1641
return "fp2";
1642
case UNW_PPC64_F3:
1643
return "fp3";
1644
case UNW_PPC64_F4:
1645
return "fp4";
1646
case UNW_PPC64_F5:
1647
return "fp5";
1648
case UNW_PPC64_F6:
1649
return "fp6";
1650
case UNW_PPC64_F7:
1651
return "fp7";
1652
case UNW_PPC64_F8:
1653
return "fp8";
1654
case UNW_PPC64_F9:
1655
return "fp9";
1656
case UNW_PPC64_F10:
1657
return "fp10";
1658
case UNW_PPC64_F11:
1659
return "fp11";
1660
case UNW_PPC64_F12:
1661
return "fp12";
1662
case UNW_PPC64_F13:
1663
return "fp13";
1664
case UNW_PPC64_F14:
1665
return "fp14";
1666
case UNW_PPC64_F15:
1667
return "fp15";
1668
case UNW_PPC64_F16:
1669
return "fp16";
1670
case UNW_PPC64_F17:
1671
return "fp17";
1672
case UNW_PPC64_F18:
1673
return "fp18";
1674
case UNW_PPC64_F19:
1675
return "fp19";
1676
case UNW_PPC64_F20:
1677
return "fp20";
1678
case UNW_PPC64_F21:
1679
return "fp21";
1680
case UNW_PPC64_F22:
1681
return "fp22";
1682
case UNW_PPC64_F23:
1683
return "fp23";
1684
case UNW_PPC64_F24:
1685
return "fp24";
1686
case UNW_PPC64_F25:
1687
return "fp25";
1688
case UNW_PPC64_F26:
1689
return "fp26";
1690
case UNW_PPC64_F27:
1691
return "fp27";
1692
case UNW_PPC64_F28:
1693
return "fp28";
1694
case UNW_PPC64_F29:
1695
return "fp29";
1696
case UNW_PPC64_F30:
1697
return "fp30";
1698
case UNW_PPC64_F31:
1699
return "fp31";
1700
case UNW_PPC64_V0:
1701
return "v0";
1702
case UNW_PPC64_V1:
1703
return "v1";
1704
case UNW_PPC64_V2:
1705
return "v2";
1706
case UNW_PPC64_V3:
1707
return "v3";
1708
case UNW_PPC64_V4:
1709
return "v4";
1710
case UNW_PPC64_V5:
1711
return "v5";
1712
case UNW_PPC64_V6:
1713
return "v6";
1714
case UNW_PPC64_V7:
1715
return "v7";
1716
case UNW_PPC64_V8:
1717
return "v8";
1718
case UNW_PPC64_V9:
1719
return "v9";
1720
case UNW_PPC64_V10:
1721
return "v10";
1722
case UNW_PPC64_V11:
1723
return "v11";
1724
case UNW_PPC64_V12:
1725
return "v12";
1726
case UNW_PPC64_V13:
1727
return "v13";
1728
case UNW_PPC64_V14:
1729
return "v14";
1730
case UNW_PPC64_V15:
1731
return "v15";
1732
case UNW_PPC64_V16:
1733
return "v16";
1734
case UNW_PPC64_V17:
1735
return "v17";
1736
case UNW_PPC64_V18:
1737
return "v18";
1738
case UNW_PPC64_V19:
1739
return "v19";
1740
case UNW_PPC64_V20:
1741
return "v20";
1742
case UNW_PPC64_V21:
1743
return "v21";
1744
case UNW_PPC64_V22:
1745
return "v22";
1746
case UNW_PPC64_V23:
1747
return "v23";
1748
case UNW_PPC64_V24:
1749
return "v24";
1750
case UNW_PPC64_V25:
1751
return "v25";
1752
case UNW_PPC64_V26:
1753
return "v26";
1754
case UNW_PPC64_V27:
1755
return "v27";
1756
case UNW_PPC64_V28:
1757
return "v28";
1758
case UNW_PPC64_V29:
1759
return "v29";
1760
case UNW_PPC64_V30:
1761
return "v30";
1762
case UNW_PPC64_V31:
1763
return "v31";
1764
}
1765
return "unknown register";
1766
}
1767
#endif // _LIBUNWIND_TARGET_PPC64
1768
1769
1770
#if defined(_LIBUNWIND_TARGET_AARCH64)
1771
/// Registers_arm64 holds the register state of a thread in a 64-bit arm
1772
/// process.
1773
class _LIBUNWIND_HIDDEN Registers_arm64 {
1774
public:
1775
Registers_arm64();
1776
Registers_arm64(const void *registers);
1777
1778
bool validRegister(int num) const;
1779
uint64_t getRegister(int num) const;
1780
void setRegister(int num, uint64_t value);
1781
bool validFloatRegister(int num) const;
1782
double getFloatRegister(int num) const;
1783
void setFloatRegister(int num, double value);
1784
bool validVectorRegister(int num) const;
1785
v128 getVectorRegister(int num) const;
1786
void setVectorRegister(int num, v128 value);
1787
static const char *getRegisterName(int num);
1788
void jumpto();
1789
static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64; }
1790
static int getArch() { return REGISTERS_ARM64; }
1791
1792
uint64_t getSP() const { return _registers.__sp; }
1793
void setSP(uint64_t value) { _registers.__sp = value; }
1794
uint64_t getIP() const { return _registers.__pc; }
1795
void setIP(uint64_t value) { _registers.__pc = value; }
1796
uint64_t getFP() const { return _registers.__fp; }
1797
void setFP(uint64_t value) { _registers.__fp = value; }
1798
1799
private:
1800
struct GPRs {
1801
uint64_t __x[29]; // x0-x28
1802
uint64_t __fp; // Frame pointer x29
1803
uint64_t __lr; // Link register x30
1804
uint64_t __sp; // Stack pointer x31
1805
uint64_t __pc; // Program counter
1806
uint64_t __ra_sign_state; // RA sign state register
1807
};
1808
1809
GPRs _registers;
1810
double _vectorHalfRegisters[32];
1811
// Currently only the lower double in 128-bit vectore registers
1812
// is perserved during unwinding. We could define new register
1813
// numbers (> 96) which mean whole vector registers, then this
1814
// struct would need to change to contain whole vector registers.
1815
};
1816
1817
inline Registers_arm64::Registers_arm64(const void *registers) {
1818
static_assert((check_fit<Registers_arm64, unw_context_t>::does_fit),
1819
"arm64 registers do not fit into unw_context_t");
1820
memcpy(&_registers, registers, sizeof(_registers));
1821
static_assert(sizeof(GPRs) == 0x110,
1822
"expected VFP registers to be at offset 272");
1823
memcpy(_vectorHalfRegisters,
1824
static_cast<const uint8_t *>(registers) + sizeof(GPRs),
1825
sizeof(_vectorHalfRegisters));
1826
}
1827
1828
inline Registers_arm64::Registers_arm64() {
1829
memset(&_registers, 0, sizeof(_registers));
1830
memset(&_vectorHalfRegisters, 0, sizeof(_vectorHalfRegisters));
1831
}
1832
1833
inline bool Registers_arm64::validRegister(int regNum) const {
1834
if (regNum == UNW_REG_IP)
1835
return true;
1836
if (regNum == UNW_REG_SP)
1837
return true;
1838
if (regNum < 0)
1839
return false;
1840
if (regNum > 95)
1841
return false;
1842
if (regNum == UNW_ARM64_RA_SIGN_STATE)
1843
return true;
1844
if ((regNum > 31) && (regNum < 64))
1845
return false;
1846
return true;
1847
}
1848
1849
inline uint64_t Registers_arm64::getRegister(int regNum) const {
1850
if (regNum == UNW_REG_IP)
1851
return _registers.__pc;
1852
if (regNum == UNW_REG_SP)
1853
return _registers.__sp;
1854
if (regNum == UNW_ARM64_RA_SIGN_STATE)
1855
return _registers.__ra_sign_state;
1856
if ((regNum >= 0) && (regNum < 32))
1857
return _registers.__x[regNum];
1858
_LIBUNWIND_ABORT("unsupported arm64 register");
1859
}
1860
1861
inline void Registers_arm64::setRegister(int regNum, uint64_t value) {
1862
if (regNum == UNW_REG_IP)
1863
_registers.__pc = value;
1864
else if (regNum == UNW_REG_SP)
1865
_registers.__sp = value;
1866
else if (regNum == UNW_ARM64_RA_SIGN_STATE)
1867
_registers.__ra_sign_state = value;
1868
else if ((regNum >= 0) && (regNum < 32))
1869
_registers.__x[regNum] = value;
1870
else
1871
_LIBUNWIND_ABORT("unsupported arm64 register");
1872
}
1873
1874
inline const char *Registers_arm64::getRegisterName(int regNum) {
1875
switch (regNum) {
1876
case UNW_REG_IP:
1877
return "pc";
1878
case UNW_REG_SP:
1879
return "sp";
1880
case UNW_ARM64_X0:
1881
return "x0";
1882
case UNW_ARM64_X1:
1883
return "x1";
1884
case UNW_ARM64_X2:
1885
return "x2";
1886
case UNW_ARM64_X3:
1887
return "x3";
1888
case UNW_ARM64_X4:
1889
return "x4";
1890
case UNW_ARM64_X5:
1891
return "x5";
1892
case UNW_ARM64_X6:
1893
return "x6";
1894
case UNW_ARM64_X7:
1895
return "x7";
1896
case UNW_ARM64_X8:
1897
return "x8";
1898
case UNW_ARM64_X9:
1899
return "x9";
1900
case UNW_ARM64_X10:
1901
return "x10";
1902
case UNW_ARM64_X11:
1903
return "x11";
1904
case UNW_ARM64_X12:
1905
return "x12";
1906
case UNW_ARM64_X13:
1907
return "x13";
1908
case UNW_ARM64_X14:
1909
return "x14";
1910
case UNW_ARM64_X15:
1911
return "x15";
1912
case UNW_ARM64_X16:
1913
return "x16";
1914
case UNW_ARM64_X17:
1915
return "x17";
1916
case UNW_ARM64_X18:
1917
return "x18";
1918
case UNW_ARM64_X19:
1919
return "x19";
1920
case UNW_ARM64_X20:
1921
return "x20";
1922
case UNW_ARM64_X21:
1923
return "x21";
1924
case UNW_ARM64_X22:
1925
return "x22";
1926
case UNW_ARM64_X23:
1927
return "x23";
1928
case UNW_ARM64_X24:
1929
return "x24";
1930
case UNW_ARM64_X25:
1931
return "x25";
1932
case UNW_ARM64_X26:
1933
return "x26";
1934
case UNW_ARM64_X27:
1935
return "x27";
1936
case UNW_ARM64_X28:
1937
return "x28";
1938
case UNW_ARM64_X29:
1939
return "fp";
1940
case UNW_ARM64_X30:
1941
return "lr";
1942
case UNW_ARM64_X31:
1943
return "sp";
1944
case UNW_ARM64_D0:
1945
return "d0";
1946
case UNW_ARM64_D1:
1947
return "d1";
1948
case UNW_ARM64_D2:
1949
return "d2";
1950
case UNW_ARM64_D3:
1951
return "d3";
1952
case UNW_ARM64_D4:
1953
return "d4";
1954
case UNW_ARM64_D5:
1955
return "d5";
1956
case UNW_ARM64_D6:
1957
return "d6";
1958
case UNW_ARM64_D7:
1959
return "d7";
1960
case UNW_ARM64_D8:
1961
return "d8";
1962
case UNW_ARM64_D9:
1963
return "d9";
1964
case UNW_ARM64_D10:
1965
return "d10";
1966
case UNW_ARM64_D11:
1967
return "d11";
1968
case UNW_ARM64_D12:
1969
return "d12";
1970
case UNW_ARM64_D13:
1971
return "d13";
1972
case UNW_ARM64_D14:
1973
return "d14";
1974
case UNW_ARM64_D15:
1975
return "d15";
1976
case UNW_ARM64_D16:
1977
return "d16";
1978
case UNW_ARM64_D17:
1979
return "d17";
1980
case UNW_ARM64_D18:
1981
return "d18";
1982
case UNW_ARM64_D19:
1983
return "d19";
1984
case UNW_ARM64_D20:
1985
return "d20";
1986
case UNW_ARM64_D21:
1987
return "d21";
1988
case UNW_ARM64_D22:
1989
return "d22";
1990
case UNW_ARM64_D23:
1991
return "d23";
1992
case UNW_ARM64_D24:
1993
return "d24";
1994
case UNW_ARM64_D25:
1995
return "d25";
1996
case UNW_ARM64_D26:
1997
return "d26";
1998
case UNW_ARM64_D27:
1999
return "d27";
2000
case UNW_ARM64_D28:
2001
return "d28";
2002
case UNW_ARM64_D29:
2003
return "d29";
2004
case UNW_ARM64_D30:
2005
return "d30";
2006
case UNW_ARM64_D31:
2007
return "d31";
2008
default:
2009
return "unknown register";
2010
}
2011
}
2012
2013
inline bool Registers_arm64::validFloatRegister(int regNum) const {
2014
if (regNum < UNW_ARM64_D0)
2015
return false;
2016
if (regNum > UNW_ARM64_D31)
2017
return false;
2018
return true;
2019
}
2020
2021
inline double Registers_arm64::getFloatRegister(int regNum) const {
2022
assert(validFloatRegister(regNum));
2023
return _vectorHalfRegisters[regNum - UNW_ARM64_D0];
2024
}
2025
2026
inline void Registers_arm64::setFloatRegister(int regNum, double value) {
2027
assert(validFloatRegister(regNum));
2028
_vectorHalfRegisters[regNum - UNW_ARM64_D0] = value;
2029
}
2030
2031
inline bool Registers_arm64::validVectorRegister(int) const {
2032
return false;
2033
}
2034
2035
inline v128 Registers_arm64::getVectorRegister(int) const {
2036
_LIBUNWIND_ABORT("no arm64 vector register support yet");
2037
}
2038
2039
inline void Registers_arm64::setVectorRegister(int, v128) {
2040
_LIBUNWIND_ABORT("no arm64 vector register support yet");
2041
}
2042
#endif // _LIBUNWIND_TARGET_AARCH64
2043
2044
#if defined(_LIBUNWIND_TARGET_ARM)
2045
/// Registers_arm holds the register state of a thread in a 32-bit arm
2046
/// process.
2047
///
2048
/// NOTE: Assumes VFPv3. On ARM processors without a floating point unit,
2049
/// this uses more memory than required.
2050
class _LIBUNWIND_HIDDEN Registers_arm {
2051
public:
2052
Registers_arm();
2053
Registers_arm(const void *registers);
2054
2055
bool validRegister(int num) const;
2056
uint32_t getRegister(int num) const;
2057
void setRegister(int num, uint32_t value);
2058
bool validFloatRegister(int num) const;
2059
unw_fpreg_t getFloatRegister(int num);
2060
void setFloatRegister(int num, unw_fpreg_t value);
2061
bool validVectorRegister(int num) const;
2062
v128 getVectorRegister(int num) const;
2063
void setVectorRegister(int num, v128 value);
2064
static const char *getRegisterName(int num);
2065
void jumpto() {
2066
restoreSavedFloatRegisters();
2067
restoreCoreAndJumpTo();
2068
}
2069
static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM; }
2070
static int getArch() { return REGISTERS_ARM; }
2071
2072
uint32_t getSP() const { return _registers.__sp; }
2073
void setSP(uint32_t value) { _registers.__sp = value; }
2074
uint32_t getIP() const { return _registers.__pc; }
2075
void setIP(uint32_t value) { _registers.__pc = value; }
2076
2077
void saveVFPAsX() {
2078
assert(_use_X_for_vfp_save || !_saved_vfp_d0_d15);
2079
_use_X_for_vfp_save = true;
2080
}
2081
2082
void restoreSavedFloatRegisters() {
2083
if (_saved_vfp_d0_d15) {
2084
if (_use_X_for_vfp_save)
2085
restoreVFPWithFLDMX(_vfp_d0_d15_pad);
2086
else
2087
restoreVFPWithFLDMD(_vfp_d0_d15_pad);
2088
}
2089
if (_saved_vfp_d16_d31)
2090
restoreVFPv3(_vfp_d16_d31);
2091
#if defined(__ARM_WMMX)
2092
if (_saved_iwmmx)
2093
restoreiWMMX(_iwmmx);
2094
if (_saved_iwmmx_control)
2095
restoreiWMMXControl(_iwmmx_control);
2096
#endif
2097
}
2098
2099
private:
2100
struct GPRs {
2101
uint32_t __r[13]; // r0-r12
2102
uint32_t __sp; // Stack pointer r13
2103
uint32_t __lr; // Link register r14
2104
uint32_t __pc; // Program counter r15
2105
};
2106
2107
static void saveVFPWithFSTMD(void*);
2108
static void saveVFPWithFSTMX(void*);
2109
static void saveVFPv3(void*);
2110
static void restoreVFPWithFLDMD(void*);
2111
static void restoreVFPWithFLDMX(void*);
2112
static void restoreVFPv3(void*);
2113
#if defined(__ARM_WMMX)
2114
static void saveiWMMX(void*);
2115
static void saveiWMMXControl(uint32_t*);
2116
static void restoreiWMMX(void*);
2117
static void restoreiWMMXControl(uint32_t*);
2118
#endif
2119
void restoreCoreAndJumpTo();
2120
2121
// ARM registers
2122
GPRs _registers;
2123
2124
// We save floating point registers lazily because we can't know ahead of
2125
// time which ones are used. See EHABI #4.7.
2126
2127
// Whether D0-D15 are saved in the FTSMX instead of FSTMD format.
2128
//
2129
// See EHABI #7.5 that explains how matching instruction sequences for load
2130
// and store need to be used to correctly restore the exact register bits.
2131
bool _use_X_for_vfp_save;
2132
// Whether VFP D0-D15 are saved.
2133
bool _saved_vfp_d0_d15;
2134
// Whether VFPv3 D16-D31 are saved.
2135
bool _saved_vfp_d16_d31;
2136
// VFP registers D0-D15, + padding if saved using FSTMX
2137
unw_fpreg_t _vfp_d0_d15_pad[17];
2138
// VFPv3 registers D16-D31, always saved using FSTMD
2139
unw_fpreg_t _vfp_d16_d31[16];
2140
#if defined(__ARM_WMMX)
2141
// Whether iWMMX data registers are saved.
2142
bool _saved_iwmmx;
2143
// Whether iWMMX control registers are saved.
2144
mutable bool _saved_iwmmx_control;
2145
// iWMMX registers
2146
unw_fpreg_t _iwmmx[16];
2147
// iWMMX control registers
2148
mutable uint32_t _iwmmx_control[4];
2149
#endif
2150
};
2151
2152
inline Registers_arm::Registers_arm(const void *registers)
2153
: _use_X_for_vfp_save(false),
2154
_saved_vfp_d0_d15(false),
2155
_saved_vfp_d16_d31(false) {
2156
static_assert((check_fit<Registers_arm, unw_context_t>::does_fit),
2157
"arm registers do not fit into unw_context_t");
2158
// See unw_getcontext() note about data.
2159
memcpy(&_registers, registers, sizeof(_registers));
2160
memset(&_vfp_d0_d15_pad, 0, sizeof(_vfp_d0_d15_pad));
2161
memset(&_vfp_d16_d31, 0, sizeof(_vfp_d16_d31));
2162
#if defined(__ARM_WMMX)
2163
_saved_iwmmx = false;
2164
_saved_iwmmx_control = false;
2165
memset(&_iwmmx, 0, sizeof(_iwmmx));
2166
memset(&_iwmmx_control, 0, sizeof(_iwmmx_control));
2167
#endif
2168
}
2169
2170
inline Registers_arm::Registers_arm()
2171
: _use_X_for_vfp_save(false),
2172
_saved_vfp_d0_d15(false),
2173
_saved_vfp_d16_d31(false) {
2174
memset(&_registers, 0, sizeof(_registers));
2175
memset(&_vfp_d0_d15_pad, 0, sizeof(_vfp_d0_d15_pad));
2176
memset(&_vfp_d16_d31, 0, sizeof(_vfp_d16_d31));
2177
#if defined(__ARM_WMMX)
2178
_saved_iwmmx = false;
2179
_saved_iwmmx_control = false;
2180
memset(&_iwmmx, 0, sizeof(_iwmmx));
2181
memset(&_iwmmx_control, 0, sizeof(_iwmmx_control));
2182
#endif
2183
}
2184
2185
inline bool Registers_arm::validRegister(int regNum) const {
2186
// Returns true for all non-VFP registers supported by the EHABI
2187
// virtual register set (VRS).
2188
if (regNum == UNW_REG_IP)
2189
return true;
2190
2191
if (regNum == UNW_REG_SP)
2192
return true;
2193
2194
if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R15)
2195
return true;
2196
2197
#if defined(__ARM_WMMX)
2198
if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3)
2199
return true;
2200
#endif
2201
2202
return false;
2203
}
2204
2205
inline uint32_t Registers_arm::getRegister(int regNum) const {
2206
if (regNum == UNW_REG_SP || regNum == UNW_ARM_SP)
2207
return _registers.__sp;
2208
2209
if (regNum == UNW_ARM_LR)
2210
return _registers.__lr;
2211
2212
if (regNum == UNW_REG_IP || regNum == UNW_ARM_IP)
2213
return _registers.__pc;
2214
2215
if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R12)
2216
return _registers.__r[regNum];
2217
2218
#if defined(__ARM_WMMX)
2219
if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3) {
2220
if (!_saved_iwmmx_control) {
2221
_saved_iwmmx_control = true;
2222
saveiWMMXControl(_iwmmx_control);
2223
}
2224
return _iwmmx_control[regNum - UNW_ARM_WC0];
2225
}
2226
#endif
2227
2228
_LIBUNWIND_ABORT("unsupported arm register");
2229
}
2230
2231
inline void Registers_arm::setRegister(int regNum, uint32_t value) {
2232
if (regNum == UNW_REG_SP || regNum == UNW_ARM_SP) {
2233
_registers.__sp = value;
2234
return;
2235
}
2236
2237
if (regNum == UNW_ARM_LR) {
2238
_registers.__lr = value;
2239
return;
2240
}
2241
2242
if (regNum == UNW_REG_IP || regNum == UNW_ARM_IP) {
2243
_registers.__pc = value;
2244
return;
2245
}
2246
2247
if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R12) {
2248
_registers.__r[regNum] = value;
2249
return;
2250
}
2251
2252
#if defined(__ARM_WMMX)
2253
if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3) {
2254
if (!_saved_iwmmx_control) {
2255
_saved_iwmmx_control = true;
2256
saveiWMMXControl(_iwmmx_control);
2257
}
2258
_iwmmx_control[regNum - UNW_ARM_WC0] = value;
2259
return;
2260
}
2261
#endif
2262
2263
_LIBUNWIND_ABORT("unsupported arm register");
2264
}
2265
2266
inline const char *Registers_arm::getRegisterName(int regNum) {
2267
switch (regNum) {
2268
case UNW_REG_IP:
2269
case UNW_ARM_IP: // UNW_ARM_R15 is alias
2270
return "pc";
2271
case UNW_ARM_LR: // UNW_ARM_R14 is alias
2272
return "lr";
2273
case UNW_REG_SP:
2274
case UNW_ARM_SP: // UNW_ARM_R13 is alias
2275
return "sp";
2276
case UNW_ARM_R0:
2277
return "r0";
2278
case UNW_ARM_R1:
2279
return "r1";
2280
case UNW_ARM_R2:
2281
return "r2";
2282
case UNW_ARM_R3:
2283
return "r3";
2284
case UNW_ARM_R4:
2285
return "r4";
2286
case UNW_ARM_R5:
2287
return "r5";
2288
case UNW_ARM_R6:
2289
return "r6";
2290
case UNW_ARM_R7:
2291
return "r7";
2292
case UNW_ARM_R8:
2293
return "r8";
2294
case UNW_ARM_R9:
2295
return "r9";
2296
case UNW_ARM_R10:
2297
return "r10";
2298
case UNW_ARM_R11:
2299
return "r11";
2300
case UNW_ARM_R12:
2301
return "r12";
2302
case UNW_ARM_S0:
2303
return "s0";
2304
case UNW_ARM_S1:
2305
return "s1";
2306
case UNW_ARM_S2:
2307
return "s2";
2308
case UNW_ARM_S3:
2309
return "s3";
2310
case UNW_ARM_S4:
2311
return "s4";
2312
case UNW_ARM_S5:
2313
return "s5";
2314
case UNW_ARM_S6:
2315
return "s6";
2316
case UNW_ARM_S7:
2317
return "s7";
2318
case UNW_ARM_S8:
2319
return "s8";
2320
case UNW_ARM_S9:
2321
return "s9";
2322
case UNW_ARM_S10:
2323
return "s10";
2324
case UNW_ARM_S11:
2325
return "s11";
2326
case UNW_ARM_S12:
2327
return "s12";
2328
case UNW_ARM_S13:
2329
return "s13";
2330
case UNW_ARM_S14:
2331
return "s14";
2332
case UNW_ARM_S15:
2333
return "s15";
2334
case UNW_ARM_S16:
2335
return "s16";
2336
case UNW_ARM_S17:
2337
return "s17";
2338
case UNW_ARM_S18:
2339
return "s18";
2340
case UNW_ARM_S19:
2341
return "s19";
2342
case UNW_ARM_S20:
2343
return "s20";
2344
case UNW_ARM_S21:
2345
return "s21";
2346
case UNW_ARM_S22:
2347
return "s22";
2348
case UNW_ARM_S23:
2349
return "s23";
2350
case UNW_ARM_S24:
2351
return "s24";
2352
case UNW_ARM_S25:
2353
return "s25";
2354
case UNW_ARM_S26:
2355
return "s26";
2356
case UNW_ARM_S27:
2357
return "s27";
2358
case UNW_ARM_S28:
2359
return "s28";
2360
case UNW_ARM_S29:
2361
return "s29";
2362
case UNW_ARM_S30:
2363
return "s30";
2364
case UNW_ARM_S31:
2365
return "s31";
2366
case UNW_ARM_D0:
2367
return "d0";
2368
case UNW_ARM_D1:
2369
return "d1";
2370
case UNW_ARM_D2:
2371
return "d2";
2372
case UNW_ARM_D3:
2373
return "d3";
2374
case UNW_ARM_D4:
2375
return "d4";
2376
case UNW_ARM_D5:
2377
return "d5";
2378
case UNW_ARM_D6:
2379
return "d6";
2380
case UNW_ARM_D7:
2381
return "d7";
2382
case UNW_ARM_D8:
2383
return "d8";
2384
case UNW_ARM_D9:
2385
return "d9";
2386
case UNW_ARM_D10:
2387
return "d10";
2388
case UNW_ARM_D11:
2389
return "d11";
2390
case UNW_ARM_D12:
2391
return "d12";
2392
case UNW_ARM_D13:
2393
return "d13";
2394
case UNW_ARM_D14:
2395
return "d14";
2396
case UNW_ARM_D15:
2397
return "d15";
2398
case UNW_ARM_D16:
2399
return "d16";
2400
case UNW_ARM_D17:
2401
return "d17";
2402
case UNW_ARM_D18:
2403
return "d18";
2404
case UNW_ARM_D19:
2405
return "d19";
2406
case UNW_ARM_D20:
2407
return "d20";
2408
case UNW_ARM_D21:
2409
return "d21";
2410
case UNW_ARM_D22:
2411
return "d22";
2412
case UNW_ARM_D23:
2413
return "d23";
2414
case UNW_ARM_D24:
2415
return "d24";
2416
case UNW_ARM_D25:
2417
return "d25";
2418
case UNW_ARM_D26:
2419
return "d26";
2420
case UNW_ARM_D27:
2421
return "d27";
2422
case UNW_ARM_D28:
2423
return "d28";
2424
case UNW_ARM_D29:
2425
return "d29";
2426
case UNW_ARM_D30:
2427
return "d30";
2428
case UNW_ARM_D31:
2429
return "d31";
2430
default:
2431
return "unknown register";
2432
}
2433
}
2434
2435
inline bool Registers_arm::validFloatRegister(int regNum) const {
2436
// NOTE: Consider the intel MMX registers floating points so the
2437
// unw_get_fpreg can be used to transmit the 64-bit data back.
2438
return ((regNum >= UNW_ARM_D0) && (regNum <= UNW_ARM_D31))
2439
#if defined(__ARM_WMMX)
2440
|| ((regNum >= UNW_ARM_WR0) && (regNum <= UNW_ARM_WR15))
2441
#endif
2442
;
2443
}
2444
2445
inline unw_fpreg_t Registers_arm::getFloatRegister(int regNum) {
2446
if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D15) {
2447
if (!_saved_vfp_d0_d15) {
2448
_saved_vfp_d0_d15 = true;
2449
if (_use_X_for_vfp_save)
2450
saveVFPWithFSTMX(_vfp_d0_d15_pad);
2451
else
2452
saveVFPWithFSTMD(_vfp_d0_d15_pad);
2453
}
2454
return _vfp_d0_d15_pad[regNum - UNW_ARM_D0];
2455
}
2456
2457
if (regNum >= UNW_ARM_D16 && regNum <= UNW_ARM_D31) {
2458
if (!_saved_vfp_d16_d31) {
2459
_saved_vfp_d16_d31 = true;
2460
saveVFPv3(_vfp_d16_d31);
2461
}
2462
return _vfp_d16_d31[regNum - UNW_ARM_D16];
2463
}
2464
2465
#if defined(__ARM_WMMX)
2466
if (regNum >= UNW_ARM_WR0 && regNum <= UNW_ARM_WR15) {
2467
if (!_saved_iwmmx) {
2468
_saved_iwmmx = true;
2469
saveiWMMX(_iwmmx);
2470
}
2471
return _iwmmx[regNum - UNW_ARM_WR0];
2472
}
2473
#endif
2474
2475
_LIBUNWIND_ABORT("Unknown ARM float register");
2476
}
2477
2478
inline void Registers_arm::setFloatRegister(int regNum, unw_fpreg_t value) {
2479
if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D15) {
2480
if (!_saved_vfp_d0_d15) {
2481
_saved_vfp_d0_d15 = true;
2482
if (_use_X_for_vfp_save)
2483
saveVFPWithFSTMX(_vfp_d0_d15_pad);
2484
else
2485
saveVFPWithFSTMD(_vfp_d0_d15_pad);
2486
}
2487
_vfp_d0_d15_pad[regNum - UNW_ARM_D0] = value;
2488
return;
2489
}
2490
2491
if (regNum >= UNW_ARM_D16 && regNum <= UNW_ARM_D31) {
2492
if (!_saved_vfp_d16_d31) {
2493
_saved_vfp_d16_d31 = true;
2494
saveVFPv3(_vfp_d16_d31);
2495
}
2496
_vfp_d16_d31[regNum - UNW_ARM_D16] = value;
2497
return;
2498
}
2499
2500
#if defined(__ARM_WMMX)
2501
if (regNum >= UNW_ARM_WR0 && regNum <= UNW_ARM_WR15) {
2502
if (!_saved_iwmmx) {
2503
_saved_iwmmx = true;
2504
saveiWMMX(_iwmmx);
2505
}
2506
_iwmmx[regNum - UNW_ARM_WR0] = value;
2507
return;
2508
}
2509
#endif
2510
2511
_LIBUNWIND_ABORT("Unknown ARM float register");
2512
}
2513
2514
inline bool Registers_arm::validVectorRegister(int) const {
2515
return false;
2516
}
2517
2518
inline v128 Registers_arm::getVectorRegister(int) const {
2519
_LIBUNWIND_ABORT("ARM vector support not implemented");
2520
}
2521
2522
inline void Registers_arm::setVectorRegister(int, v128) {
2523
_LIBUNWIND_ABORT("ARM vector support not implemented");
2524
}
2525
#endif // _LIBUNWIND_TARGET_ARM
2526
2527
2528
#if defined(_LIBUNWIND_TARGET_OR1K)
2529
/// Registers_or1k holds the register state of a thread in an OpenRISC1000
2530
/// process.
2531
class _LIBUNWIND_HIDDEN Registers_or1k {
2532
public:
2533
Registers_or1k();
2534
Registers_or1k(const void *registers);
2535
2536
bool validRegister(int num) const;
2537
uint32_t getRegister(int num) const;
2538
void setRegister(int num, uint32_t value);
2539
bool validFloatRegister(int num) const;
2540
double getFloatRegister(int num) const;
2541
void setFloatRegister(int num, double value);
2542
bool validVectorRegister(int num) const;
2543
v128 getVectorRegister(int num) const;
2544
void setVectorRegister(int num, v128 value);
2545
static const char *getRegisterName(int num);
2546
void jumpto();
2547
static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K; }
2548
static int getArch() { return REGISTERS_OR1K; }
2549
2550
uint64_t getSP() const { return _registers.__r[1]; }
2551
void setSP(uint32_t value) { _registers.__r[1] = value; }
2552
uint64_t getIP() const { return _registers.__pc; }
2553
void setIP(uint32_t value) { _registers.__pc = value; }
2554
2555
private:
2556
struct or1k_thread_state_t {
2557
unsigned int __r[32]; // r0-r31
2558
unsigned int __pc; // Program counter
2559
unsigned int __epcr; // Program counter at exception
2560
};
2561
2562
or1k_thread_state_t _registers;
2563
};
2564
2565
inline Registers_or1k::Registers_or1k(const void *registers) {
2566
static_assert((check_fit<Registers_or1k, unw_context_t>::does_fit),
2567
"or1k registers do not fit into unw_context_t");
2568
memcpy(&_registers, static_cast<const uint8_t *>(registers),
2569
sizeof(_registers));
2570
}
2571
2572
inline Registers_or1k::Registers_or1k() {
2573
memset(&_registers, 0, sizeof(_registers));
2574
}
2575
2576
inline bool Registers_or1k::validRegister(int regNum) const {
2577
if (regNum == UNW_REG_IP)
2578
return true;
2579
if (regNum == UNW_REG_SP)
2580
return true;
2581
if (regNum < 0)
2582
return false;
2583
if (regNum <= UNW_OR1K_R31)
2584
return true;
2585
if (regNum == UNW_OR1K_EPCR)
2586
return true;
2587
return false;
2588
}
2589
2590
inline uint32_t Registers_or1k::getRegister(int regNum) const {
2591
if (regNum >= UNW_OR1K_R0 && regNum <= UNW_OR1K_R31)
2592
return _registers.__r[regNum - UNW_OR1K_R0];
2593
2594
switch (regNum) {
2595
case UNW_REG_IP:
2596
return _registers.__pc;
2597
case UNW_REG_SP:
2598
return _registers.__r[1];
2599
case UNW_OR1K_EPCR:
2600
return _registers.__epcr;
2601
}
2602
_LIBUNWIND_ABORT("unsupported or1k register");
2603
}
2604
2605
inline void Registers_or1k::setRegister(int regNum, uint32_t value) {
2606
if (regNum >= UNW_OR1K_R0 && regNum <= UNW_OR1K_R31) {
2607
_registers.__r[regNum - UNW_OR1K_R0] = value;
2608
return;
2609
}
2610
2611
switch (regNum) {
2612
case UNW_REG_IP:
2613
_registers.__pc = value;
2614
return;
2615
case UNW_REG_SP:
2616
_registers.__r[1] = value;
2617
return;
2618
case UNW_OR1K_EPCR:
2619
_registers.__epcr = value;
2620
return;
2621
}
2622
_LIBUNWIND_ABORT("unsupported or1k register");
2623
}
2624
2625
inline bool Registers_or1k::validFloatRegister(int /* regNum */) const {
2626
return false;
2627
}
2628
2629
inline double Registers_or1k::getFloatRegister(int /* regNum */) const {
2630
_LIBUNWIND_ABORT("or1k float support not implemented");
2631
}
2632
2633
inline void Registers_or1k::setFloatRegister(int /* regNum */,
2634
double /* value */) {
2635
_LIBUNWIND_ABORT("or1k float support not implemented");
2636
}
2637
2638
inline bool Registers_or1k::validVectorRegister(int /* regNum */) const {
2639
return false;
2640
}
2641
2642
inline v128 Registers_or1k::getVectorRegister(int /* regNum */) const {
2643
_LIBUNWIND_ABORT("or1k vector support not implemented");
2644
}
2645
2646
inline void Registers_or1k::setVectorRegister(int /* regNum */, v128 /* value */) {
2647
_LIBUNWIND_ABORT("or1k vector support not implemented");
2648
}
2649
2650
inline const char *Registers_or1k::getRegisterName(int regNum) {
2651
switch (regNum) {
2652
case UNW_OR1K_R0:
2653
return "r0";
2654
case UNW_OR1K_R1:
2655
return "r1";
2656
case UNW_OR1K_R2:
2657
return "r2";
2658
case UNW_OR1K_R3:
2659
return "r3";
2660
case UNW_OR1K_R4:
2661
return "r4";
2662
case UNW_OR1K_R5:
2663
return "r5";
2664
case UNW_OR1K_R6:
2665
return "r6";
2666
case UNW_OR1K_R7:
2667
return "r7";
2668
case UNW_OR1K_R8:
2669
return "r8";
2670
case UNW_OR1K_R9:
2671
return "r9";
2672
case UNW_OR1K_R10:
2673
return "r10";
2674
case UNW_OR1K_R11:
2675
return "r11";
2676
case UNW_OR1K_R12:
2677
return "r12";
2678
case UNW_OR1K_R13:
2679
return "r13";
2680
case UNW_OR1K_R14:
2681
return "r14";
2682
case UNW_OR1K_R15:
2683
return "r15";
2684
case UNW_OR1K_R16:
2685
return "r16";
2686
case UNW_OR1K_R17:
2687
return "r17";
2688
case UNW_OR1K_R18:
2689
return "r18";
2690
case UNW_OR1K_R19:
2691
return "r19";
2692
case UNW_OR1K_R20:
2693
return "r20";
2694
case UNW_OR1K_R21:
2695
return "r21";
2696
case UNW_OR1K_R22:
2697
return "r22";
2698
case UNW_OR1K_R23:
2699
return "r23";
2700
case UNW_OR1K_R24:
2701
return "r24";
2702
case UNW_OR1K_R25:
2703
return "r25";
2704
case UNW_OR1K_R26:
2705
return "r26";
2706
case UNW_OR1K_R27:
2707
return "r27";
2708
case UNW_OR1K_R28:
2709
return "r28";
2710
case UNW_OR1K_R29:
2711
return "r29";
2712
case UNW_OR1K_R30:
2713
return "r30";
2714
case UNW_OR1K_R31:
2715
return "r31";
2716
case UNW_OR1K_EPCR:
2717
return "EPCR";
2718
default:
2719
return "unknown register";
2720
}
2721
2722
}
2723
#endif // _LIBUNWIND_TARGET_OR1K
2724
2725
#if defined(_LIBUNWIND_TARGET_MIPS_O32)
2726
/// Registers_mips_o32 holds the register state of a thread in a 32-bit MIPS
2727
/// process.
2728
class _LIBUNWIND_HIDDEN Registers_mips_o32 {
2729
public:
2730
Registers_mips_o32();
2731
Registers_mips_o32(const void *registers);
2732
2733
bool validRegister(int num) const;
2734
uint32_t getRegister(int num) const;
2735
void setRegister(int num, uint32_t value);
2736
bool validFloatRegister(int num) const;
2737
double getFloatRegister(int num) const;
2738
void setFloatRegister(int num, double value);
2739
bool validVectorRegister(int num) const;
2740
v128 getVectorRegister(int num) const;
2741
void setVectorRegister(int num, v128 value);
2742
static const char *getRegisterName(int num);
2743
void jumpto();
2744
static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS; }
2745
static int getArch() { return REGISTERS_MIPS_O32; }
2746
2747
uint32_t getSP() const { return _registers.__r[29]; }
2748
void setSP(uint32_t value) { _registers.__r[29] = value; }
2749
uint32_t getIP() const { return _registers.__pc; }
2750
void setIP(uint32_t value) { _registers.__pc = value; }
2751
2752
private:
2753
struct mips_o32_thread_state_t {
2754
uint32_t __r[32];
2755
uint32_t __pc;
2756
uint32_t __hi;
2757
uint32_t __lo;
2758
};
2759
2760
mips_o32_thread_state_t _registers;
2761
#ifdef __mips_hard_float
2762
/// O32 with 32-bit floating point registers only uses half of this
2763
/// space. However, using the same layout for 32-bit vs 64-bit
2764
/// floating point registers results in a single context size for
2765
/// O32 with hard float.
2766
uint32_t _padding;
2767
double _floats[32];
2768
#endif
2769
};
2770
2771
inline Registers_mips_o32::Registers_mips_o32(const void *registers) {
2772
static_assert((check_fit<Registers_mips_o32, unw_context_t>::does_fit),
2773
"mips_o32 registers do not fit into unw_context_t");
2774
memcpy(&_registers, static_cast<const uint8_t *>(registers),
2775
sizeof(_registers));
2776
}
2777
2778
inline Registers_mips_o32::Registers_mips_o32() {
2779
memset(&_registers, 0, sizeof(_registers));
2780
}
2781
2782
inline bool Registers_mips_o32::validRegister(int regNum) const {
2783
if (regNum == UNW_REG_IP)
2784
return true;
2785
if (regNum == UNW_REG_SP)
2786
return true;
2787
if (regNum < 0)
2788
return false;
2789
if (regNum <= UNW_MIPS_R31)
2790
return true;
2791
#if __mips_isa_rev != 6
2792
if (regNum == UNW_MIPS_HI)
2793
return true;
2794
if (regNum == UNW_MIPS_LO)
2795
return true;
2796
#endif
2797
#if defined(__mips_hard_float) && __mips_fpr == 32
2798
if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31)
2799
return true;
2800
#endif
2801
// FIXME: DSP accumulator registers, MSA registers
2802
return false;
2803
}
2804
2805
inline uint32_t Registers_mips_o32::getRegister(int regNum) const {
2806
if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31)
2807
return _registers.__r[regNum - UNW_MIPS_R0];
2808
#if defined(__mips_hard_float) && __mips_fpr == 32
2809
if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) {
2810
uint32_t *p;
2811
2812
if (regNum % 2 == 0)
2813
p = (uint32_t *)&_floats[regNum - UNW_MIPS_F0];
2814
else
2815
p = (uint32_t *)&_floats[(regNum - 1) - UNW_MIPS_F0] + 1;
2816
return *p;
2817
}
2818
#endif
2819
2820
switch (regNum) {
2821
case UNW_REG_IP:
2822
return _registers.__pc;
2823
case UNW_REG_SP:
2824
return _registers.__r[29];
2825
case UNW_MIPS_HI:
2826
return _registers.__hi;
2827
case UNW_MIPS_LO:
2828
return _registers.__lo;
2829
}
2830
_LIBUNWIND_ABORT("unsupported mips_o32 register");
2831
}
2832
2833
inline void Registers_mips_o32::setRegister(int regNum, uint32_t value) {
2834
if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31) {
2835
_registers.__r[regNum - UNW_MIPS_R0] = value;
2836
return;
2837
}
2838
#if defined(__mips_hard_float) && __mips_fpr == 32
2839
if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) {
2840
uint32_t *p;
2841
2842
if (regNum % 2 == 0)
2843
p = (uint32_t *)&_floats[regNum - UNW_MIPS_F0];
2844
else
2845
p = (uint32_t *)&_floats[(regNum - 1) - UNW_MIPS_F0] + 1;
2846
*p = value;
2847
return;
2848
}
2849
#endif
2850
2851
switch (regNum) {
2852
case UNW_REG_IP:
2853
_registers.__pc = value;
2854
return;
2855
case UNW_REG_SP:
2856
_registers.__r[29] = value;
2857
return;
2858
case UNW_MIPS_HI:
2859
_registers.__hi = value;
2860
return;
2861
case UNW_MIPS_LO:
2862
_registers.__lo = value;
2863
return;
2864
}
2865
_LIBUNWIND_ABORT("unsupported mips_o32 register");
2866
}
2867
2868
inline bool Registers_mips_o32::validFloatRegister(int regNum) const {
2869
#if defined(__mips_hard_float) && __mips_fpr == 64
2870
if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31)
2871
return true;
2872
#endif
2873
return false;
2874
}
2875
2876
inline double Registers_mips_o32::getFloatRegister(int regNum) const {
2877
#if defined(__mips_hard_float) && __mips_fpr == 64
2878
assert(validFloatRegister(regNum));
2879
return _floats[regNum - UNW_MIPS_F0];
2880
#else
2881
_LIBUNWIND_ABORT("mips_o32 float support not implemented");
2882
#endif
2883
}
2884
2885
inline void Registers_mips_o32::setFloatRegister(int regNum,
2886
double value) {
2887
#if defined(__mips_hard_float) && __mips_fpr == 64
2888
assert(validFloatRegister(regNum));
2889
_floats[regNum - UNW_MIPS_F0] = value;
2890
#else
2891
_LIBUNWIND_ABORT("mips_o32 float support not implemented");
2892
#endif
2893
}
2894
2895
inline bool Registers_mips_o32::validVectorRegister(int /* regNum */) const {
2896
return false;
2897
}
2898
2899
inline v128 Registers_mips_o32::getVectorRegister(int /* regNum */) const {
2900
_LIBUNWIND_ABORT("mips_o32 vector support not implemented");
2901
}
2902
2903
inline void Registers_mips_o32::setVectorRegister(int /* regNum */, v128 /* value */) {
2904
_LIBUNWIND_ABORT("mips_o32 vector support not implemented");
2905
}
2906
2907
inline const char *Registers_mips_o32::getRegisterName(int regNum) {
2908
switch (regNum) {
2909
case UNW_MIPS_R0:
2910
return "$0";
2911
case UNW_MIPS_R1:
2912
return "$1";
2913
case UNW_MIPS_R2:
2914
return "$2";
2915
case UNW_MIPS_R3:
2916
return "$3";
2917
case UNW_MIPS_R4:
2918
return "$4";
2919
case UNW_MIPS_R5:
2920
return "$5";
2921
case UNW_MIPS_R6:
2922
return "$6";
2923
case UNW_MIPS_R7:
2924
return "$7";
2925
case UNW_MIPS_R8:
2926
return "$8";
2927
case UNW_MIPS_R9:
2928
return "$9";
2929
case UNW_MIPS_R10:
2930
return "$10";
2931
case UNW_MIPS_R11:
2932
return "$11";
2933
case UNW_MIPS_R12:
2934
return "$12";
2935
case UNW_MIPS_R13:
2936
return "$13";
2937
case UNW_MIPS_R14:
2938
return "$14";
2939
case UNW_MIPS_R15:
2940
return "$15";
2941
case UNW_MIPS_R16:
2942
return "$16";
2943
case UNW_MIPS_R17:
2944
return "$17";
2945
case UNW_MIPS_R18:
2946
return "$18";
2947
case UNW_MIPS_R19:
2948
return "$19";
2949
case UNW_MIPS_R20:
2950
return "$20";
2951
case UNW_MIPS_R21:
2952
return "$21";
2953
case UNW_MIPS_R22:
2954
return "$22";
2955
case UNW_MIPS_R23:
2956
return "$23";
2957
case UNW_MIPS_R24:
2958
return "$24";
2959
case UNW_MIPS_R25:
2960
return "$25";
2961
case UNW_MIPS_R26:
2962
return "$26";
2963
case UNW_MIPS_R27:
2964
return "$27";
2965
case UNW_MIPS_R28:
2966
return "$28";
2967
case UNW_MIPS_R29:
2968
return "$29";
2969
case UNW_MIPS_R30:
2970
return "$30";
2971
case UNW_MIPS_R31:
2972
return "$31";
2973
case UNW_MIPS_F0:
2974
return "$f0";
2975
case UNW_MIPS_F1:
2976
return "$f1";
2977
case UNW_MIPS_F2:
2978
return "$f2";
2979
case UNW_MIPS_F3:
2980
return "$f3";
2981
case UNW_MIPS_F4:
2982
return "$f4";
2983
case UNW_MIPS_F5:
2984
return "$f5";
2985
case UNW_MIPS_F6:
2986
return "$f6";
2987
case UNW_MIPS_F7:
2988
return "$f7";
2989
case UNW_MIPS_F8:
2990
return "$f8";
2991
case UNW_MIPS_F9:
2992
return "$f9";
2993
case UNW_MIPS_F10:
2994
return "$f10";
2995
case UNW_MIPS_F11:
2996
return "$f11";
2997
case UNW_MIPS_F12:
2998
return "$f12";
2999
case UNW_MIPS_F13:
3000
return "$f13";
3001
case UNW_MIPS_F14:
3002
return "$f14";
3003
case UNW_MIPS_F15:
3004
return "$f15";
3005
case UNW_MIPS_F16:
3006
return "$f16";
3007
case UNW_MIPS_F17:
3008
return "$f17";
3009
case UNW_MIPS_F18:
3010
return "$f18";
3011
case UNW_MIPS_F19:
3012
return "$f19";
3013
case UNW_MIPS_F20:
3014
return "$f20";
3015
case UNW_MIPS_F21:
3016
return "$f21";
3017
case UNW_MIPS_F22:
3018
return "$f22";
3019
case UNW_MIPS_F23:
3020
return "$f23";
3021
case UNW_MIPS_F24:
3022
return "$f24";
3023
case UNW_MIPS_F25:
3024
return "$f25";
3025
case UNW_MIPS_F26:
3026
return "$f26";
3027
case UNW_MIPS_F27:
3028
return "$f27";
3029
case UNW_MIPS_F28:
3030
return "$f28";
3031
case UNW_MIPS_F29:
3032
return "$f29";
3033
case UNW_MIPS_F30:
3034
return "$f30";
3035
case UNW_MIPS_F31:
3036
return "$f31";
3037
case UNW_MIPS_HI:
3038
return "$hi";
3039
case UNW_MIPS_LO:
3040
return "$lo";
3041
default:
3042
return "unknown register";
3043
}
3044
}
3045
#endif // _LIBUNWIND_TARGET_MIPS_O32
3046
3047
#if defined(_LIBUNWIND_TARGET_MIPS_NEWABI)
3048
/// Registers_mips_newabi holds the register state of a thread in a
3049
/// MIPS process using NEWABI (the N32 or N64 ABIs).
3050
class _LIBUNWIND_HIDDEN Registers_mips_newabi {
3051
public:
3052
Registers_mips_newabi();
3053
Registers_mips_newabi(const void *registers);
3054
3055
bool validRegister(int num) const;
3056
uint64_t getRegister(int num) const;
3057
void setRegister(int num, uint64_t value);
3058
bool validFloatRegister(int num) const;
3059
double getFloatRegister(int num) const;
3060
void setFloatRegister(int num, double value);
3061
bool validVectorRegister(int num) const;
3062
v128 getVectorRegister(int num) const;
3063
void setVectorRegister(int num, v128 value);
3064
static const char *getRegisterName(int num);
3065
void jumpto();
3066
static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS; }
3067
static int getArch() { return REGISTERS_MIPS_NEWABI; }
3068
3069
uint64_t getSP() const { return _registers.__r[29]; }
3070
void setSP(uint64_t value) { _registers.__r[29] = value; }
3071
uint64_t getIP() const { return _registers.__pc; }
3072
void setIP(uint64_t value) { _registers.__pc = value; }
3073
3074
private:
3075
struct mips_newabi_thread_state_t {
3076
uint64_t __r[32];
3077
uint64_t __pc;
3078
uint64_t __hi;
3079
uint64_t __lo;
3080
};
3081
3082
mips_newabi_thread_state_t _registers;
3083
#ifdef __mips_hard_float
3084
double _floats[32];
3085
#endif
3086
};
3087
3088
inline Registers_mips_newabi::Registers_mips_newabi(const void *registers) {
3089
static_assert((check_fit<Registers_mips_newabi, unw_context_t>::does_fit),
3090
"mips_newabi registers do not fit into unw_context_t");
3091
memcpy(&_registers, static_cast<const uint8_t *>(registers),
3092
sizeof(_registers));
3093
}
3094
3095
inline Registers_mips_newabi::Registers_mips_newabi() {
3096
memset(&_registers, 0, sizeof(_registers));
3097
}
3098
3099
inline bool Registers_mips_newabi::validRegister(int regNum) const {
3100
if (regNum == UNW_REG_IP)
3101
return true;
3102
if (regNum == UNW_REG_SP)
3103
return true;
3104
if (regNum < 0)
3105
return false;
3106
if (regNum <= UNW_MIPS_R31)
3107
return true;
3108
#if __mips_isa_rev != 6
3109
if (regNum == UNW_MIPS_HI)
3110
return true;
3111
if (regNum == UNW_MIPS_LO)
3112
return true;
3113
#endif
3114
// FIXME: Hard float, DSP accumulator registers, MSA registers
3115
return false;
3116
}
3117
3118
inline uint64_t Registers_mips_newabi::getRegister(int regNum) const {
3119
if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31)
3120
return _registers.__r[regNum - UNW_MIPS_R0];
3121
3122
switch (regNum) {
3123
case UNW_REG_IP:
3124
return _registers.__pc;
3125
case UNW_REG_SP:
3126
return _registers.__r[29];
3127
case UNW_MIPS_HI:
3128
return _registers.__hi;
3129
case UNW_MIPS_LO:
3130
return _registers.__lo;
3131
}
3132
_LIBUNWIND_ABORT("unsupported mips_newabi register");
3133
}
3134
3135
inline void Registers_mips_newabi::setRegister(int regNum, uint64_t value) {
3136
if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31) {
3137
_registers.__r[regNum - UNW_MIPS_R0] = value;
3138
return;
3139
}
3140
3141
switch (regNum) {
3142
case UNW_REG_IP:
3143
_registers.__pc = value;
3144
return;
3145
case UNW_REG_SP:
3146
_registers.__r[29] = value;
3147
return;
3148
case UNW_MIPS_HI:
3149
_registers.__hi = value;
3150
return;
3151
case UNW_MIPS_LO:
3152
_registers.__lo = value;
3153
return;
3154
}
3155
_LIBUNWIND_ABORT("unsupported mips_newabi register");
3156
}
3157
3158
inline bool Registers_mips_newabi::validFloatRegister(int regNum) const {
3159
#ifdef __mips_hard_float
3160
if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31)
3161
return true;
3162
#endif
3163
return false;
3164
}
3165
3166
inline double Registers_mips_newabi::getFloatRegister(int regNum) const {
3167
#ifdef __mips_hard_float
3168
assert(validFloatRegister(regNum));
3169
return _floats[regNum - UNW_MIPS_F0];
3170
#else
3171
_LIBUNWIND_ABORT("mips_newabi float support not implemented");
3172
#endif
3173
}
3174
3175
inline void Registers_mips_newabi::setFloatRegister(int regNum,
3176
double value) {
3177
#ifdef __mips_hard_float
3178
assert(validFloatRegister(regNum));
3179
_floats[regNum - UNW_MIPS_F0] = value;
3180
#else
3181
_LIBUNWIND_ABORT("mips_newabi float support not implemented");
3182
#endif
3183
}
3184
3185
inline bool Registers_mips_newabi::validVectorRegister(int /* regNum */) const {
3186
return false;
3187
}
3188
3189
inline v128 Registers_mips_newabi::getVectorRegister(int /* regNum */) const {
3190
_LIBUNWIND_ABORT("mips_newabi vector support not implemented");
3191
}
3192
3193
inline void Registers_mips_newabi::setVectorRegister(int /* regNum */, v128 /* value */) {
3194
_LIBUNWIND_ABORT("mips_newabi vector support not implemented");
3195
}
3196
3197
inline const char *Registers_mips_newabi::getRegisterName(int regNum) {
3198
switch (regNum) {
3199
case UNW_MIPS_R0:
3200
return "$0";
3201
case UNW_MIPS_R1:
3202
return "$1";
3203
case UNW_MIPS_R2:
3204
return "$2";
3205
case UNW_MIPS_R3:
3206
return "$3";
3207
case UNW_MIPS_R4:
3208
return "$4";
3209
case UNW_MIPS_R5:
3210
return "$5";
3211
case UNW_MIPS_R6:
3212
return "$6";
3213
case UNW_MIPS_R7:
3214
return "$7";
3215
case UNW_MIPS_R8:
3216
return "$8";
3217
case UNW_MIPS_R9:
3218
return "$9";
3219
case UNW_MIPS_R10:
3220
return "$10";
3221
case UNW_MIPS_R11:
3222
return "$11";
3223
case UNW_MIPS_R12:
3224
return "$12";
3225
case UNW_MIPS_R13:
3226
return "$13";
3227
case UNW_MIPS_R14:
3228
return "$14";
3229
case UNW_MIPS_R15:
3230
return "$15";
3231
case UNW_MIPS_R16:
3232
return "$16";
3233
case UNW_MIPS_R17:
3234
return "$17";
3235
case UNW_MIPS_R18:
3236
return "$18";
3237
case UNW_MIPS_R19:
3238
return "$19";
3239
case UNW_MIPS_R20:
3240
return "$20";
3241
case UNW_MIPS_R21:
3242
return "$21";
3243
case UNW_MIPS_R22:
3244
return "$22";
3245
case UNW_MIPS_R23:
3246
return "$23";
3247
case UNW_MIPS_R24:
3248
return "$24";
3249
case UNW_MIPS_R25:
3250
return "$25";
3251
case UNW_MIPS_R26:
3252
return "$26";
3253
case UNW_MIPS_R27:
3254
return "$27";
3255
case UNW_MIPS_R28:
3256
return "$28";
3257
case UNW_MIPS_R29:
3258
return "$29";
3259
case UNW_MIPS_R30:
3260
return "$30";
3261
case UNW_MIPS_R31:
3262
return "$31";
3263
case UNW_MIPS_F0:
3264
return "$f0";
3265
case UNW_MIPS_F1:
3266
return "$f1";
3267
case UNW_MIPS_F2:
3268
return "$f2";
3269
case UNW_MIPS_F3:
3270
return "$f3";
3271
case UNW_MIPS_F4:
3272
return "$f4";
3273
case UNW_MIPS_F5:
3274
return "$f5";
3275
case UNW_MIPS_F6:
3276
return "$f6";
3277
case UNW_MIPS_F7:
3278
return "$f7";
3279
case UNW_MIPS_F8:
3280
return "$f8";
3281
case UNW_MIPS_F9:
3282
return "$f9";
3283
case UNW_MIPS_F10:
3284
return "$f10";
3285
case UNW_MIPS_F11:
3286
return "$f11";
3287
case UNW_MIPS_F12:
3288
return "$f12";
3289
case UNW_MIPS_F13:
3290
return "$f13";
3291
case UNW_MIPS_F14:
3292
return "$f14";
3293
case UNW_MIPS_F15:
3294
return "$f15";
3295
case UNW_MIPS_F16:
3296
return "$f16";
3297
case UNW_MIPS_F17:
3298
return "$f17";
3299
case UNW_MIPS_F18:
3300
return "$f18";
3301
case UNW_MIPS_F19:
3302
return "$f19";
3303
case UNW_MIPS_F20:
3304
return "$f20";
3305
case UNW_MIPS_F21:
3306
return "$f21";
3307
case UNW_MIPS_F22:
3308
return "$f22";
3309
case UNW_MIPS_F23:
3310
return "$f23";
3311
case UNW_MIPS_F24:
3312
return "$f24";
3313
case UNW_MIPS_F25:
3314
return "$f25";
3315
case UNW_MIPS_F26:
3316
return "$f26";
3317
case UNW_MIPS_F27:
3318
return "$f27";
3319
case UNW_MIPS_F28:
3320
return "$f28";
3321
case UNW_MIPS_F29:
3322
return "$f29";
3323
case UNW_MIPS_F30:
3324
return "$f30";
3325
case UNW_MIPS_F31:
3326
return "$f31";
3327
case UNW_MIPS_HI:
3328
return "$hi";
3329
case UNW_MIPS_LO:
3330
return "$lo";
3331
default:
3332
return "unknown register";
3333
}
3334
}
3335
#endif // _LIBUNWIND_TARGET_MIPS_NEWABI
3336
3337
#if defined(_LIBUNWIND_TARGET_SPARC)
3338
/// Registers_sparc holds the register state of a thread in a 32-bit Sparc
3339
/// process.
3340
class _LIBUNWIND_HIDDEN Registers_sparc {
3341
public:
3342
Registers_sparc();
3343
Registers_sparc(const void *registers);
3344
3345
bool validRegister(int num) const;
3346
uint32_t getRegister(int num) const;
3347
void setRegister(int num, uint32_t value);
3348
bool validFloatRegister(int num) const;
3349
double getFloatRegister(int num) const;
3350
void setFloatRegister(int num, double value);
3351
bool validVectorRegister(int num) const;
3352
v128 getVectorRegister(int num) const;
3353
void setVectorRegister(int num, v128 value);
3354
static const char *getRegisterName(int num);
3355
void jumpto();
3356
static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC; }
3357
static int getArch() { return REGISTERS_SPARC; }
3358
3359
uint64_t getSP() const { return _registers.__regs[UNW_SPARC_O6]; }
3360
void setSP(uint32_t value) { _registers.__regs[UNW_SPARC_O6] = value; }
3361
uint64_t getIP() const { return _registers.__regs[UNW_SPARC_O7]; }
3362
void setIP(uint32_t value) { _registers.__regs[UNW_SPARC_O7] = value; }
3363
3364
private:
3365
struct sparc_thread_state_t {
3366
unsigned int __regs[32];
3367
};
3368
3369
sparc_thread_state_t _registers;
3370
};
3371
3372
inline Registers_sparc::Registers_sparc(const void *registers) {
3373
static_assert((check_fit<Registers_sparc, unw_context_t>::does_fit),
3374
"sparc registers do not fit into unw_context_t");
3375
memcpy(&_registers, static_cast<const uint8_t *>(registers),
3376
sizeof(_registers));
3377
}
3378
3379
inline Registers_sparc::Registers_sparc() {
3380
memset(&_registers, 0, sizeof(_registers));
3381
}
3382
3383
inline bool Registers_sparc::validRegister(int regNum) const {
3384
if (regNum == UNW_REG_IP)
3385
return true;
3386
if (regNum == UNW_REG_SP)
3387
return true;
3388
if (regNum < 0)
3389
return false;
3390
if (regNum <= UNW_SPARC_I7)
3391
return true;
3392
return false;
3393
}
3394
3395
inline uint32_t Registers_sparc::getRegister(int regNum) const {
3396
if ((UNW_SPARC_G0 <= regNum) && (regNum <= UNW_SPARC_I7)) {
3397
return _registers.__regs[regNum];
3398
}
3399
3400
switch (regNum) {
3401
case UNW_REG_IP:
3402
return _registers.__regs[UNW_SPARC_O7];
3403
case UNW_REG_SP:
3404
return _registers.__regs[UNW_SPARC_O6];
3405
}
3406
_LIBUNWIND_ABORT("unsupported sparc register");
3407
}
3408
3409
inline void Registers_sparc::setRegister(int regNum, uint32_t value) {
3410
if ((UNW_SPARC_G0 <= regNum) && (regNum <= UNW_SPARC_I7)) {
3411
_registers.__regs[regNum] = value;
3412
return;
3413
}
3414
3415
switch (regNum) {
3416
case UNW_REG_IP:
3417
_registers.__regs[UNW_SPARC_O7] = value;
3418
return;
3419
case UNW_REG_SP:
3420
_registers.__regs[UNW_SPARC_O6] = value;
3421
return;
3422
}
3423
_LIBUNWIND_ABORT("unsupported sparc register");
3424
}
3425
3426
inline bool Registers_sparc::validFloatRegister(int) const { return false; }
3427
3428
inline double Registers_sparc::getFloatRegister(int) const {
3429
_LIBUNWIND_ABORT("no Sparc float registers");
3430
}
3431
3432
inline void Registers_sparc::setFloatRegister(int, double) {
3433
_LIBUNWIND_ABORT("no Sparc float registers");
3434
}
3435
3436
inline bool Registers_sparc::validVectorRegister(int) const { return false; }
3437
3438
inline v128 Registers_sparc::getVectorRegister(int) const {
3439
_LIBUNWIND_ABORT("no Sparc vector registers");
3440
}
3441
3442
inline void Registers_sparc::setVectorRegister(int, v128) {
3443
_LIBUNWIND_ABORT("no Sparc vector registers");
3444
}
3445
3446
inline const char *Registers_sparc::getRegisterName(int regNum) {
3447
switch (regNum) {
3448
case UNW_REG_IP:
3449
return "pc";
3450
case UNW_SPARC_G0:
3451
return "g0";
3452
case UNW_SPARC_G1:
3453
return "g1";
3454
case UNW_SPARC_G2:
3455
return "g2";
3456
case UNW_SPARC_G3:
3457
return "g3";
3458
case UNW_SPARC_G4:
3459
return "g4";
3460
case UNW_SPARC_G5:
3461
return "g5";
3462
case UNW_SPARC_G6:
3463
return "g6";
3464
case UNW_SPARC_G7:
3465
return "g7";
3466
case UNW_SPARC_O0:
3467
return "o0";
3468
case UNW_SPARC_O1:
3469
return "o1";
3470
case UNW_SPARC_O2:
3471
return "o2";
3472
case UNW_SPARC_O3:
3473
return "o3";
3474
case UNW_SPARC_O4:
3475
return "o4";
3476
case UNW_SPARC_O5:
3477
return "o5";
3478
case UNW_REG_SP:
3479
case UNW_SPARC_O6:
3480
return "sp";
3481
case UNW_SPARC_O7:
3482
return "o7";
3483
case UNW_SPARC_L0:
3484
return "l0";
3485
case UNW_SPARC_L1:
3486
return "l1";
3487
case UNW_SPARC_L2:
3488
return "l2";
3489
case UNW_SPARC_L3:
3490
return "l3";
3491
case UNW_SPARC_L4:
3492
return "l4";
3493
case UNW_SPARC_L5:
3494
return "l5";
3495
case UNW_SPARC_L6:
3496
return "l6";
3497
case UNW_SPARC_L7:
3498
return "l7";
3499
case UNW_SPARC_I0:
3500
return "i0";
3501
case UNW_SPARC_I1:
3502
return "i1";
3503
case UNW_SPARC_I2:
3504
return "i2";
3505
case UNW_SPARC_I3:
3506
return "i3";
3507
case UNW_SPARC_I4:
3508
return "i4";
3509
case UNW_SPARC_I5:
3510
return "i5";
3511
case UNW_SPARC_I6:
3512
return "fp";
3513
case UNW_SPARC_I7:
3514
return "i7";
3515
default:
3516
return "unknown register";
3517
}
3518
}
3519
#endif // _LIBUNWIND_TARGET_SPARC
3520
3521
} // namespace libunwind
3522
3523
#endif // __REGISTERS_HPP__
3524
3525