]>
Commit | Line | Data |
---|---|---|
afe874b1 A |
1 | /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- |
2 | * | |
3 | * Copyright (c) 2007-2009 Apple Inc. All rights reserved. | |
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 | ||
1038 | ||
1039 | } | |
1040 | ||
1041 | ||
1042 | } // namespace libunwind | |
1043 | ||
1044 | ||
1045 | ||
1046 | #endif // __REGISTERS_HPP__ | |
1047 | ||
1048 | ||
1049 | ||
1050 |