]>
Commit | Line | Data |
---|---|---|
afe874b1 A |
1 | /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- |
2 | * | |
f80fe69f | 3 | * Copyright (c) 2007-2011 Apple Inc. All rights reserved. |
afe874b1 A |
4 | * |
5 | * @APPLE_LICENSE_HEADER_START@ | |
6 | * | |
7 | * This file contains Original Code and/or Modifications of Original Code | |
8 | * as defined in and that are subject to the Apple Public Source License | |
9 | * Version 2.0 (the 'License'). You may not use this file except in | |
10 | * compliance with the License. Please obtain a copy of the License at | |
11 | * http://www.opensource.apple.com/apsl/ and read it before using this | |
12 | * file. | |
13 | * | |
14 | * The Original Code and all software distributed under the License are | |
15 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
16 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
17 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
18 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | |
19 | * Please see the License for the specific language governing rights and | |
20 | * limitations under the License. | |
21 | * | |
22 | * @APPLE_LICENSE_HEADER_END@ | |
23 | */ | |
24 | ||
25 | // | |
26 | // C++ interface to lower levels of libuwind | |
27 | // | |
28 | ||
29 | #ifndef __REGISTERS_HPP__ | |
30 | #define __REGISTERS_HPP__ | |
31 | ||
32 | #include <stdint.h> | |
33 | #include <stdio.h> | |
34 | #include <stdlib.h> | |
35 | #include <dlfcn.h> | |
36 | #include <mach-o/loader.h> | |
37 | #include <mach-o/getsect.h> | |
38 | #include <mach/i386/thread_status.h> | |
39 | ||
40 | #include "libunwind.h" | |
41 | #include "InternalMacros.h" | |
42 | ||
43 | namespace libunwind { | |
44 | ||
45 | ||
46 | /// | |
47 | /// Registers_x86 holds the register state of a thread in a 32-bit intel process. | |
48 | /// | |
49 | class Registers_x86 | |
50 | { | |
51 | public: | |
52 | Registers_x86(); | |
53 | Registers_x86(const void* registers); | |
54 | ||
55 | bool validRegister(int num) const; | |
56 | uint32_t getRegister(int num) const; | |
57 | void setRegister(int num, uint32_t value); | |
58 | bool validFloatRegister(int num) const { return false; } | |
59 | double getFloatRegister(int num) const; | |
60 | void setFloatRegister(int num, double value); | |
61 | bool validVectorRegister(int num) const { return false; } | |
62 | v128 getVectorRegister(int num) const; | |
63 | void setVectorRegister(int num, v128 value); | |
64 | const char* getRegisterName(int num); | |
65 | void jumpto(); | |
66 | ||
67 | uint32_t getSP() const { return fRegisters.__esp; } | |
68 | void setSP(uint32_t value) { fRegisters.__esp = value; } | |
69 | uint32_t getIP() const { return fRegisters.__eip; } | |
70 | void setIP(uint32_t value) { fRegisters.__eip = value; } | |
71 | uint32_t getEBP() const { return fRegisters.__ebp; } | |
72 | void setEBP(uint32_t value) { fRegisters.__ebp = value; } | |
73 | uint32_t getEBX() const { return fRegisters.__ebx; } | |
74 | void setEBX(uint32_t value) { fRegisters.__ebx = value; } | |
75 | uint32_t getECX() const { return fRegisters.__ecx; } | |
76 | void setECX(uint32_t value) { fRegisters.__ecx = value; } | |
77 | uint32_t getEDX() const { return fRegisters.__edx; } | |
78 | void setEDX(uint32_t value) { fRegisters.__edx = value; } | |
79 | uint32_t getESI() const { return fRegisters.__esi; } | |
80 | void setESI(uint32_t value) { fRegisters.__esi = value; } | |
81 | uint32_t getEDI() const { return fRegisters.__edi; } | |
82 | void setEDI(uint32_t value) { fRegisters.__edi = value; } | |
83 | ||
84 | private: | |
85 | i386_thread_state_t fRegisters; | |
86 | }; | |
87 | ||
88 | inline Registers_x86::Registers_x86(const void* registers) | |
89 | { | |
90 | COMPILE_TIME_ASSERT( sizeof(Registers_x86) < sizeof(unw_context_t) ); | |
91 | fRegisters = *((i386_thread_state_t*)registers); | |
92 | } | |
93 | ||
94 | inline Registers_x86::Registers_x86() | |
95 | { | |
96 | bzero(&fRegisters, sizeof(fRegisters)); | |
97 | } | |
98 | ||
99 | ||
100 | inline bool Registers_x86::validRegister(int regNum) const | |
101 | { | |
102 | if ( regNum == UNW_REG_IP ) | |
103 | return true; | |
104 | if ( regNum == UNW_REG_SP ) | |
105 | return true; | |
106 | if ( regNum < 0 ) | |
107 | return false; | |
108 | if ( regNum > 7 ) | |
109 | return false; | |
110 | return true; | |
111 | } | |
112 | ||
113 | inline uint32_t Registers_x86::getRegister(int regNum) const | |
114 | { | |
115 | switch ( regNum ) { | |
116 | case UNW_REG_IP: | |
117 | return fRegisters.__eip; | |
118 | case UNW_REG_SP: | |
119 | return fRegisters.__esp; | |
120 | case UNW_X86_EAX: | |
121 | return fRegisters.__eax; | |
122 | case UNW_X86_ECX: | |
123 | return fRegisters.__ecx; | |
124 | case UNW_X86_EDX: | |
125 | return fRegisters.__edx; | |
126 | case UNW_X86_EBX: | |
127 | return fRegisters.__ebx; | |
128 | case UNW_X86_EBP: | |
129 | return fRegisters.__ebp; | |
130 | case UNW_X86_ESP: | |
131 | return fRegisters.__esp; | |
132 | case UNW_X86_ESI: | |
133 | return fRegisters.__esi; | |
134 | case UNW_X86_EDI: | |
135 | return fRegisters.__edi; | |
136 | } | |
137 | ABORT("unsupported x86 register"); | |
138 | } | |
139 | ||
140 | inline void Registers_x86::setRegister(int regNum, uint32_t value) | |
141 | { | |
142 | switch ( regNum ) { | |
143 | case UNW_REG_IP: | |
144 | fRegisters.__eip = value; | |
145 | return; | |
146 | case UNW_REG_SP: | |
147 | fRegisters.__esp = value; | |
148 | return; | |
149 | case UNW_X86_EAX: | |
150 | fRegisters.__eax = value; | |
151 | return; | |
152 | case UNW_X86_ECX: | |
153 | fRegisters.__ecx = value; | |
154 | return; | |
155 | case UNW_X86_EDX: | |
156 | fRegisters.__edx = value; | |
157 | return; | |
158 | case UNW_X86_EBX: | |
159 | fRegisters.__ebx = value; | |
160 | return; | |
161 | case UNW_X86_EBP: | |
162 | fRegisters.__ebp = value; | |
163 | return; | |
164 | case UNW_X86_ESP: | |
165 | fRegisters.__esp = value; | |
166 | return; | |
167 | case UNW_X86_ESI: | |
168 | fRegisters.__esi = value; | |
169 | return; | |
170 | case UNW_X86_EDI: | |
171 | fRegisters.__edi = value; | |
172 | return; | |
173 | } | |
174 | ABORT("unsupported x86 register"); | |
175 | } | |
176 | ||
177 | inline const char* Registers_x86::getRegisterName(int regNum) | |
178 | { | |
179 | switch ( regNum ) { | |
180 | case UNW_REG_IP: | |
181 | return "ip"; | |
182 | case UNW_REG_SP: | |
183 | return "esp"; | |
184 | case UNW_X86_EAX: | |
185 | return "eax"; | |
186 | case UNW_X86_ECX: | |
187 | return "ecx"; | |
188 | case UNW_X86_EDX: | |
189 | return "edx"; | |
190 | case UNW_X86_EBX: | |
191 | return "ebx"; | |
192 | case UNW_X86_EBP: | |
193 | return "ebp"; | |
194 | case UNW_X86_ESP: | |
195 | return "esp"; | |
196 | case UNW_X86_ESI: | |
197 | return "esi"; | |
198 | case UNW_X86_EDI: | |
199 | return "edi"; | |
200 | default: | |
201 | return "unknown register"; | |
202 | } | |
203 | } | |
204 | ||
205 | inline double Registers_x86::getFloatRegister(int num) const | |
206 | { | |
207 | ABORT("no x86 float registers"); | |
208 | } | |
209 | ||
210 | inline void Registers_x86::setFloatRegister(int num, double value) | |
211 | { | |
212 | ABORT("no x86 float registers"); | |
213 | } | |
214 | ||
215 | inline v128 Registers_x86::getVectorRegister(int num) const | |
216 | { | |
217 | ABORT("no x86 vector registers"); | |
218 | } | |
219 | ||
220 | inline void Registers_x86::setVectorRegister(int num, v128 value) | |
221 | { | |
222 | ABORT("no x86 vector registers"); | |
223 | } | |
224 | ||
225 | ||
226 | ||
227 | ||
228 | /// | |
229 | /// Registers_x86_64 holds the register state of a thread in a 64-bit intel process. | |
230 | /// | |
231 | class Registers_x86_64 | |
232 | { | |
233 | public: | |
234 | Registers_x86_64(); | |
235 | Registers_x86_64(const void* registers); | |
236 | ||
237 | bool validRegister(int num) const; | |
238 | uint64_t getRegister(int num) const; | |
239 | void setRegister(int num, uint64_t value); | |
240 | bool validFloatRegister(int num) const{ return false; } | |
241 | double getFloatRegister(int num) const; | |
242 | void setFloatRegister(int num, double value); | |
243 | bool validVectorRegister(int num) const { return false; } | |
244 | v128 getVectorRegister(int num) const; | |
245 | void setVectorRegister(int num, v128 value); | |
246 | const char* getRegisterName(int num); | |
247 | void jumpto(); | |
248 | uint64_t getSP() const { return fRegisters.__rsp; } | |
249 | void setSP(uint64_t value) { fRegisters.__rsp = value; } | |
250 | uint64_t getIP() const { return fRegisters.__rip; } | |
251 | void setIP(uint64_t value) { fRegisters.__rip = value; } | |
252 | uint64_t getRBP() const { return fRegisters.__rbp; } | |
253 | void setRBP(uint64_t value) { fRegisters.__rbp = value; } | |
254 | uint64_t getRBX() const { return fRegisters.__rbx; } | |
255 | void setRBX(uint64_t value) { fRegisters.__rbx = value; } | |
256 | uint64_t getR12() const { return fRegisters.__r12; } | |
257 | void setR12(uint64_t value) { fRegisters.__r12 = value; } | |
258 | uint64_t getR13() const { return fRegisters.__r13; } | |
259 | void setR13(uint64_t value) { fRegisters.__r13 = value; } | |
260 | uint64_t getR14() const { return fRegisters.__r14; } | |
261 | void setR14(uint64_t value) { fRegisters.__r14 = value; } | |
262 | uint64_t getR15() const { return fRegisters.__r15; } | |
263 | void setR15(uint64_t value) { fRegisters.__r15 = value; } | |
264 | private: | |
265 | x86_thread_state64_t fRegisters; | |
266 | }; | |
267 | ||
268 | inline Registers_x86_64::Registers_x86_64(const void* registers) | |
269 | { | |
270 | COMPILE_TIME_ASSERT( sizeof(Registers_x86_64) < sizeof(unw_context_t) ); | |
271 | fRegisters = *((x86_thread_state64_t*)registers); | |
272 | } | |
273 | ||
274 | inline Registers_x86_64::Registers_x86_64() | |
275 | { | |
276 | bzero(&fRegisters, sizeof(fRegisters)); | |
277 | } | |
278 | ||
279 | ||
280 | inline bool Registers_x86_64::validRegister(int regNum) const | |
281 | { | |
282 | if ( regNum == UNW_REG_IP ) | |
283 | return true; | |
284 | if ( regNum == UNW_REG_SP ) | |
285 | return true; | |
286 | if ( regNum < 0 ) | |
287 | return false; | |
288 | if ( regNum > 15 ) | |
289 | return false; | |
290 | return true; | |
291 | } | |
292 | ||
293 | inline uint64_t Registers_x86_64::getRegister(int regNum) const | |
294 | { | |
295 | switch ( regNum ) { | |
296 | case UNW_REG_IP: | |
297 | return fRegisters.__rip; | |
298 | case UNW_REG_SP: | |
299 | return fRegisters.__rsp; | |
300 | case UNW_X86_64_RAX: | |
301 | return fRegisters.__rax; | |
302 | case UNW_X86_64_RDX: | |
303 | return fRegisters.__rdx; | |
304 | case UNW_X86_64_RCX: | |
305 | return fRegisters.__rcx; | |
306 | case UNW_X86_64_RBX: | |
307 | return fRegisters.__rbx; | |
308 | case UNW_X86_64_RSI: | |
309 | return fRegisters.__rsi; | |
310 | case UNW_X86_64_RDI: | |
311 | return fRegisters.__rdi; | |
312 | case UNW_X86_64_RBP: | |
313 | return fRegisters.__rbp; | |
314 | case UNW_X86_64_RSP: | |
315 | return fRegisters.__rsp; | |
316 | case UNW_X86_64_R8: | |
317 | return fRegisters.__r8; | |
318 | case UNW_X86_64_R9: | |
319 | return fRegisters.__r9; | |
320 | case UNW_X86_64_R10: | |
321 | return fRegisters.__r10; | |
322 | case UNW_X86_64_R11: | |
323 | return fRegisters.__r11; | |
324 | case UNW_X86_64_R12: | |
325 | return fRegisters.__r12; | |
326 | case UNW_X86_64_R13: | |
327 | return fRegisters.__r13; | |
328 | case UNW_X86_64_R14: | |
329 | return fRegisters.__r14; | |
330 | case UNW_X86_64_R15: | |
331 | return fRegisters.__r15; | |
332 | } | |
333 | ABORT("unsupported x86_64 register"); | |
334 | } | |
335 | ||
336 | inline void Registers_x86_64::setRegister(int regNum, uint64_t value) | |
337 | { | |
338 | switch ( regNum ) { | |
339 | case UNW_REG_IP: | |
340 | fRegisters.__rip = value; | |
341 | return; | |
342 | case UNW_REG_SP: | |
343 | fRegisters.__rsp = value; | |
344 | return; | |
345 | case UNW_X86_64_RAX: | |
346 | fRegisters.__rax = value; | |
347 | return; | |
348 | case UNW_X86_64_RDX: | |
349 | fRegisters.__rdx = value; | |
350 | return; | |
351 | case UNW_X86_64_RCX: | |
352 | fRegisters.__rcx = value; | |
353 | return; | |
354 | case UNW_X86_64_RBX: | |
355 | fRegisters.__rbx = value; | |
356 | return; | |
357 | case UNW_X86_64_RSI: | |
358 | fRegisters.__rsi = value; | |
359 | return; | |
360 | case UNW_X86_64_RDI: | |
361 | fRegisters.__rdi = value; | |
362 | return; | |
363 | case UNW_X86_64_RBP: | |
364 | fRegisters.__rbp = value; | |
365 | return; | |
366 | case UNW_X86_64_RSP: | |
367 | fRegisters.__rsp = value; | |
368 | return; | |
369 | case UNW_X86_64_R8: | |
370 | fRegisters.__r8 = value; | |
371 | return; | |
372 | case UNW_X86_64_R9: | |
373 | fRegisters.__r9 = value; | |
374 | return; | |
375 | case UNW_X86_64_R10: | |
376 | fRegisters.__r10 = value; | |
377 | return; | |
378 | case UNW_X86_64_R11: | |
379 | fRegisters.__r11 = value; | |
380 | return; | |
381 | case UNW_X86_64_R12: | |
382 | fRegisters.__r12 = value; | |
383 | return; | |
384 | case UNW_X86_64_R13: | |
385 | fRegisters.__r13 = value; | |
386 | return; | |
387 | case UNW_X86_64_R14: | |
388 | fRegisters.__r14 = value; | |
389 | return; | |
390 | case UNW_X86_64_R15: | |
391 | fRegisters.__r15 = value; | |
392 | return; | |
393 | } | |
394 | ABORT("unsupported x86_64 register"); | |
395 | } | |
396 | ||
397 | inline const char* Registers_x86_64::getRegisterName(int regNum) | |
398 | { | |
399 | switch ( regNum ) { | |
400 | case UNW_REG_IP: | |
401 | return "rip"; | |
402 | case UNW_REG_SP: | |
403 | return "rsp"; | |
404 | case UNW_X86_64_RAX: | |
405 | return "rax"; | |
406 | case UNW_X86_64_RDX: | |
407 | return "rdx"; | |
408 | case UNW_X86_64_RCX: | |
409 | return "rcx"; | |
410 | case UNW_X86_64_RBX: | |
411 | return "rbx"; | |
412 | case UNW_X86_64_RSI: | |
413 | return "rsi"; | |
414 | case UNW_X86_64_RDI: | |
415 | return "rdi"; | |
416 | case UNW_X86_64_RBP: | |
417 | return "rbp"; | |
418 | case UNW_X86_64_RSP: | |
419 | return "rsp"; | |
420 | case UNW_X86_64_R8: | |
421 | return "r8"; | |
422 | case UNW_X86_64_R9: | |
423 | return "r9"; | |
424 | case UNW_X86_64_R10: | |
425 | return "r10"; | |
426 | case UNW_X86_64_R11: | |
427 | return "r11"; | |
428 | case UNW_X86_64_R12: | |
429 | return "r12"; | |
430 | case UNW_X86_64_R13: | |
431 | return "r13"; | |
432 | case UNW_X86_64_R14: | |
433 | return "r14"; | |
434 | case UNW_X86_64_R15: | |
435 | return "r15"; | |
436 | default: | |
437 | return "unknown register"; | |
438 | } | |
439 | } | |
440 | ||
441 | double Registers_x86_64::getFloatRegister(int num) const | |
442 | { | |
443 | ABORT("no x86_64 float registers"); | |
444 | } | |
445 | ||
446 | void Registers_x86_64::setFloatRegister(int num, double value) | |
447 | { | |
448 | ABORT("no x86_64 float registers"); | |
449 | } | |
450 | ||
451 | inline v128 Registers_x86_64::getVectorRegister(int num) const | |
452 | { | |
453 | ABORT("no x86_64 vector registers"); | |
454 | } | |
455 | ||
456 | inline void Registers_x86_64::setVectorRegister(int num, v128 value) | |
457 | { | |
458 | ABORT("no x86_64 vector registers"); | |
459 | } | |
460 | ||
461 | ||
462 | /// | |
463 | /// Registers_ppc holds the register state of a thread in a 32-bit PowerPC process. | |
464 | /// | |
465 | class Registers_ppc | |
466 | { | |
467 | public: | |
468 | Registers_ppc(); | |
469 | Registers_ppc(const void* registers); | |
470 | ||
471 | bool validRegister(int num) const; | |
472 | uint32_t getRegister(int num) const; | |
473 | void setRegister(int num, uint32_t value); | |
474 | bool validFloatRegister(int num) const; | |
475 | double getFloatRegister(int num) const; | |
476 | void setFloatRegister(int num, double value); | |
477 | bool validVectorRegister(int num) const; | |
478 | v128 getVectorRegister(int num) const; | |
479 | void setVectorRegister(int num, v128 value); | |
480 | void jumpto(); | |
481 | const char* getRegisterName(int num); | |
482 | uint64_t getSP() const { return fRegisters.__r1; } | |
483 | void setSP(uint64_t value) { fRegisters.__r1 = value; } | |
484 | uint64_t getIP() const { return fRegisters.__srr0; } | |
485 | void setIP(uint64_t value) { fRegisters.__srr0 = value; } | |
486 | private: | |
487 | struct ppc_thread_state_t | |
488 | { | |
489 | unsigned int __srr0; /* Instruction address register (PC) */ | |
490 | unsigned int __srr1; /* Machine state register (supervisor) */ | |
491 | unsigned int __r0; | |
492 | unsigned int __r1; | |
493 | unsigned int __r2; | |
494 | unsigned int __r3; | |
495 | unsigned int __r4; | |
496 | unsigned int __r5; | |
497 | unsigned int __r6; | |
498 | unsigned int __r7; | |
499 | unsigned int __r8; | |
500 | unsigned int __r9; | |
501 | unsigned int __r10; | |
502 | unsigned int __r11; | |
503 | unsigned int __r12; | |
504 | unsigned int __r13; | |
505 | unsigned int __r14; | |
506 | unsigned int __r15; | |
507 | unsigned int __r16; | |
508 | unsigned int __r17; | |
509 | unsigned int __r18; | |
510 | unsigned int __r19; | |
511 | unsigned int __r20; | |
512 | unsigned int __r21; | |
513 | unsigned int __r22; | |
514 | unsigned int __r23; | |
515 | unsigned int __r24; | |
516 | unsigned int __r25; | |
517 | unsigned int __r26; | |
518 | unsigned int __r27; | |
519 | unsigned int __r28; | |
520 | unsigned int __r29; | |
521 | unsigned int __r30; | |
522 | unsigned int __r31; | |
523 | unsigned int __cr; /* Condition register */ | |
524 | unsigned int __xer; /* User's integer exception register */ | |
525 | unsigned int __lr; /* Link register */ | |
526 | unsigned int __ctr; /* Count register */ | |
527 | unsigned int __mq; /* MQ register (601 only) */ | |
528 | unsigned int __vrsave; /* Vector Save Register */ | |
529 | }; | |
530 | ||
531 | struct ppc_float_state_t | |
532 | { | |
533 | double __fpregs[32]; | |
534 | ||
535 | unsigned int __fpscr_pad; /* fpscr is 64 bits, 32 bits of rubbish */ | |
536 | unsigned int __fpscr; /* floating point status register */ | |
537 | }; | |
538 | ||
539 | ppc_thread_state_t fRegisters; | |
540 | ppc_float_state_t fFloatRegisters; | |
541 | v128 fVectorRegisters[32]; // offset 424 | |
542 | }; | |
543 | ||
544 | ||
545 | ||
546 | inline Registers_ppc::Registers_ppc(const void* registers) | |
547 | { | |
548 | COMPILE_TIME_ASSERT( sizeof(Registers_ppc) < sizeof(unw_context_t) ); | |
549 | fRegisters = *((ppc_thread_state_t*)registers); | |
550 | fFloatRegisters = *((ppc_float_state_t*)((char*)registers+160)); | |
551 | memcpy(fVectorRegisters, ((char*)registers+424), sizeof(fVectorRegisters)); | |
552 | } | |
553 | ||
554 | inline Registers_ppc::Registers_ppc() | |
555 | { | |
556 | bzero(&fRegisters, sizeof(fRegisters)); | |
557 | bzero(&fFloatRegisters, sizeof(fFloatRegisters)); | |
558 | bzero(&fVectorRegisters, sizeof(fVectorRegisters)); | |
559 | } | |
560 | ||
561 | ||
562 | inline bool Registers_ppc::validRegister(int regNum) const | |
563 | { | |
564 | if ( regNum == UNW_REG_IP ) | |
565 | return true; | |
566 | if ( regNum == UNW_REG_SP ) | |
567 | return true; | |
568 | if ( regNum == UNW_PPC_VRSAVE ) | |
569 | return true; | |
570 | if ( regNum < 0 ) | |
571 | return false; | |
572 | if ( regNum <= UNW_PPC_R31 ) | |
573 | return true; | |
574 | if ( regNum == UNW_PPC_MQ ) | |
575 | return true; | |
576 | if ( regNum == UNW_PPC_LR ) | |
577 | return true; | |
578 | if ( regNum == UNW_PPC_CTR ) | |
579 | return true; | |
580 | if ( (UNW_PPC_CR0 <= regNum) && (regNum <= UNW_PPC_CR7) ) | |
581 | return true; | |
582 | return false; | |
583 | } | |
584 | ||
585 | ||
586 | inline uint32_t Registers_ppc::getRegister(int regNum) const | |
587 | { | |
588 | switch ( regNum ) { | |
589 | case UNW_REG_IP: | |
590 | return fRegisters.__srr0; | |
591 | case UNW_REG_SP: | |
592 | return fRegisters.__r1; | |
593 | case UNW_PPC_R0: | |
594 | return fRegisters.__r0; | |
595 | case UNW_PPC_R1: | |
596 | return fRegisters.__r1; | |
597 | case UNW_PPC_R2: | |
598 | return fRegisters.__r2; | |
599 | case UNW_PPC_R3: | |
600 | return fRegisters.__r3; | |
601 | case UNW_PPC_R4: | |
602 | return fRegisters.__r4; | |
603 | case UNW_PPC_R5: | |
604 | return fRegisters.__r5; | |
605 | case UNW_PPC_R6: | |
606 | return fRegisters.__r6; | |
607 | case UNW_PPC_R7: | |
608 | return fRegisters.__r7; | |
609 | case UNW_PPC_R8: | |
610 | return fRegisters.__r8; | |
611 | case UNW_PPC_R9: | |
612 | return fRegisters.__r9; | |
613 | case UNW_PPC_R10: | |
614 | return fRegisters.__r10; | |
615 | case UNW_PPC_R11: | |
616 | return fRegisters.__r11; | |
617 | case UNW_PPC_R12: | |
618 | return fRegisters.__r12; | |
619 | case UNW_PPC_R13: | |
620 | return fRegisters.__r13; | |
621 | case UNW_PPC_R14: | |
622 | return fRegisters.__r14; | |
623 | case UNW_PPC_R15: | |
624 | return fRegisters.__r15; | |
625 | case UNW_PPC_R16: | |
626 | return fRegisters.__r16; | |
627 | case UNW_PPC_R17: | |
628 | return fRegisters.__r17; | |
629 | case UNW_PPC_R18: | |
630 | return fRegisters.__r18; | |
631 | case UNW_PPC_R19: | |
632 | return fRegisters.__r19; | |
633 | case UNW_PPC_R20: | |
634 | return fRegisters.__r20; | |
635 | case UNW_PPC_R21: | |
636 | return fRegisters.__r21; | |
637 | case UNW_PPC_R22: | |
638 | return fRegisters.__r22; | |
639 | case UNW_PPC_R23: | |
640 | return fRegisters.__r23; | |
641 | case UNW_PPC_R24: | |
642 | return fRegisters.__r24; | |
643 | case UNW_PPC_R25: | |
644 | return fRegisters.__r25; | |
645 | case UNW_PPC_R26: | |
646 | return fRegisters.__r26; | |
647 | case UNW_PPC_R27: | |
648 | return fRegisters.__r27; | |
649 | case UNW_PPC_R28: | |
650 | return fRegisters.__r28; | |
651 | case UNW_PPC_R29: | |
652 | return fRegisters.__r29; | |
653 | case UNW_PPC_R30: | |
654 | return fRegisters.__r30; | |
655 | case UNW_PPC_R31: | |
656 | return fRegisters.__r31; | |
657 | case UNW_PPC_LR: | |
658 | return fRegisters.__lr; | |
659 | case UNW_PPC_CR0: | |
660 | return (fRegisters.__cr & 0xF0000000); | |
661 | case UNW_PPC_CR1: | |
662 | return (fRegisters.__cr & 0x0F000000); | |
663 | case UNW_PPC_CR2: | |
664 | return (fRegisters.__cr & 0x00F00000); | |
665 | case UNW_PPC_CR3: | |
666 | return (fRegisters.__cr & 0x000F0000); | |
667 | case UNW_PPC_CR4: | |
668 | return (fRegisters.__cr & 0x0000F000); | |
669 | case UNW_PPC_CR5: | |
670 | return (fRegisters.__cr & 0x00000F00); | |
671 | case UNW_PPC_CR6: | |
672 | return (fRegisters.__cr & 0x000000F0); | |
673 | case UNW_PPC_CR7: | |
674 | return (fRegisters.__cr & 0x0000000F); | |
675 | case UNW_PPC_VRSAVE: | |
676 | return fRegisters.__vrsave; | |
677 | } | |
678 | ABORT("unsupported ppc register"); | |
679 | } | |
680 | ||
681 | ||
682 | inline void Registers_ppc::setRegister(int regNum, uint32_t value) | |
683 | { | |
684 | //fprintf(stderr, "Registers_ppc::setRegister(%d, 0x%08X)\n", regNum, value); | |
685 | switch ( regNum ) { | |
686 | case UNW_REG_IP: | |
687 | fRegisters.__srr0 = value; | |
688 | return; | |
689 | case UNW_REG_SP: | |
690 | fRegisters.__r1 = value; | |
691 | return; | |
692 | case UNW_PPC_R0: | |
693 | fRegisters.__r0 = value; | |
694 | return; | |
695 | case UNW_PPC_R1: | |
696 | fRegisters.__r1 = value; | |
697 | return; | |
698 | case UNW_PPC_R2: | |
699 | fRegisters.__r2 = value; | |
700 | return; | |
701 | case UNW_PPC_R3: | |
702 | fRegisters.__r3 = value; | |
703 | return; | |
704 | case UNW_PPC_R4: | |
705 | fRegisters.__r4 = value; | |
706 | return; | |
707 | case UNW_PPC_R5: | |
708 | fRegisters.__r5 = value; | |
709 | return; | |
710 | case UNW_PPC_R6: | |
711 | fRegisters.__r6 = value; | |
712 | return; | |
713 | case UNW_PPC_R7: | |
714 | fRegisters.__r7 = value; | |
715 | return; | |
716 | case UNW_PPC_R8: | |
717 | fRegisters.__r8 = value; | |
718 | return; | |
719 | case UNW_PPC_R9: | |
720 | fRegisters.__r9 = value; | |
721 | return; | |
722 | case UNW_PPC_R10: | |
723 | fRegisters.__r10 = value; | |
724 | return; | |
725 | case UNW_PPC_R11: | |
726 | fRegisters.__r11 = value; | |
727 | return; | |
728 | case UNW_PPC_R12: | |
729 | fRegisters.__r12 = value; | |
730 | return; | |
731 | case UNW_PPC_R13: | |
732 | fRegisters.__r13 = value; | |
733 | return; | |
734 | case UNW_PPC_R14: | |
735 | fRegisters.__r14 = value; | |
736 | return; | |
737 | case UNW_PPC_R15: | |
738 | fRegisters.__r15 = value; | |
739 | return; | |
740 | case UNW_PPC_R16: | |
741 | fRegisters.__r16 = value; | |
742 | return; | |
743 | case UNW_PPC_R17: | |
744 | fRegisters.__r17 = value; | |
745 | return; | |
746 | case UNW_PPC_R18: | |
747 | fRegisters.__r18 = value; | |
748 | return; | |
749 | case UNW_PPC_R19: | |
750 | fRegisters.__r19 = value; | |
751 | return; | |
752 | case UNW_PPC_R20: | |
753 | fRegisters.__r20 = value; | |
754 | return; | |
755 | case UNW_PPC_R21: | |
756 | fRegisters.__r21 = value; | |
757 | return; | |
758 | case UNW_PPC_R22: | |
759 | fRegisters.__r22 = value; | |
760 | return; | |
761 | case UNW_PPC_R23: | |
762 | fRegisters.__r23 = value; | |
763 | return; | |
764 | case UNW_PPC_R24: | |
765 | fRegisters.__r24 = value; | |
766 | return; | |
767 | case UNW_PPC_R25: | |
768 | fRegisters.__r25 = value; | |
769 | return; | |
770 | case UNW_PPC_R26: | |
771 | fRegisters.__r26 = value; | |
772 | return; | |
773 | case UNW_PPC_R27: | |
774 | fRegisters.__r27 = value; | |
775 | return; | |
776 | case UNW_PPC_R28: | |
777 | fRegisters.__r28 = value; | |
778 | return; | |
779 | case UNW_PPC_R29: | |
780 | fRegisters.__r29 = value; | |
781 | return; | |
782 | case UNW_PPC_R30: | |
783 | fRegisters.__r30 = value; | |
784 | return; | |
785 | case UNW_PPC_R31: | |
786 | fRegisters.__r31 = value; | |
787 | return; | |
788 | case UNW_PPC_MQ: | |
789 | fRegisters.__mq = value; | |
790 | return; | |
791 | case UNW_PPC_LR: | |
792 | fRegisters.__lr = value; | |
793 | return; | |
794 | case UNW_PPC_CTR: | |
795 | fRegisters.__ctr = value; | |
796 | return; | |
797 | case UNW_PPC_CR0: | |
798 | fRegisters.__cr &= 0x0FFFFFFF; | |
799 | fRegisters.__cr |= (value & 0xF0000000); | |
800 | return; | |
801 | case UNW_PPC_CR1: | |
802 | fRegisters.__cr &= 0xF0FFFFFF; | |
803 | fRegisters.__cr |= (value & 0x0F000000); | |
804 | return; | |
805 | case UNW_PPC_CR2: | |
806 | fRegisters.__cr &= 0xFF0FFFFF; | |
807 | fRegisters.__cr |= (value & 0x00F00000); | |
808 | return; | |
809 | case UNW_PPC_CR3: | |
810 | fRegisters.__cr &= 0xFFF0FFFF; | |
811 | fRegisters.__cr |= (value & 0x000F0000); | |
812 | return; | |
813 | case UNW_PPC_CR4: | |
814 | fRegisters.__cr &= 0xFFFF0FFF; | |
815 | fRegisters.__cr |= (value & 0x0000F000); | |
816 | return; | |
817 | case UNW_PPC_CR5: | |
818 | fRegisters.__cr &= 0xFFFFF0FF; | |
819 | fRegisters.__cr |= (value & 0x00000F00); | |
820 | return; | |
821 | case UNW_PPC_CR6: | |
822 | fRegisters.__cr &= 0xFFFFFF0F; | |
823 | fRegisters.__cr |= (value & 0x000000F0); | |
824 | return; | |
825 | case UNW_PPC_CR7: | |
826 | fRegisters.__cr &= 0xFFFFFFF0; | |
827 | fRegisters.__cr |= (value & 0x0000000F); | |
828 | return; | |
829 | case UNW_PPC_VRSAVE: | |
830 | fRegisters.__vrsave = value; | |
831 | return; | |
832 | // not saved | |
833 | return; | |
834 | case UNW_PPC_XER: | |
835 | fRegisters.__xer = value; | |
836 | return; | |
837 | case UNW_PPC_AP: | |
838 | case UNW_PPC_VSCR: | |
839 | case UNW_PPC_SPEFSCR: | |
840 | // not saved | |
841 | return; | |
842 | } | |
843 | ABORT("unsupported ppc register"); | |
844 | } | |
845 | ||
846 | inline bool Registers_ppc::validFloatRegister(int regNum) const | |
847 | { | |
848 | if ( regNum < UNW_PPC_F0 ) | |
849 | return false; | |
850 | if ( regNum > UNW_PPC_F31 ) | |
851 | return false; | |
852 | return true; | |
853 | } | |
854 | ||
855 | inline double Registers_ppc::getFloatRegister(int regNum) const | |
856 | { | |
857 | assert(validFloatRegister(regNum)); | |
858 | return fFloatRegisters.__fpregs[regNum-UNW_PPC_F0]; | |
859 | } | |
860 | ||
861 | inline void Registers_ppc::setFloatRegister(int regNum, double value) | |
862 | { | |
863 | //fprintf(stderr, "Registers_ppc::setFloatRegister(%d, %g))\n", regNum, value); | |
864 | assert(validFloatRegister(regNum)); | |
865 | fFloatRegisters.__fpregs[regNum-UNW_PPC_F0] = value; | |
866 | } | |
867 | ||
868 | ||
869 | inline bool Registers_ppc::validVectorRegister(int regNum) const | |
870 | { | |
871 | if ( regNum < UNW_PPC_V0 ) | |
872 | return false; | |
873 | if ( regNum > UNW_PPC_V31 ) | |
874 | return false; | |
875 | return true; | |
876 | } | |
877 | ||
878 | v128 Registers_ppc::getVectorRegister(int regNum) const | |
879 | { | |
880 | assert(validVectorRegister(regNum)); | |
881 | v128 result = fVectorRegisters[regNum-UNW_PPC_V0]; | |
882 | //fprintf(stderr, "Registers_ppc::getVectorRegister(this=%p, %d) => <0x%08X, 0x%08X, 0x%08X, 0x%08X> \n", | |
883 | // this, regNum, result.vec[0], result.vec[1], result.vec[2], result.vec[3]); | |
884 | return result; | |
885 | } | |
886 | ||
887 | void Registers_ppc::setVectorRegister(int regNum, v128 value) | |
888 | { | |
889 | assert(validVectorRegister(regNum)); | |
890 | //fprintf(stderr, "Registers_ppc::setVectorRegister(this=%p, %d) <0x%08X, 0x%08X, 0x%08X, 0x%08X> => <0x%08X, 0x%08X, 0x%08X, 0x%08X> \n", | |
891 | // this, regNum, fVectorRegisters[regNum-UNW_PPC_V0].vec[0], fVectorRegisters[regNum-UNW_PPC_V0].vec[1], fVectorRegisters[regNum-UNW_PPC_V0].vec[2], | |
892 | // fVectorRegisters[regNum-UNW_PPC_V0].vec[3], value.vec[0], value.vec[1], value.vec[2], value.vec[3]); | |
893 | fVectorRegisters[regNum-UNW_PPC_V0] = value; | |
894 | } | |
895 | ||
896 | ||
897 | inline const char* Registers_ppc::getRegisterName(int regNum) | |
898 | { | |
899 | switch ( regNum ) { | |
900 | case UNW_REG_IP: | |
901 | return "ip"; | |
902 | case UNW_REG_SP: | |
903 | return "sp"; | |
904 | case UNW_PPC_R0: | |
905 | return "r0"; | |
906 | case UNW_PPC_R1: | |
907 | return "r1"; | |
908 | case UNW_PPC_R2: | |
909 | return "r2"; | |
910 | case UNW_PPC_R3: | |
911 | return "r3"; | |
912 | case UNW_PPC_R4: | |
913 | return "r4"; | |
914 | case UNW_PPC_R5: | |
915 | return "r5"; | |
916 | case UNW_PPC_R6: | |
917 | return "r6"; | |
918 | case UNW_PPC_R7: | |
919 | return "r7"; | |
920 | case UNW_PPC_R8: | |
921 | return "r8"; | |
922 | case UNW_PPC_R9: | |
923 | return "r9"; | |
924 | case UNW_PPC_R10: | |
925 | return "r10"; | |
926 | case UNW_PPC_R11: | |
927 | return "r11"; | |
928 | case UNW_PPC_R12: | |
929 | return "r12"; | |
930 | case UNW_PPC_R13: | |
931 | return "r13"; | |
932 | case UNW_PPC_R14: | |
933 | return "r14"; | |
934 | case UNW_PPC_R15: | |
935 | return "r15"; | |
936 | case UNW_PPC_R16: | |
937 | return "r16"; | |
938 | case UNW_PPC_R17: | |
939 | return "r17"; | |
940 | case UNW_PPC_R18: | |
941 | return "r18"; | |
942 | case UNW_PPC_R19: | |
943 | return "r19"; | |
944 | case UNW_PPC_R20: | |
945 | return "r20"; | |
946 | case UNW_PPC_R21: | |
947 | return "r21"; | |
948 | case UNW_PPC_R22: | |
949 | return "r22"; | |
950 | case UNW_PPC_R23: | |
951 | return "r23"; | |
952 | case UNW_PPC_R24: | |
953 | return "r24"; | |
954 | case UNW_PPC_R25: | |
955 | return "r25"; | |
956 | case UNW_PPC_R26: | |
957 | return "r26"; | |
958 | case UNW_PPC_R27: | |
959 | return "r27"; | |
960 | case UNW_PPC_R28: | |
961 | return "r28"; | |
962 | case UNW_PPC_R29: | |
963 | return "r29"; | |
964 | case UNW_PPC_R30: | |
965 | return "r30"; | |
966 | case UNW_PPC_R31: | |
967 | return "r31"; | |
968 | case UNW_PPC_F0: | |
969 | return "fp0"; | |
970 | case UNW_PPC_F1: | |
971 | return "fp1"; | |
972 | case UNW_PPC_F2: | |
973 | return "fp2"; | |
974 | case UNW_PPC_F3: | |
975 | return "fp3"; | |
976 | case UNW_PPC_F4: | |
977 | return "fp4"; | |
978 | case UNW_PPC_F5: | |
979 | return "fp5"; | |
980 | case UNW_PPC_F6: | |
981 | return "fp6"; | |
982 | case UNW_PPC_F7: | |
983 | return "fp7"; | |
984 | case UNW_PPC_F8: | |
985 | return "fp8"; | |
986 | case UNW_PPC_F9: | |
987 | return "fp9"; | |
988 | case UNW_PPC_F10: | |
989 | return "fp10"; | |
990 | case UNW_PPC_F11: | |
991 | return "fp11"; | |
992 | case UNW_PPC_F12: | |
993 | return "fp12"; | |
994 | case UNW_PPC_F13: | |
995 | return "fp13"; | |
996 | case UNW_PPC_F14: | |
997 | return "fp14"; | |
998 | case UNW_PPC_F15: | |
999 | return "fp15"; | |
1000 | case UNW_PPC_F16: | |
1001 | return "fp16"; | |
1002 | case UNW_PPC_F17: | |
1003 | return "fp17"; | |
1004 | case UNW_PPC_F18: | |
1005 | return "fp18"; | |
1006 | case UNW_PPC_F19: | |
1007 | return "fp19"; | |
1008 | case UNW_PPC_F20: | |
1009 | return "fp20"; | |
1010 | case UNW_PPC_F21: | |
1011 | return "fp21"; | |
1012 | case UNW_PPC_F22: | |
1013 | return "fp22"; | |
1014 | case UNW_PPC_F23: | |
1015 | return "fp23"; | |
1016 | case UNW_PPC_F24: | |
1017 | return "fp24"; | |
1018 | case UNW_PPC_F25: | |
1019 | return "fp25"; | |
1020 | case UNW_PPC_F26: | |
1021 | return "fp26"; | |
1022 | case UNW_PPC_F27: | |
1023 | return "fp27"; | |
1024 | case UNW_PPC_F28: | |
1025 | return "fp28"; | |
1026 | case UNW_PPC_F29: | |
1027 | return "fp29"; | |
1028 | case UNW_PPC_F30: | |
1029 | return "fp30"; | |
1030 | case UNW_PPC_F31: | |
1031 | return "fp31"; | |
1032 | case UNW_PPC_LR: | |
1033 | return "lr"; | |
1034 | default: | |
1035 | return "unknown register"; | |
1036 | } | |
1037 | ||
f80fe69f A |
1038 | } |
1039 | ||
1040 | ||
1041 | ||
1042 | ||
1043 | ||
1044 | struct arm_thread_state64_t | |
1045 | { | |
1046 | __uint64_t __x[29]; /* General purpose registers x0-x28 */ | |
1047 | __uint64_t __fp; /* Frame pointer x29 */ | |
1048 | __uint64_t __lr; /* Link register x30 */ | |
1049 | __uint64_t __sp; /* Stack pointer x31 */ | |
1050 | __uint64_t __pc; /* Program counter */ | |
1051 | __uint32_t __cpsr; /* Current program status register */ | |
1052 | __uint32_t padding[3]; /* round up struct size to be 0x110 */ | |
1053 | }; | |
1054 | ||
1055 | ||
1056 | /// | |
1057 | /// Registers_arm64 holds the register state of a thread in a 64-bit intel process. | |
1058 | /// | |
1059 | class Registers_arm64 | |
1060 | { | |
1061 | public: | |
1062 | Registers_arm64(); | |
1063 | Registers_arm64(const void* registers); | |
1064 | ||
1065 | bool validRegister(int num) const; | |
1066 | uint64_t getRegister(int num) const; | |
1067 | void setRegister(int num, uint64_t value); | |
1068 | bool validFloatRegister(int num) const; | |
1069 | double getFloatRegister(int num) const; | |
1070 | void setFloatRegister(int num, double value); | |
1071 | bool validVectorRegister(int num) const; | |
1072 | v128 getVectorRegister(int num) const; | |
1073 | void setVectorRegister(int num, v128 value); | |
1074 | const char* getRegisterName(int num); | |
1075 | void jumpto(); | |
1076 | uint64_t getSP() const { return fRegisters.__sp; } | |
1077 | void setSP(uint64_t value) { fRegisters.__sp = value; } | |
1078 | uint64_t getIP() const { return fRegisters.__pc; } | |
1079 | void setIP(uint64_t value) { fRegisters.__pc = value; } | |
1080 | uint64_t getFP() const { return fRegisters.__fp; } | |
1081 | void setFP(uint64_t value) { fRegisters.__fp = value; } | |
1082 | private: | |
1083 | arm_thread_state64_t fRegisters; | |
1084 | double fHalfVectorRegisters[32]; | |
1085 | // Currently only the lower double in 128-bit vectore registers | |
1086 | // is perserved during unwinding. We could define new register | |
1087 | // numbers (> 96) which mean whole vector registers, then this | |
1088 | // struct would need to change to contain whole vector registers. | |
1089 | }; | |
1090 | ||
1091 | inline Registers_arm64::Registers_arm64(const void* registers) | |
1092 | { | |
1093 | COMPILE_TIME_ASSERT( sizeof(Registers_arm64) < sizeof(unw_context_t) ); | |
1094 | fRegisters = *((arm_thread_state64_t*)registers); | |
1095 | } | |
1096 | ||
1097 | inline Registers_arm64::Registers_arm64() | |
1098 | { | |
1099 | bzero(&fRegisters, sizeof(fRegisters)); | |
1100 | bzero(&fRegisters, sizeof(fHalfVectorRegisters)); | |
1101 | } | |
1102 | ||
1103 | ||
1104 | inline bool Registers_arm64::validRegister(int regNum) const | |
1105 | { | |
1106 | if ( regNum == UNW_REG_IP ) | |
1107 | return true; | |
1108 | if ( regNum == UNW_REG_SP ) | |
1109 | return true; | |
1110 | if ( regNum < 0 ) | |
1111 | return false; | |
1112 | if ( regNum > 95 ) | |
1113 | return false; | |
1114 | if ( (regNum > 31) && (regNum < 64) ) | |
1115 | return false; | |
1116 | return true; | |
1117 | } | |
1118 | ||
1119 | inline uint64_t Registers_arm64::getRegister(int regNum) const | |
1120 | { | |
1121 | if ( regNum == UNW_REG_IP ) | |
1122 | return fRegisters.__pc; | |
1123 | if ( regNum == UNW_REG_SP ) | |
1124 | return fRegisters.__sp; | |
1125 | if ( (regNum >= 0) && (regNum < 32) ) | |
1126 | return fRegisters.__x[regNum]; | |
1127 | ABORT("unsupported arm64 register"); | |
1128 | } | |
1129 | ||
1130 | inline void Registers_arm64::setRegister(int regNum, uint64_t value) | |
1131 | { | |
1132 | if ( regNum == UNW_REG_IP ) | |
1133 | fRegisters.__pc = value; | |
1134 | else if ( regNum == UNW_REG_SP ) | |
1135 | fRegisters.__sp = value; | |
1136 | else if ( (regNum >= 0) && (regNum < 32) ) | |
1137 | fRegisters.__x[regNum] = value; | |
1138 | else | |
1139 | ABORT("unsupported arm64 register"); | |
1140 | } | |
1141 | ||
1142 | inline const char* Registers_arm64::getRegisterName(int regNum) | |
1143 | { | |
1144 | switch (regNum) { | |
1145 | case UNW_REG_IP: | |
1146 | return "pc"; | |
1147 | case UNW_REG_SP: | |
1148 | return "sp"; | |
1149 | case UNW_ARM64_X0: | |
1150 | return "x0"; | |
1151 | case UNW_ARM64_X1: | |
1152 | return "x1"; | |
1153 | case UNW_ARM64_X2: | |
1154 | return "x2"; | |
1155 | case UNW_ARM64_X3: | |
1156 | return "x3"; | |
1157 | case UNW_ARM64_X4: | |
1158 | return "x4"; | |
1159 | case UNW_ARM64_X5: | |
1160 | return "x5"; | |
1161 | case UNW_ARM64_X6: | |
1162 | return "x6"; | |
1163 | case UNW_ARM64_X7: | |
1164 | return "x7"; | |
1165 | case UNW_ARM64_X8: | |
1166 | return "x8"; | |
1167 | case UNW_ARM64_X9: | |
1168 | return "x9"; | |
1169 | case UNW_ARM64_X10: | |
1170 | return "x10"; | |
1171 | case UNW_ARM64_X11: | |
1172 | return "x11"; | |
1173 | case UNW_ARM64_X12: | |
1174 | return "x12"; | |
1175 | case UNW_ARM64_X13: | |
1176 | return "x13"; | |
1177 | case UNW_ARM64_X14: | |
1178 | return "x14"; | |
1179 | case UNW_ARM64_X15: | |
1180 | return "x15"; | |
1181 | case UNW_ARM64_X16: | |
1182 | return "x16"; | |
1183 | case UNW_ARM64_X17: | |
1184 | return "x17"; | |
1185 | case UNW_ARM64_X18: | |
1186 | return "x18"; | |
1187 | case UNW_ARM64_X19: | |
1188 | return "x19"; | |
1189 | case UNW_ARM64_X20: | |
1190 | return "x20"; | |
1191 | case UNW_ARM64_X21: | |
1192 | return "x21"; | |
1193 | case UNW_ARM64_X22: | |
1194 | return "x22"; | |
1195 | case UNW_ARM64_X23: | |
1196 | return "x23"; | |
1197 | case UNW_ARM64_X24: | |
1198 | return "x24"; | |
1199 | case UNW_ARM64_X25: | |
1200 | return "x25"; | |
1201 | case UNW_ARM64_X26: | |
1202 | return "x26"; | |
1203 | case UNW_ARM64_X27: | |
1204 | return "x27"; | |
1205 | case UNW_ARM64_X28: | |
1206 | return "x28"; | |
1207 | case UNW_ARM64_X29: | |
1208 | return "fp"; | |
1209 | case UNW_ARM64_X30: | |
1210 | return "lr"; | |
1211 | case UNW_ARM64_X31: | |
1212 | return "sp"; | |
1213 | case UNW_ARM64_D0: | |
1214 | return "d0"; | |
1215 | case UNW_ARM64_D1: | |
1216 | return "d1"; | |
1217 | case UNW_ARM64_D2: | |
1218 | return "d2"; | |
1219 | case UNW_ARM64_D3: | |
1220 | return "d3"; | |
1221 | case UNW_ARM64_D4: | |
1222 | return "d4"; | |
1223 | case UNW_ARM64_D5: | |
1224 | return "d5"; | |
1225 | case UNW_ARM64_D6: | |
1226 | return "d6"; | |
1227 | case UNW_ARM64_D7: | |
1228 | return "d7"; | |
1229 | case UNW_ARM64_D8: | |
1230 | return "d8"; | |
1231 | case UNW_ARM64_D9: | |
1232 | return "d9"; | |
1233 | case UNW_ARM64_D10: | |
1234 | return "d10"; | |
1235 | case UNW_ARM64_D11: | |
1236 | return "d11"; | |
1237 | case UNW_ARM64_D12: | |
1238 | return "d12"; | |
1239 | case UNW_ARM64_D13: | |
1240 | return "d13"; | |
1241 | case UNW_ARM64_D14: | |
1242 | return "d14"; | |
1243 | case UNW_ARM64_D15: | |
1244 | return "d15"; | |
1245 | case UNW_ARM64_D16: | |
1246 | return "d16"; | |
1247 | case UNW_ARM64_D17: | |
1248 | return "d17"; | |
1249 | case UNW_ARM64_D18: | |
1250 | return "d18"; | |
1251 | case UNW_ARM64_D19: | |
1252 | return "d19"; | |
1253 | case UNW_ARM64_D20: | |
1254 | return "d20"; | |
1255 | case UNW_ARM64_D21: | |
1256 | return "d21"; | |
1257 | case UNW_ARM64_D22: | |
1258 | return "d22"; | |
1259 | case UNW_ARM64_D23: | |
1260 | return "d23"; | |
1261 | case UNW_ARM64_D24: | |
1262 | return "d24"; | |
1263 | case UNW_ARM64_D25: | |
1264 | return "d25"; | |
1265 | case UNW_ARM64_D26: | |
1266 | return "d26"; | |
1267 | case UNW_ARM64_D27: | |
1268 | return "d27"; | |
1269 | case UNW_ARM64_D28: | |
1270 | return "d28"; | |
1271 | case UNW_ARM64_D29: | |
1272 | return "d29"; | |
1273 | case UNW_ARM64_D30: | |
1274 | return "d30"; | |
1275 | case UNW_ARM64_D31: | |
1276 | return "d31"; | |
1277 | default: | |
1278 | return "unknown register"; | |
1279 | } | |
1280 | } | |
1281 | ||
1282 | bool Registers_arm64::validFloatRegister(int regNum) const | |
1283 | { | |
1284 | if ( regNum < UNW_ARM64_D0 ) | |
1285 | return false; | |
1286 | if ( regNum > UNW_ARM64_D31 ) | |
1287 | return false; | |
1288 | return true; | |
1289 | } | |
1290 | ||
afe874b1 | 1291 | |
f80fe69f A |
1292 | double Registers_arm64::getFloatRegister(int regNum) const |
1293 | { | |
1294 | assert(validFloatRegister(regNum)); | |
1295 | return fHalfVectorRegisters[regNum-UNW_ARM64_D0]; | |
1296 | } | |
1297 | ||
1298 | void Registers_arm64::setFloatRegister(int regNum, double value) | |
1299 | { | |
1300 | assert(validFloatRegister(regNum)); | |
1301 | fHalfVectorRegisters[regNum-UNW_ARM64_D0] = value; | |
afe874b1 A |
1302 | } |
1303 | ||
f80fe69f A |
1304 | inline bool Registers_arm64::validVectorRegister(int regNum) const |
1305 | { | |
1306 | return false; | |
1307 | } | |
1308 | ||
1309 | inline v128 Registers_arm64::getVectorRegister(int regNum) const | |
1310 | { | |
1311 | ABORT("no arm64 vector register support yet"); | |
1312 | } | |
1313 | ||
1314 | inline void Registers_arm64::setVectorRegister(int regNum, v128 value) | |
1315 | { | |
1316 | ABORT("no arm64 vector register support yet"); | |
1317 | } | |
1318 | ||
1319 | ||
afe874b1 A |
1320 | |
1321 | } // namespace libunwind | |
1322 | ||
1323 | ||
1324 | ||
1325 | #endif // __REGISTERS_HPP__ | |
1326 | ||
1327 | ||
1328 | ||
1329 |