Home | History | Annotate | Line # | Download | only in libunwind
Registers.hpp revision 1.16
      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 #ifndef __REGISTERS_HPP__
     13 #define __REGISTERS_HPP__
     14 
     15 #include <cassert>
     16 #include <cstdint>
     17 
     18 namespace _Unwind {
     19 
     20 enum {
     21   REGNO_X86_EAX = 0,
     22   REGNO_X86_ECX = 1,
     23   REGNO_X86_EDX = 2,
     24   REGNO_X86_EBX = 3,
     25   REGNO_X86_ESP = 4,
     26   REGNO_X86_EBP = 5,
     27   REGNO_X86_ESI = 6,
     28   REGNO_X86_EDI = 7,
     29   REGNO_X86_EIP = 8,
     30 };
     31 
     32 class Registers_x86 {
     33 public:
     34   enum {
     35     LAST_REGISTER = REGNO_X86_EIP,
     36     LAST_RESTORE_REG = REGNO_X86_EIP,
     37     RETURN_OFFSET = 0,
     38   };
     39 
     40   __dso_hidden Registers_x86();
     41 
     42   static int dwarf2regno(int num) { return num; }
     43 
     44   bool validRegister(int num) const {
     45     return num >= REGNO_X86_EAX && num <= REGNO_X86_EDI;
     46   }
     47 
     48   uint32_t getRegister(int num) const {
     49     assert(validRegister(num));
     50     return reg[num];
     51   }
     52 
     53   void setRegister(int num, uint32_t value) {
     54     assert(validRegister(num));
     55     reg[num] = value;
     56   }
     57 
     58   uint32_t getIP() const { return reg[REGNO_X86_EIP]; }
     59 
     60   void setIP(uint32_t value) { reg[REGNO_X86_EIP] = value; }
     61 
     62   uint32_t getSP() const { return reg[REGNO_X86_ESP]; }
     63 
     64   void setSP(uint32_t value) { reg[REGNO_X86_ESP] = value; }
     65 
     66   bool validFloatVectorRegister(int num) const { return false; }
     67 
     68   void copyFloatVectorRegister(int num, uint32_t addr) {
     69   }
     70 
     71   __dso_hidden void jumpto() const __dead;
     72 
     73 private:
     74   uint32_t reg[REGNO_X86_EIP + 1];
     75 };
     76 
     77 enum {
     78   REGNO_X86_64_RAX = 0,
     79   REGNO_X86_64_RDX = 1,
     80   REGNO_X86_64_RCX = 2,
     81   REGNO_X86_64_RBX = 3,
     82   REGNO_X86_64_RSI = 4,
     83   REGNO_X86_64_RDI = 5,
     84   REGNO_X86_64_RBP = 6,
     85   REGNO_X86_64_RSP = 7,
     86   REGNO_X86_64_R8 = 8,
     87   REGNO_X86_64_R9 = 9,
     88   REGNO_X86_64_R10 = 10,
     89   REGNO_X86_64_R11 = 11,
     90   REGNO_X86_64_R12 = 12,
     91   REGNO_X86_64_R13 = 13,
     92   REGNO_X86_64_R14 = 14,
     93   REGNO_X86_64_R15 = 15,
     94   REGNO_X86_64_RIP = 16,
     95 };
     96 
     97 class Registers_x86_64 {
     98 public:
     99   enum {
    100     LAST_REGISTER = REGNO_X86_64_RIP,
    101     LAST_RESTORE_REG = REGNO_X86_64_RIP,
    102     RETURN_OFFSET = 0,
    103   };
    104 
    105   __dso_hidden Registers_x86_64();
    106 
    107   static int dwarf2regno(int num) { return num; }
    108 
    109   bool validRegister(int num) const {
    110     return num >= REGNO_X86_64_RAX && num <= REGNO_X86_64_R15;
    111   }
    112 
    113   uint64_t getRegister(int num) const {
    114     assert(validRegister(num));
    115     return reg[num];
    116   }
    117 
    118   void setRegister(int num, uint64_t value) {
    119     assert(validRegister(num));
    120     reg[num] = value;
    121   }
    122 
    123   uint64_t getIP() const { return reg[REGNO_X86_64_RIP]; }
    124 
    125   void setIP(uint64_t value) { reg[REGNO_X86_64_RIP] = value; }
    126 
    127   uint64_t getSP() const { return reg[REGNO_X86_64_RSP]; }
    128 
    129   void setSP(uint64_t value) { reg[REGNO_X86_64_RSP] = value; }
    130 
    131   bool validFloatVectorRegister(int num) const { return false; }
    132 
    133   void copyFloatVectorRegister(int num, uint64_t addr) {
    134   }
    135 
    136   __dso_hidden void jumpto() const __dead;
    137 
    138 private:
    139   uint64_t reg[REGNO_X86_64_RIP + 1];
    140 };
    141 
    142 enum {
    143   DWARF_PPC32_R0 = 0,
    144   DWARF_PPC32_R31 = 31,
    145   DWARF_PPC32_F0 = 32,
    146   DWARF_PPC32_F31 = 63,
    147   DWARF_PPC32_LR = 65,
    148   DWARF_PPC32_CR = 70,
    149   DWARF_PPC32_V0 = 77,
    150   DWARF_PPC32_V31 = 108,
    151 
    152   REGNO_PPC32_R0 = 0,
    153   REGNO_PPC32_R1 = 1,
    154   REGNO_PPC32_R31 = 31,
    155   REGNO_PPC32_LR = 32,
    156   REGNO_PPC32_CR = 33,
    157   REGNO_PPC32_SRR0 = 34,
    158 
    159   REGNO_PPC32_F0 = REGNO_PPC32_SRR0 + 1,
    160   REGNO_PPC32_F31 = REGNO_PPC32_F0 + 31,
    161   REGNO_PPC32_V0 = REGNO_PPC32_F31 + 1,
    162   REGNO_PPC32_V31 = REGNO_PPC32_V0 + 31,
    163 };
    164 
    165 class Registers_ppc32 {
    166 public:
    167   enum {
    168     LAST_REGISTER = REGNO_PPC32_V31,
    169     LAST_RESTORE_REG = REGNO_PPC32_V31,
    170     RETURN_OFFSET = 0,
    171   };
    172 
    173   __dso_hidden Registers_ppc32();
    174 
    175   static int dwarf2regno(int num) {
    176     if (num >= DWARF_PPC32_R0 && num <= DWARF_PPC32_R31)
    177       return REGNO_PPC32_R0 + (num - DWARF_PPC32_R0);
    178     if (num >= DWARF_PPC32_F0 && num <= DWARF_PPC32_F31)
    179       return REGNO_PPC32_F0 + (num - DWARF_PPC32_F0);
    180     if (num >= DWARF_PPC32_V0 && num <= DWARF_PPC32_V31)
    181       return REGNO_PPC32_V0 + (num - DWARF_PPC32_V0);
    182     switch (num) {
    183     case DWARF_PPC32_LR:
    184       return REGNO_PPC32_LR;
    185     case DWARF_PPC32_CR:
    186       return REGNO_PPC32_CR;
    187     default:
    188       return LAST_REGISTER + 1;
    189     }
    190   }
    191 
    192   bool validRegister(int num) const {
    193     return num >= 0 && num <= LAST_RESTORE_REG;
    194   }
    195 
    196   uint64_t getRegister(int num) const {
    197     assert(validRegister(num));
    198     return reg[num];
    199   }
    200 
    201   void setRegister(int num, uint64_t value) {
    202     assert(validRegister(num));
    203     reg[num] = value;
    204   }
    205 
    206   uint64_t getIP() const { return reg[REGNO_PPC32_SRR0]; }
    207 
    208   void setIP(uint64_t value) { reg[REGNO_PPC32_SRR0] = value; }
    209 
    210   uint64_t getSP() const { return reg[REGNO_PPC32_R1]; }
    211 
    212   void setSP(uint64_t value) { reg[REGNO_PPC32_R1] = value; }
    213 
    214   bool validFloatVectorRegister(int num) const {
    215     return (num >= REGNO_PPC32_F0 && num <= REGNO_PPC32_F31) ||
    216            (num >= REGNO_PPC32_V0 && num <= REGNO_PPC32_V31);
    217   }
    218 
    219   void copyFloatVectorRegister(int num, uint64_t addr_) {
    220     const void *addr = reinterpret_cast<const void *>(addr_);
    221     if (num >= REGNO_PPC32_F0 && num <= REGNO_PPC32_F31)
    222       memcpy(fpreg + (num - REGNO_PPC32_F0), addr, sizeof(fpreg[0]));
    223     else
    224       memcpy(vecreg + (num - REGNO_PPC32_V0), addr, sizeof(vecreg[0]));
    225   }
    226 
    227   __dso_hidden void jumpto() const __dead;
    228 
    229 private:
    230   struct vecreg_t {
    231     uint64_t low, high;
    232   };
    233   uint32_t reg[REGNO_PPC32_SRR0 + 1];
    234   uint32_t dummy;
    235   uint64_t fpreg[32];
    236   vecreg_t vecreg[64];
    237 };
    238 
    239 enum {
    240   DWARF_ARM32_R0 = 0,
    241   DWARF_ARM32_R15 = 15,
    242   DWARF_ARM32_SPSR = 128,
    243   DWARF_ARM32_OLD_S0 = 64,
    244   DWARF_ARM32_OLD_S31 = 91,
    245   DWARF_ARM32_D0 = 256,
    246   DWARF_ARM32_D31 = 287,
    247   REGNO_ARM32_R0 = 0,
    248   REGNO_ARM32_SP = 13,
    249   REGNO_ARM32_R15 = 15,
    250   REGNO_ARM32_SPSR = 16,
    251   REGNO_ARM32_D0 = 17,
    252   REGNO_ARM32_D15 = 32,
    253   REGNO_ARM32_D31 = 48,
    254 };
    255 
    256 class Registers_arm32 {
    257 public:
    258   enum {
    259     LAST_REGISTER = REGNO_ARM32_D31,
    260     LAST_RESTORE_REG = REGNO_ARM32_D31,
    261     RETURN_OFFSET = 0,
    262   };
    263 
    264   __dso_hidden Registers_arm32();
    265 
    266   static int dwarf2regno(int num) {
    267     if (num >= DWARF_ARM32_R0 && num <= DWARF_ARM32_R15)
    268       return REGNO_ARM32_R0 + (num - DWARF_ARM32_R0);
    269     if (num == DWARF_ARM32_SPSR)
    270       return REGNO_ARM32_SPSR;
    271     if (num >= DWARF_ARM32_D0 && num <= DWARF_ARM32_D31)
    272       return REGNO_ARM32_D0 + (num - DWARF_ARM32_D0);
    273     if (num >= DWARF_ARM32_OLD_S0 && num <= DWARF_ARM32_OLD_S31) {
    274       assert(num % 2 == 0);
    275       return REGNO_ARM32_D0 + (num - DWARF_ARM32_OLD_S0) / 2;
    276     }
    277     return LAST_REGISTER + 1;
    278   }
    279 
    280   bool validRegister(int num) const {
    281     return num >= 0 && num <= REGNO_ARM32_SPSR;
    282   }
    283 
    284   uint64_t getRegister(int num) const {
    285     assert(validRegister(num));
    286     return reg[num];
    287   }
    288 
    289   void setRegister(int num, uint64_t value) {
    290     assert(validRegister(num));
    291     reg[num] = value;
    292   }
    293 
    294   uint64_t getIP() const { return reg[REGNO_ARM32_R15]; }
    295 
    296   void setIP(uint64_t value) { reg[REGNO_ARM32_R15] = value; }
    297 
    298   uint64_t getSP() const { return reg[REGNO_ARM32_SP]; }
    299 
    300   void setSP(uint64_t value) { reg[REGNO_ARM32_SP] = value; }
    301 
    302   bool validFloatVectorRegister(int num) const {
    303     return (num >= REGNO_ARM32_D0 && num <= REGNO_ARM32_D31);
    304   }
    305 
    306   void copyFloatVectorRegister(int num, uint64_t addr_) {
    307     if (num <= REGNO_ARM32_D15) {
    308       if ((flags & 1) == 0) {
    309         lazyVFP1();
    310         flags |= 1;
    311       }
    312     } else {
    313       if ((flags & 2) == 0) {
    314         lazyVFP3();
    315         flags |= 2;
    316       }
    317     }
    318     const void *addr = reinterpret_cast<const void *>(addr_);
    319     memcpy(fpreg + (num - REGNO_ARM32_D0), addr, sizeof(fpreg[0]));
    320   }
    321 
    322   __dso_hidden void lazyVFP1();
    323   __dso_hidden void lazyVFP3();
    324   __dso_hidden void jumpto() const __dead;
    325 
    326 private:
    327   uint32_t reg[REGNO_ARM32_SPSR + 1];
    328   uint32_t flags;
    329   uint64_t fpreg[32];
    330 };
    331 
    332 enum {
    333   DWARF_VAX_R0 = 0,
    334   DWARF_VAX_R15 = 15,
    335   DWARF_VAX_PSW = 16,
    336 
    337   REGNO_VAX_R0 = 0,
    338   REGNO_VAX_R14 = 14,
    339   REGNO_VAX_R15 = 15,
    340   REGNO_VAX_PSW = 16,
    341 };
    342 
    343 class Registers_vax {
    344 public:
    345   enum {
    346     LAST_REGISTER = REGNO_VAX_PSW,
    347     LAST_RESTORE_REG = REGNO_VAX_PSW,
    348     RETURN_OFFSET = 0,
    349   };
    350 
    351   __dso_hidden Registers_vax();
    352 
    353   static int dwarf2regno(int num) {
    354     if (num >= DWARF_VAX_R0 && num <= DWARF_VAX_R15)
    355       return REGNO_VAX_R0 + (num - DWARF_VAX_R0);
    356     if (num == DWARF_VAX_PSW)
    357       return REGNO_VAX_PSW;
    358     return LAST_REGISTER + 1;
    359   }
    360 
    361   bool validRegister(int num) const {
    362     return num >= 0 && num <= LAST_RESTORE_REG;
    363   }
    364 
    365   uint64_t getRegister(int num) const {
    366     assert(validRegister(num));
    367     return reg[num];
    368   }
    369 
    370   void setRegister(int num, uint64_t value) {
    371     assert(validRegister(num));
    372     reg[num] = value;
    373   }
    374 
    375   uint64_t getIP() const { return reg[REGNO_VAX_R15]; }
    376 
    377   void setIP(uint64_t value) { reg[REGNO_VAX_R15] = value; }
    378 
    379   uint64_t getSP() const { return reg[REGNO_VAX_R14]; }
    380 
    381   void setSP(uint64_t value) { reg[REGNO_VAX_R14] = value; }
    382 
    383   bool validFloatVectorRegister(int num) const {
    384     return false;
    385   }
    386 
    387   void copyFloatVectorRegister(int num, uint64_t addr_) {
    388   }
    389 
    390   __dso_hidden void jumpto() const __dead;
    391 
    392 private:
    393   uint32_t reg[REGNO_VAX_PSW + 1];
    394 };
    395 
    396 enum {
    397   DWARF_M68K_A0 = 0,
    398   DWARF_M68K_A7 = 7,
    399   DWARF_M68K_D0 = 8,
    400   DWARF_M68K_D7 = 15,
    401   DWARF_M68K_FP0 = 16,
    402   DWARF_M68K_FP7 = 23,
    403   DWARF_M68K_PC = 24,
    404 
    405   REGNO_M68K_A0 = 0,
    406   REGNO_M68K_A7 = 7,
    407   REGNO_M68K_D0 = 8,
    408   REGNO_M68K_D7 = 15,
    409   REGNO_M68K_PC = 16,
    410   REGNO_M68K_FP0 = 17,
    411   REGNO_M68K_FP7 = 24,
    412 };
    413 
    414 class Registers_M68K {
    415 public:
    416   enum {
    417     LAST_REGISTER = REGNO_M68K_FP7,
    418     LAST_RESTORE_REG = REGNO_M68K_FP7,
    419     RETURN_OFFSET = 0,
    420   };
    421 
    422   __dso_hidden Registers_M68K();
    423 
    424   static int dwarf2regno(int num) {
    425     if (num >= DWARF_M68K_A0 && num <= DWARF_M68K_A7)
    426       return REGNO_M68K_A0 + (num - DWARF_M68K_A0);
    427     if (num >= DWARF_M68K_D0 && num <= DWARF_M68K_D7)
    428       return REGNO_M68K_D0 + (num - DWARF_M68K_D0);
    429     if (num >= DWARF_M68K_FP0 && num <= DWARF_M68K_FP7)
    430       return REGNO_M68K_FP0 + (num - DWARF_M68K_FP0);
    431     if (num == DWARF_M68K_PC)
    432       return REGNO_M68K_PC;
    433     return LAST_REGISTER + 1;
    434   }
    435 
    436   bool validRegister(int num) const {
    437     return num >= 0 && num <= REGNO_M68K_PC;
    438   }
    439 
    440   uint64_t getRegister(int num) const {
    441     assert(validRegister(num));
    442     return reg[num];
    443   }
    444 
    445   void setRegister(int num, uint64_t value) {
    446     assert(validRegister(num));
    447     reg[num] = value;
    448   }
    449 
    450   uint64_t getIP() const { return reg[REGNO_M68K_PC]; }
    451 
    452   void setIP(uint64_t value) { reg[REGNO_M68K_PC] = value; }
    453 
    454   uint64_t getSP() const { return reg[REGNO_M68K_A7]; }
    455 
    456   void setSP(uint64_t value) { reg[REGNO_M68K_A7] = value; }
    457 
    458   bool validFloatVectorRegister(int num) const {
    459     return num >= REGNO_M68K_FP0 && num <= REGNO_M68K_FP7;
    460   }
    461 
    462   void copyFloatVectorRegister(int num, uint64_t addr_) {
    463     assert(validFloatVectorRegister(num));
    464     const void *addr = reinterpret_cast<const void *>(addr_);
    465     memcpy(fpreg + (num - REGNO_M68K_FP0), addr, sizeof(fpreg[0]));
    466   }
    467 
    468   __dso_hidden void jumpto() const __dead;
    469 
    470 private:
    471   typedef uint32_t fpreg_t[3];
    472 
    473   uint32_t reg[REGNO_M68K_PC + 1];
    474   uint32_t dummy;
    475   fpreg_t fpreg[8];
    476 };
    477 
    478 enum {
    479   DWARF_SH3_R0 = 0,
    480   DWARF_SH3_R15 = 15,
    481   DWARF_SH3_PC = 16,
    482   DWARF_SH3_PR = 17,
    483 
    484   REGNO_SH3_R0 = 0,
    485   REGNO_SH3_R15 = 15,
    486   REGNO_SH3_PC = 16,
    487   REGNO_SH3_PR = 17,
    488 };
    489 
    490 class Registers_SH3 {
    491 public:
    492   enum {
    493     LAST_REGISTER = REGNO_SH3_PR,
    494     LAST_RESTORE_REG = REGNO_SH3_PR,
    495     RETURN_OFFSET = 0,
    496   };
    497 
    498   __dso_hidden Registers_SH3();
    499 
    500   static int dwarf2regno(int num) {
    501     if (num >= DWARF_SH3_R0 && num <= DWARF_SH3_R15)
    502       return REGNO_SH3_R0 + (num - DWARF_SH3_R0);
    503     if (num == DWARF_SH3_PC)
    504       return REGNO_SH3_PC;
    505     if (num == DWARF_SH3_PR)
    506       return REGNO_SH3_PR;
    507     return LAST_REGISTER + 1;
    508   }
    509 
    510   bool validRegister(int num) const {
    511     return num >= 0 && num <= REGNO_SH3_PR;
    512   }
    513 
    514   uint64_t getRegister(int num) const {
    515     assert(validRegister(num));
    516     return reg[num];
    517   }
    518 
    519   void setRegister(int num, uint64_t value) {
    520     assert(validRegister(num));
    521     reg[num] = value;
    522   }
    523 
    524   uint64_t getIP() const { return reg[REGNO_SH3_PC]; }
    525 
    526   void setIP(uint64_t value) { reg[REGNO_SH3_PC] = value; }
    527 
    528   uint64_t getSP() const { return reg[REGNO_SH3_R15]; }
    529 
    530   void setSP(uint64_t value) { reg[REGNO_SH3_R15] = value; }
    531 
    532   bool validFloatVectorRegister(int num) const { return false; }
    533 
    534   void copyFloatVectorRegister(int num, uint64_t addr_) {}
    535 
    536   __dso_hidden void jumpto() const __dead;
    537 
    538 private:
    539   uint32_t reg[REGNO_SH3_PR + 1];
    540 };
    541 
    542 enum {
    543   DWARF_SPARC64_R0 = 0,
    544   DWARF_SPARC64_R31 = 31,
    545   DWARF_SPARC64_PC = 32,
    546 
    547   REGNO_SPARC64_R0 = 0,
    548   REGNO_SPARC64_R14 = 14,
    549   REGNO_SPARC64_R15 = 15,
    550   REGNO_SPARC64_R31 = 31,
    551   REGNO_SPARC64_PC = 32,
    552 };
    553 
    554 class Registers_SPARC64 {
    555 public:
    556   enum {
    557     LAST_REGISTER = REGNO_SPARC64_PC,
    558     LAST_RESTORE_REG = REGNO_SPARC64_PC,
    559     RETURN_OFFSET = 8,
    560   };
    561   typedef uint64_t reg_t;
    562 
    563   __dso_hidden Registers_SPARC64();
    564 
    565   static int dwarf2regno(int num) {
    566     if (num >= DWARF_SPARC64_R0 && num <= DWARF_SPARC64_R31)
    567       return REGNO_SPARC64_R0 + (num - DWARF_SPARC64_R0);
    568     if (num == DWARF_SPARC64_PC)
    569       return REGNO_SPARC64_PC;
    570     return LAST_REGISTER + 1;
    571   }
    572 
    573   bool validRegister(int num) const {
    574     return num >= 0 && num <= REGNO_SPARC64_PC;
    575   }
    576 
    577   uint64_t getRegister(int num) const {
    578     assert(validRegister(num));
    579     return reg[num];
    580   }
    581 
    582   void setRegister(int num, uint64_t value) {
    583     assert(validRegister(num));
    584     reg[num] = value;
    585   }
    586 
    587   uint64_t getIP() const { return reg[REGNO_SPARC64_PC]; }
    588 
    589   void setIP(uint64_t value) { reg[REGNO_SPARC64_PC] = value; }
    590 
    591   uint64_t getSP() const { return reg[REGNO_SPARC64_R14]; }
    592 
    593   void setSP(uint64_t value) { reg[REGNO_SPARC64_R14] = value; }
    594 
    595   bool validFloatVectorRegister(int num) const { return false; }
    596 
    597   void copyFloatVectorRegister(int num, uint64_t addr_) {}
    598 
    599   __dso_hidden void jumpto() const __dead;
    600 
    601 private:
    602   uint64_t reg[REGNO_SPARC64_PC + 1];
    603 };
    604 
    605 enum {
    606   DWARF_SPARC_R0 = 0,
    607   DWARF_SPARC_R31 = 31,
    608   DWARF_SPARC_PC = 32,
    609 
    610   REGNO_SPARC_R0 = 0,
    611   REGNO_SPARC_R14 = 14,
    612   REGNO_SPARC_R15 = 15,
    613   REGNO_SPARC_R31 = 31,
    614   REGNO_SPARC_PC = 32,
    615 };
    616 
    617 class Registers_SPARC {
    618 public:
    619   enum {
    620     LAST_REGISTER = REGNO_SPARC_PC,
    621     LAST_RESTORE_REG = REGNO_SPARC_PC,
    622     RETURN_OFFSET = 8,
    623   };
    624   typedef uint32_t reg_t;
    625 
    626   __dso_hidden Registers_SPARC();
    627 
    628   static int dwarf2regno(int num) {
    629     if (num >= DWARF_SPARC_R0 && num <= DWARF_SPARC_R31)
    630       return REGNO_SPARC_R0 + (num - DWARF_SPARC_R0);
    631     if (num == DWARF_SPARC_PC)
    632       return REGNO_SPARC_PC;
    633     return LAST_REGISTER + 1;
    634   }
    635 
    636   bool validRegister(int num) const {
    637     return num >= 0 && num <= REGNO_SPARC_PC;
    638   }
    639 
    640   uint64_t getRegister(int num) const {
    641     assert(validRegister(num));
    642     return reg[num];
    643   }
    644 
    645   void setRegister(int num, uint64_t value) {
    646     assert(validRegister(num));
    647     reg[num] = value;
    648   }
    649 
    650   uint64_t getIP() const { return reg[REGNO_SPARC_PC]; }
    651 
    652   void setIP(uint64_t value) { reg[REGNO_SPARC_PC] = value; }
    653 
    654   uint64_t getSP() const { return reg[REGNO_SPARC_R14]; }
    655 
    656   void setSP(uint64_t value) { reg[REGNO_SPARC_R14] = value; }
    657 
    658   bool validFloatVectorRegister(int num) const { return false; }
    659 
    660   void copyFloatVectorRegister(int num, uint64_t addr_) {}
    661 
    662   __dso_hidden void jumpto() const __dead;
    663 
    664 private:
    665   uint32_t reg[REGNO_SPARC_PC + 1];
    666 };
    667 
    668 enum {
    669   DWARF_ALPHA_R0 = 0,
    670   DWARF_ALPHA_R30 = 30,
    671   DWARF_ALPHA_F0 = 32,
    672   DWARF_ALPHA_F30 = 62,
    673 
    674   REGNO_ALPHA_R0 = 0,
    675   REGNO_ALPHA_R26 = 26,
    676   REGNO_ALPHA_R30 = 30,
    677   REGNO_ALPHA_PC = 31,
    678   REGNO_ALPHA_F0 = 32,
    679   REGNO_ALPHA_F30 = 62,
    680 };
    681 
    682 class Registers_Alpha {
    683 public:
    684   enum {
    685     LAST_REGISTER = REGNO_ALPHA_F30,
    686     LAST_RESTORE_REG = REGNO_ALPHA_F30,
    687     RETURN_OFFSET = 0,
    688   };
    689   typedef uint32_t reg_t;
    690 
    691   __dso_hidden Registers_Alpha();
    692 
    693   static int dwarf2regno(int num) { return num; }
    694 
    695   bool validRegister(int num) const {
    696     return num >= 0 && num <= REGNO_ALPHA_PC;
    697   }
    698 
    699   uint64_t getRegister(int num) const {
    700     assert(validRegister(num));
    701     return reg[num];
    702   }
    703 
    704   void setRegister(int num, uint64_t value) {
    705     assert(validRegister(num));
    706     reg[num] = value;
    707   }
    708 
    709   uint64_t getIP() const { return reg[REGNO_ALPHA_PC]; }
    710 
    711   void setIP(uint64_t value) { reg[REGNO_ALPHA_PC] = value; }
    712 
    713   uint64_t getSP() const { return reg[REGNO_ALPHA_R30]; }
    714 
    715   void setSP(uint64_t value) { reg[REGNO_ALPHA_R30] = value; }
    716 
    717   bool validFloatVectorRegister(int num) const {
    718     return num >= REGNO_ALPHA_F0 && num <= REGNO_ALPHA_F30;
    719   }
    720 
    721   void copyFloatVectorRegister(int num, uint64_t addr_) {
    722     assert(validFloatVectorRegister(num));
    723     const void *addr = reinterpret_cast<const void *>(addr_);
    724     memcpy(fpreg + (num - REGNO_ALPHA_F0), addr, sizeof(fpreg[0]));
    725   }
    726 
    727   __dso_hidden void jumpto() const __dead;
    728 
    729 private:
    730   uint64_t reg[REGNO_ALPHA_PC + 1];
    731   uint64_t fpreg[31];
    732 };
    733 
    734 enum {
    735   DWARF_HPPA_R1 = 1,
    736   DWARF_HPPA_R31 = 31,
    737   DWARF_HPPA_FR4L = 32,
    738   DWARF_HPPA_FR31H = 87,
    739 
    740   REGNO_HPPA_PC = 0,
    741   REGNO_HPPA_R1 = 1,
    742   REGNO_HPPA_R2 = 2,
    743   REGNO_HPPA_R30 = 30,
    744   REGNO_HPPA_R31 = 31,
    745   REGNO_HPPA_FR4L = 32,
    746   REGNO_HPPA_FR31H = 87,
    747 };
    748 
    749 class Registers_HPPA {
    750 public:
    751   enum {
    752     LAST_REGISTER = REGNO_HPPA_FR31H,
    753     LAST_RESTORE_REG = REGNO_HPPA_FR31H,
    754     RETURN_OFFSET = -3, // strictly speaking, this is a mask
    755   };
    756 
    757   __dso_hidden Registers_HPPA();
    758 
    759   static int dwarf2regno(int num) {
    760     if (num >= DWARF_HPPA_R1 && num <= DWARF_HPPA_R31)
    761       return REGNO_HPPA_R1 + (num - DWARF_HPPA_R1);
    762     if (num >= DWARF_HPPA_FR4L && num <= DWARF_HPPA_FR31H)
    763       return REGNO_HPPA_FR4L + (num - DWARF_HPPA_FR31H);
    764     return LAST_REGISTER + 1;
    765   }
    766 
    767   bool validRegister(int num) const {
    768     return num >= REGNO_HPPA_PC && num <= REGNO_HPPA_R31;
    769   }
    770 
    771   uint64_t getRegister(int num) const {
    772     assert(validRegister(num));
    773     return reg[num];
    774   }
    775 
    776   void setRegister(int num, uint64_t value) {
    777     assert(validRegister(num));
    778     reg[num] = value;
    779   }
    780 
    781   uint64_t getIP() const { return reg[REGNO_HPPA_PC]; }
    782 
    783   void setIP(uint64_t value) { reg[REGNO_HPPA_PC] = value; }
    784 
    785   uint64_t getSP() const { return reg[REGNO_HPPA_R30]; }
    786 
    787   void setSP(uint64_t value) { reg[REGNO_HPPA_R30] = value; }
    788 
    789   bool validFloatVectorRegister(int num) const {
    790     return num >= REGNO_HPPA_FR4L && num <= REGNO_HPPA_FR31H;
    791   }
    792 
    793   void copyFloatVectorRegister(int num, uint64_t addr_) {
    794     assert(validFloatVectorRegister(num));
    795     const void *addr = reinterpret_cast<const void *>(addr_);
    796     memcpy(fpreg + (num - REGNO_HPPA_FR4L), addr, sizeof(fpreg[0]));
    797   }
    798 
    799   __dso_hidden void jumpto() const __dead;
    800 
    801 private:
    802   uint32_t reg[REGNO_HPPA_R31 + 1];
    803   uint32_t fpreg[56];
    804 };
    805 
    806 enum {
    807   DWARF_MIPS_R1 = 0,
    808   DWARF_MIPS_R31 = 31,
    809   DWARF_MIPS_F0 = 32,
    810   DWARF_MIPS_F31 = 63,
    811 
    812   REGNO_MIPS_PC = 0,
    813   REGNO_MIPS_R1 = 0,
    814   REGNO_MIPS_R29 = 29,
    815   REGNO_MIPS_R31 = 31,
    816   REGNO_MIPS_F0 = 33,
    817   REGNO_MIPS_F31 = 64
    818 };
    819 
    820 class Registers_MIPS {
    821 public:
    822   enum {
    823     LAST_REGISTER = REGNO_MIPS_F31,
    824     LAST_RESTORE_REG = REGNO_MIPS_F31,
    825     RETURN_OFFSET = 0,
    826   };
    827 
    828   __dso_hidden Registers_MIPS();
    829 
    830   static int dwarf2regno(int num) {
    831     if (num >= DWARF_MIPS_R1 && num <= DWARF_MIPS_R31)
    832       return REGNO_MIPS_R1 + (num - DWARF_MIPS_R1);
    833     if (num >= DWARF_MIPS_F0 && num <= DWARF_MIPS_F31)
    834       return REGNO_MIPS_F0 + (num - DWARF_MIPS_F0);
    835     return LAST_REGISTER + 1;
    836   }
    837 
    838   bool validRegister(int num) const {
    839     return num >= REGNO_MIPS_PC && num <= REGNO_MIPS_R31;
    840   }
    841 
    842   uint64_t getRegister(int num) const {
    843     assert(validRegister(num));
    844     return reg[num];
    845   }
    846 
    847   void setRegister(int num, uint64_t value) {
    848     assert(validRegister(num));
    849     reg[num] = value;
    850   }
    851 
    852   uint64_t getIP() const { return reg[REGNO_MIPS_PC]; }
    853 
    854   void setIP(uint64_t value) { reg[REGNO_MIPS_PC] = value; }
    855 
    856   uint64_t getSP() const { return reg[REGNO_MIPS_R29]; }
    857 
    858   void setSP(uint64_t value) { reg[REGNO_MIPS_R29] = value; }
    859 
    860   bool validFloatVectorRegister(int num) const {
    861     return num >= DWARF_MIPS_F0 && num <= DWARF_MIPS_F31;
    862   }
    863 
    864   void copyFloatVectorRegister(int num, uint64_t addr_) {
    865     assert(validFloatVectorRegister(num));
    866     const void *addr = reinterpret_cast<const void *>(addr_);
    867     memcpy(fpreg + (num - REGNO_MIPS_F0), addr, sizeof(fpreg[0]));
    868   }
    869 
    870   __dso_hidden void jumpto() const __dead;
    871 
    872 private:
    873   uint32_t reg[REGNO_MIPS_R31 + 1];
    874   uint64_t fpreg[32];
    875 };
    876 
    877 enum {
    878   DWARF_MIPS64_R1 = 0,
    879   DWARF_MIPS64_R31 = 31,
    880   DWARF_MIPS64_F0 = 32,
    881   DWARF_MIPS64_F31 = 63,
    882 
    883   REGNO_MIPS64_PC = 0,
    884   REGNO_MIPS64_R1 = 0,
    885   REGNO_MIPS64_R29 = 29,
    886   REGNO_MIPS64_R31 = 31,
    887   REGNO_MIPS64_F0 = 33,
    888   REGNO_MIPS64_F31 = 64
    889 };
    890 
    891 class Registers_MIPS64 {
    892 public:
    893   enum {
    894     LAST_REGISTER = REGNO_MIPS64_F31,
    895     LAST_RESTORE_REG = REGNO_MIPS64_F31,
    896     RETURN_OFFSET = 0,
    897   };
    898 
    899   __dso_hidden Registers_MIPS64();
    900 
    901   static int dwarf2regno(int num) {
    902     if (num >= DWARF_MIPS64_R1 && num <= DWARF_MIPS64_R31)
    903       return REGNO_MIPS64_R1 + (num - DWARF_MIPS64_R1);
    904     if (num >= DWARF_MIPS64_F0 && num <= DWARF_MIPS64_F31)
    905       return REGNO_MIPS64_F0 + (num - DWARF_MIPS64_F0);
    906     return LAST_REGISTER + 1;
    907   }
    908 
    909   bool validRegister(int num) const {
    910     return num >= REGNO_MIPS64_PC && num <= REGNO_MIPS64_R31;
    911   }
    912 
    913   uint64_t getRegister(int num) const {
    914     assert(validRegister(num));
    915     return reg[num];
    916   }
    917 
    918   void setRegister(int num, uint64_t value) {
    919     assert(validRegister(num));
    920     reg[num] = value;
    921   }
    922 
    923   uint64_t getIP() const { return reg[REGNO_MIPS64_PC]; }
    924 
    925   void setIP(uint64_t value) { reg[REGNO_MIPS64_PC] = value; }
    926 
    927   uint64_t getSP() const { return reg[REGNO_MIPS64_R29]; }
    928 
    929   void setSP(uint64_t value) { reg[REGNO_MIPS64_R29] = value; }
    930 
    931   bool validFloatVectorRegister(int num) const {
    932     return num >= DWARF_MIPS64_F0 && num <= DWARF_MIPS64_F31;
    933   }
    934 
    935   void copyFloatVectorRegister(int num, uint64_t addr_) {
    936     assert(validFloatVectorRegister(num));
    937     const void *addr = reinterpret_cast<const void *>(addr_);
    938     memcpy(fpreg + (num - REGNO_MIPS64_F0), addr, sizeof(fpreg[0]));
    939   }
    940 
    941   __dso_hidden void jumpto() const __dead;
    942 
    943 private:
    944   uint64_t reg[REGNO_MIPS64_R31 + 1];
    945   uint64_t fpreg[32];
    946 };
    947 
    948 #if __i386__
    949 typedef Registers_x86 NativeUnwindRegisters;
    950 #elif __x86_64__
    951 typedef Registers_x86_64 NativeUnwindRegisters;
    952 #elif __powerpc__
    953 typedef Registers_ppc32 NativeUnwindRegisters;
    954 #elif __arm__
    955 typedef Registers_arm32 NativeUnwindRegisters;
    956 #elif __vax__
    957 typedef Registers_vax NativeUnwindRegisters;
    958 #elif __m68k__
    959 typedef Registers_M68K NativeUnwindRegisters;
    960 #elif __mips_n64 || __mips_n32
    961 typedef Registers_MIPS64 NativeUnwindRegisters;
    962 #elif __mips__
    963 typedef Registers_MIPS NativeUnwindRegisters;
    964 #elif __sh3__
    965 typedef Registers_SH3 NativeUnwindRegisters;
    966 #elif __sparc64__
    967 typedef Registers_SPARC64 NativeUnwindRegisters;
    968 #elif __sparc__
    969 typedef Registers_SPARC NativeUnwindRegisters;
    970 #elif __alpha__
    971 typedef Registers_Alpha NativeUnwindRegisters;
    972 #elif __hppa__
    973 typedef Registers_HPPA NativeUnwindRegisters;
    974 #endif
    975 } // namespace _Unwind
    976 
    977 #endif // __REGISTERS_HPP__
    978