1aa0b96d0Sjoerg //===----------------------------- Registers.hpp --------------------------===// 2aa0b96d0Sjoerg // 3aa0b96d0Sjoerg // The LLVM Compiler Infrastructure 4aa0b96d0Sjoerg // 5aa0b96d0Sjoerg // This file is dual licensed under the MIT and the University of Illinois Open 6aa0b96d0Sjoerg // Source Licenses. See LICENSE.TXT for details. 7aa0b96d0Sjoerg // 8aa0b96d0Sjoerg // 9aa0b96d0Sjoerg // Models register sets for supported processors. 10aa0b96d0Sjoerg // 11aa0b96d0Sjoerg //===----------------------------------------------------------------------===// 12aa0b96d0Sjoerg #ifndef __REGISTERS_HPP__ 13aa0b96d0Sjoerg #define __REGISTERS_HPP__ 14aa0b96d0Sjoerg 15155a9ee6Sjoerg #include <sys/endian.h> 16aa0b96d0Sjoerg #include <cassert> 17aa0b96d0Sjoerg #include <cstdint> 18aa0b96d0Sjoerg 19aa0b96d0Sjoerg namespace _Unwind { 20aa0b96d0Sjoerg 21aa0b96d0Sjoerg enum { 22aa0b96d0Sjoerg REGNO_X86_EAX = 0, 23aa0b96d0Sjoerg REGNO_X86_ECX = 1, 24aa0b96d0Sjoerg REGNO_X86_EDX = 2, 25aa0b96d0Sjoerg REGNO_X86_EBX = 3, 26aa0b96d0Sjoerg REGNO_X86_ESP = 4, 27aa0b96d0Sjoerg REGNO_X86_EBP = 5, 28aa0b96d0Sjoerg REGNO_X86_ESI = 6, 29aa0b96d0Sjoerg REGNO_X86_EDI = 7, 30aa0b96d0Sjoerg REGNO_X86_EIP = 8, 31aa0b96d0Sjoerg }; 32aa0b96d0Sjoerg 33aa0b96d0Sjoerg class Registers_x86 { 34aa0b96d0Sjoerg public: 35aa0b96d0Sjoerg enum { 36aa0b96d0Sjoerg LAST_REGISTER = REGNO_X86_EIP, 37916de6d0Sjoerg LAST_RESTORE_REG = REGNO_X86_EIP, 389788222aSjoerg RETURN_OFFSET = 0, 390282220bSjoerg RETURN_MASK = 0, 40aa0b96d0Sjoerg }; 41aa0b96d0Sjoerg 42aa0b96d0Sjoerg __dso_hidden Registers_x86(); 43aa0b96d0Sjoerg dwarf2regno(int num)44aa0b96d0Sjoerg static int dwarf2regno(int num) { return num; } 45aa0b96d0Sjoerg validRegister(int num) const46aa0b96d0Sjoerg bool validRegister(int num) const { 47aa0b96d0Sjoerg return num >= REGNO_X86_EAX && num <= REGNO_X86_EDI; 48aa0b96d0Sjoerg } 49aa0b96d0Sjoerg getRegister(int num) const50aa0b96d0Sjoerg uint32_t getRegister(int num) const { 51aa0b96d0Sjoerg assert(validRegister(num)); 52aa0b96d0Sjoerg return reg[num]; 53aa0b96d0Sjoerg } 54aa0b96d0Sjoerg setRegister(int num,uint32_t value)55aa0b96d0Sjoerg void setRegister(int num, uint32_t value) { 56aa0b96d0Sjoerg assert(validRegister(num)); 57aa0b96d0Sjoerg reg[num] = value; 58aa0b96d0Sjoerg } 59aa0b96d0Sjoerg getIP() const60aa0b96d0Sjoerg uint32_t getIP() const { return reg[REGNO_X86_EIP]; } 61aa0b96d0Sjoerg setIP(uint32_t value)62aa0b96d0Sjoerg void setIP(uint32_t value) { reg[REGNO_X86_EIP] = value; } 63aa0b96d0Sjoerg getSP() const64aa0b96d0Sjoerg uint32_t getSP() const { return reg[REGNO_X86_ESP]; } 65aa0b96d0Sjoerg setSP(uint32_t value)66aa0b96d0Sjoerg void setSP(uint32_t value) { reg[REGNO_X86_ESP] = value; } 67aa0b96d0Sjoerg validFloatVectorRegister(int num) const68aa0b96d0Sjoerg bool validFloatVectorRegister(int num) const { return false; } 69aa0b96d0Sjoerg copyFloatVectorRegister(int num,uint32_t addr)70aa0b96d0Sjoerg void copyFloatVectorRegister(int num, uint32_t addr) { 71aa0b96d0Sjoerg } 72aa0b96d0Sjoerg 73aa0b96d0Sjoerg __dso_hidden void jumpto() const __dead; 74aa0b96d0Sjoerg 75aa0b96d0Sjoerg private: 76aa0b96d0Sjoerg uint32_t reg[REGNO_X86_EIP + 1]; 77aa0b96d0Sjoerg }; 78aa0b96d0Sjoerg 79aa0b96d0Sjoerg enum { 80aa0b96d0Sjoerg REGNO_X86_64_RAX = 0, 81aa0b96d0Sjoerg REGNO_X86_64_RDX = 1, 82aa0b96d0Sjoerg REGNO_X86_64_RCX = 2, 83aa0b96d0Sjoerg REGNO_X86_64_RBX = 3, 84aa0b96d0Sjoerg REGNO_X86_64_RSI = 4, 85aa0b96d0Sjoerg REGNO_X86_64_RDI = 5, 86aa0b96d0Sjoerg REGNO_X86_64_RBP = 6, 87aa0b96d0Sjoerg REGNO_X86_64_RSP = 7, 88aa0b96d0Sjoerg REGNO_X86_64_R8 = 8, 89aa0b96d0Sjoerg REGNO_X86_64_R9 = 9, 90aa0b96d0Sjoerg REGNO_X86_64_R10 = 10, 91aa0b96d0Sjoerg REGNO_X86_64_R11 = 11, 92aa0b96d0Sjoerg REGNO_X86_64_R12 = 12, 93aa0b96d0Sjoerg REGNO_X86_64_R13 = 13, 94aa0b96d0Sjoerg REGNO_X86_64_R14 = 14, 95aa0b96d0Sjoerg REGNO_X86_64_R15 = 15, 96aa0b96d0Sjoerg REGNO_X86_64_RIP = 16, 97aa0b96d0Sjoerg }; 98aa0b96d0Sjoerg 99aa0b96d0Sjoerg class Registers_x86_64 { 100aa0b96d0Sjoerg public: 101aa0b96d0Sjoerg enum { 102aa0b96d0Sjoerg LAST_REGISTER = REGNO_X86_64_RIP, 103916de6d0Sjoerg LAST_RESTORE_REG = REGNO_X86_64_RIP, 1049788222aSjoerg RETURN_OFFSET = 0, 1050282220bSjoerg RETURN_MASK = 0, 106aa0b96d0Sjoerg }; 107aa0b96d0Sjoerg 108aa0b96d0Sjoerg __dso_hidden Registers_x86_64(); 109aa0b96d0Sjoerg dwarf2regno(int num)110aa0b96d0Sjoerg static int dwarf2regno(int num) { return num; } 111aa0b96d0Sjoerg validRegister(int num) const112aa0b96d0Sjoerg bool validRegister(int num) const { 113aa0b96d0Sjoerg return num >= REGNO_X86_64_RAX && num <= REGNO_X86_64_R15; 114aa0b96d0Sjoerg } 115aa0b96d0Sjoerg getRegister(int num) const116aa0b96d0Sjoerg uint64_t getRegister(int num) const { 117aa0b96d0Sjoerg assert(validRegister(num)); 118aa0b96d0Sjoerg return reg[num]; 119aa0b96d0Sjoerg } 120aa0b96d0Sjoerg setRegister(int num,uint64_t value)121aa0b96d0Sjoerg void setRegister(int num, uint64_t value) { 122aa0b96d0Sjoerg assert(validRegister(num)); 123aa0b96d0Sjoerg reg[num] = value; 124aa0b96d0Sjoerg } 125aa0b96d0Sjoerg getIP() const126aa0b96d0Sjoerg uint64_t getIP() const { return reg[REGNO_X86_64_RIP]; } 127aa0b96d0Sjoerg setIP(uint64_t value)128aa0b96d0Sjoerg void setIP(uint64_t value) { reg[REGNO_X86_64_RIP] = value; } 129aa0b96d0Sjoerg getSP() const130aa0b96d0Sjoerg uint64_t getSP() const { return reg[REGNO_X86_64_RSP]; } 131aa0b96d0Sjoerg setSP(uint64_t value)132aa0b96d0Sjoerg void setSP(uint64_t value) { reg[REGNO_X86_64_RSP] = value; } 133aa0b96d0Sjoerg validFloatVectorRegister(int num) const134aa0b96d0Sjoerg bool validFloatVectorRegister(int num) const { return false; } 135aa0b96d0Sjoerg copyFloatVectorRegister(int num,uint64_t addr)136aa0b96d0Sjoerg void copyFloatVectorRegister(int num, uint64_t addr) { 137aa0b96d0Sjoerg } 138aa0b96d0Sjoerg 139aa0b96d0Sjoerg __dso_hidden void jumpto() const __dead; 140aa0b96d0Sjoerg 141aa0b96d0Sjoerg private: 142aa0b96d0Sjoerg uint64_t reg[REGNO_X86_64_RIP + 1]; 143aa0b96d0Sjoerg }; 144aa0b96d0Sjoerg 145aa0b96d0Sjoerg enum { 146aa0b96d0Sjoerg DWARF_PPC32_R0 = 0, 147aa0b96d0Sjoerg DWARF_PPC32_R31 = 31, 148aa0b96d0Sjoerg DWARF_PPC32_F0 = 32, 149aa0b96d0Sjoerg DWARF_PPC32_F31 = 63, 150aa0b96d0Sjoerg DWARF_PPC32_LR = 65, 1512524c512Sthorpej DWARF_PPC32_CTR = 66, 152b238bfcaSjoerg DWARF_PPC32_CR = 70, 1532524c512Sthorpej DWARF_PPC32_XER = 76, 154b238bfcaSjoerg DWARF_PPC32_V0 = 77, 1552524c512Sthorpej DWARF_PPC32_SIGRETURN = 99, 156b238bfcaSjoerg DWARF_PPC32_V31 = 108, 157b238bfcaSjoerg 158aa0b96d0Sjoerg REGNO_PPC32_R0 = 0, 159b238bfcaSjoerg REGNO_PPC32_R1 = 1, 160aa0b96d0Sjoerg REGNO_PPC32_R31 = 31, 161b238bfcaSjoerg REGNO_PPC32_LR = 32, 162b238bfcaSjoerg REGNO_PPC32_CR = 33, 163b238bfcaSjoerg REGNO_PPC32_SRR0 = 34, 164b238bfcaSjoerg 165aa0b96d0Sjoerg REGNO_PPC32_F0 = REGNO_PPC32_SRR0 + 1, 166aa0b96d0Sjoerg REGNO_PPC32_F31 = REGNO_PPC32_F0 + 31, 167aa0b96d0Sjoerg REGNO_PPC32_V0 = REGNO_PPC32_F31 + 1, 168aa0b96d0Sjoerg REGNO_PPC32_V31 = REGNO_PPC32_V0 + 31, 1692524c512Sthorpej 1702524c512Sthorpej REGNO_PPC32_CTR = REGNO_PPC32_V31 + 1, 1712524c512Sthorpej REGNO_PPC32_XER = REGNO_PPC32_CTR + 1, 1722524c512Sthorpej REGNO_PPC32_SIGRETURN = REGNO_PPC32_XER + 1 173aa0b96d0Sjoerg }; 174aa0b96d0Sjoerg 175aa0b96d0Sjoerg class Registers_ppc32 { 176aa0b96d0Sjoerg public: 177aa0b96d0Sjoerg enum { 1782524c512Sthorpej LAST_REGISTER = REGNO_PPC32_SIGRETURN, 1792524c512Sthorpej LAST_RESTORE_REG = REGNO_PPC32_SIGRETURN, 1809788222aSjoerg RETURN_OFFSET = 0, 1810282220bSjoerg RETURN_MASK = 0, 182aa0b96d0Sjoerg }; 183aa0b96d0Sjoerg 184aa0b96d0Sjoerg __dso_hidden Registers_ppc32(); 185aa0b96d0Sjoerg dwarf2regno(int num)186aa0b96d0Sjoerg static int dwarf2regno(int num) { 187aa0b96d0Sjoerg if (num >= DWARF_PPC32_R0 && num <= DWARF_PPC32_R31) 188aa0b96d0Sjoerg return REGNO_PPC32_R0 + (num - DWARF_PPC32_R0); 189aa0b96d0Sjoerg if (num >= DWARF_PPC32_F0 && num <= DWARF_PPC32_F31) 190aa0b96d0Sjoerg return REGNO_PPC32_F0 + (num - DWARF_PPC32_F0); 191aa0b96d0Sjoerg if (num >= DWARF_PPC32_V0 && num <= DWARF_PPC32_V31) 192aa0b96d0Sjoerg return REGNO_PPC32_V0 + (num - DWARF_PPC32_V0); 193b238bfcaSjoerg switch (num) { 194b238bfcaSjoerg case DWARF_PPC32_LR: 195b238bfcaSjoerg return REGNO_PPC32_LR; 196b238bfcaSjoerg case DWARF_PPC32_CR: 197b238bfcaSjoerg return REGNO_PPC32_CR; 1982524c512Sthorpej case DWARF_PPC32_CTR: 1992524c512Sthorpej return REGNO_PPC32_CTR; 2002524c512Sthorpej case DWARF_PPC32_XER: 2012524c512Sthorpej return REGNO_PPC32_XER; 2022524c512Sthorpej case DWARF_PPC32_SIGRETURN: 2032524c512Sthorpej return REGNO_PPC32_SIGRETURN; 204b238bfcaSjoerg default: 205aa0b96d0Sjoerg return LAST_REGISTER + 1; 206aa0b96d0Sjoerg } 207b238bfcaSjoerg } 208aa0b96d0Sjoerg validRegister(int num) const209aa0b96d0Sjoerg bool validRegister(int num) const { 2102524c512Sthorpej return (num >= 0 && num <= REGNO_PPC32_SRR0) || 2112524c512Sthorpej (num >= REGNO_PPC32_CTR && num <= REGNO_PPC32_SIGRETURN); 212aa0b96d0Sjoerg } 213aa0b96d0Sjoerg getRegister(int num) const214aa0b96d0Sjoerg uint64_t getRegister(int num) const { 215aa0b96d0Sjoerg assert(validRegister(num)); 2162524c512Sthorpej switch (num) { 2172524c512Sthorpej case REGNO_PPC32_CTR: 2182524c512Sthorpej return ctr_reg; 2192524c512Sthorpej case REGNO_PPC32_XER: 2202524c512Sthorpej return xer_reg; 2212524c512Sthorpej case REGNO_PPC32_SIGRETURN: 2222524c512Sthorpej return sigreturn_reg; 2232524c512Sthorpej default: 224aa0b96d0Sjoerg return reg[num]; 225aa0b96d0Sjoerg } 2262524c512Sthorpej } 227aa0b96d0Sjoerg setRegister(int num,uint64_t value)228aa0b96d0Sjoerg void setRegister(int num, uint64_t value) { 229aa0b96d0Sjoerg assert(validRegister(num)); 2302524c512Sthorpej switch (num) { 2312524c512Sthorpej case REGNO_PPC32_CTR: 2322524c512Sthorpej ctr_reg = value; 2332524c512Sthorpej break; 2342524c512Sthorpej case REGNO_PPC32_XER: 2352524c512Sthorpej xer_reg = value; 2362524c512Sthorpej break; 2372524c512Sthorpej case REGNO_PPC32_SIGRETURN: 2382524c512Sthorpej sigreturn_reg = value; 2392524c512Sthorpej break; 2402524c512Sthorpej default: 241aa0b96d0Sjoerg reg[num] = value; 242aa0b96d0Sjoerg } 2432524c512Sthorpej } 244aa0b96d0Sjoerg getIP() const245aa0b96d0Sjoerg uint64_t getIP() const { return reg[REGNO_PPC32_SRR0]; } 246aa0b96d0Sjoerg setIP(uint64_t value)247aa0b96d0Sjoerg void setIP(uint64_t value) { reg[REGNO_PPC32_SRR0] = value; } 248aa0b96d0Sjoerg getSP() const249aa0b96d0Sjoerg uint64_t getSP() const { return reg[REGNO_PPC32_R1]; } 250aa0b96d0Sjoerg setSP(uint64_t value)251aa0b96d0Sjoerg void setSP(uint64_t value) { reg[REGNO_PPC32_R1] = value; } 252aa0b96d0Sjoerg validFloatVectorRegister(int num) const253aa0b96d0Sjoerg bool validFloatVectorRegister(int num) const { 254aa0b96d0Sjoerg return (num >= REGNO_PPC32_F0 && num <= REGNO_PPC32_F31) || 255aa0b96d0Sjoerg (num >= REGNO_PPC32_V0 && num <= REGNO_PPC32_V31); 256aa0b96d0Sjoerg } 257aa0b96d0Sjoerg copyFloatVectorRegister(int num,uint64_t addr_)258aa0b96d0Sjoerg void copyFloatVectorRegister(int num, uint64_t addr_) { 259aa0b96d0Sjoerg const void *addr = reinterpret_cast<const void *>(addr_); 260aa0b96d0Sjoerg if (num >= REGNO_PPC32_F0 && num <= REGNO_PPC32_F31) 261aa0b96d0Sjoerg memcpy(fpreg + (num - REGNO_PPC32_F0), addr, sizeof(fpreg[0])); 262aa0b96d0Sjoerg else 263aa0b96d0Sjoerg memcpy(vecreg + (num - REGNO_PPC32_V0), addr, sizeof(vecreg[0])); 264aa0b96d0Sjoerg } 265aa0b96d0Sjoerg 266aa0b96d0Sjoerg __dso_hidden void jumpto() const __dead; 267aa0b96d0Sjoerg 268aa0b96d0Sjoerg private: 269aa0b96d0Sjoerg struct vecreg_t { 270aa0b96d0Sjoerg uint64_t low, high; 271aa0b96d0Sjoerg }; 272aa0b96d0Sjoerg uint32_t reg[REGNO_PPC32_SRR0 + 1]; 273b238bfcaSjoerg uint32_t dummy; 274aa0b96d0Sjoerg uint64_t fpreg[32]; 275aa0b96d0Sjoerg vecreg_t vecreg[64]; 2762524c512Sthorpej uint32_t ctr_reg; 2772524c512Sthorpej uint32_t xer_reg; 2782524c512Sthorpej uint32_t sigreturn_reg; 279aa0b96d0Sjoerg }; 280aa0b96d0Sjoerg 281eb98b3ccSmatt enum { 282aa37019dSmatt DWARF_AARCH64_X0 = 0, 283aa37019dSmatt DWARF_AARCH64_X30 = 30, 284aa37019dSmatt DWARF_AARCH64_SP = 31, 285aa37019dSmatt DWARF_AARCH64_V0 = 64, 286aa37019dSmatt DWARF_AARCH64_V31 = 95, 287ba371b84Sthorpej DWARF_AARCH64_SIGRETURN = 96, 288aa37019dSmatt 289aa37019dSmatt REGNO_AARCH64_X0 = 0, 290aa37019dSmatt REGNO_AARCH64_X30 = 30, 291aa37019dSmatt REGNO_AARCH64_SP = 31, 29228f5faf2Sjoerg REGNO_AARCH64_V0 = 32, 29328f5faf2Sjoerg REGNO_AARCH64_V31 = 63, 294ba371b84Sthorpej REGNO_AARCH64_SIGRETURN = 64, 295aa37019dSmatt }; 296aa37019dSmatt 297aa37019dSmatt class Registers_aarch64 { 298aa37019dSmatt public: 299aa37019dSmatt enum { 300ba371b84Sthorpej LAST_RESTORE_REG = REGNO_AARCH64_SIGRETURN, 301ba371b84Sthorpej LAST_REGISTER = REGNO_AARCH64_SIGRETURN, 302aa37019dSmatt RETURN_OFFSET = 0, 3030282220bSjoerg RETURN_MASK = 0, 304aa37019dSmatt }; 305aa37019dSmatt 306aa37019dSmatt __dso_hidden Registers_aarch64(); 307aa37019dSmatt dwarf2regno(int num)308aa37019dSmatt static int dwarf2regno(int num) { 309aa37019dSmatt if (num >= DWARF_AARCH64_X0 && num <= DWARF_AARCH64_X30) 310aa37019dSmatt return REGNO_AARCH64_X0 + (num - DWARF_AARCH64_X0); 311aa37019dSmatt if (num == DWARF_AARCH64_SP) 312aa37019dSmatt return REGNO_AARCH64_SP; 313aa37019dSmatt if (num >= DWARF_AARCH64_V0 && num <= DWARF_AARCH64_V31) 314aa37019dSmatt return REGNO_AARCH64_V0 + (num - DWARF_AARCH64_V0); 315ba371b84Sthorpej if (num == DWARF_AARCH64_SIGRETURN) 316ba371b84Sthorpej return REGNO_AARCH64_SIGRETURN; 317aa37019dSmatt return LAST_REGISTER + 1; 318aa37019dSmatt } 319aa37019dSmatt validRegister(int num) const320aa37019dSmatt bool validRegister(int num) const { 321ba371b84Sthorpej return (num >= DWARF_AARCH64_X0 && num <= DWARF_AARCH64_SP) || 322ba371b84Sthorpej num == DWARF_AARCH64_SIGRETURN; 323aa37019dSmatt } 324aa37019dSmatt getRegister(int num) const325aa37019dSmatt uint64_t getRegister(int num) const { 326aa37019dSmatt assert(validRegister(num)); 32719f7e9f9Sthorpej if (num == REGNO_AARCH64_SIGRETURN) 328ba371b84Sthorpej return sigreturn_reg; 329aa37019dSmatt return reg[num]; 330aa37019dSmatt } 331aa37019dSmatt setRegister(int num,uint64_t value)332aa37019dSmatt void setRegister(int num, uint64_t value) { 333aa37019dSmatt assert(validRegister(num)); 33419f7e9f9Sthorpej if (num == REGNO_AARCH64_SIGRETURN) 335ba371b84Sthorpej sigreturn_reg = value; 336ba371b84Sthorpej else 337aa37019dSmatt reg[num] = value; 338aa37019dSmatt } 339aa37019dSmatt getIP() const340aa37019dSmatt uint64_t getIP() const { return reg[REGNO_AARCH64_X30]; } 341aa37019dSmatt setIP(uint64_t value)342aa37019dSmatt void setIP(uint64_t value) { reg[REGNO_AARCH64_X30] = value; } 343aa37019dSmatt getSP() const344aa37019dSmatt uint64_t getSP() const { return reg[REGNO_AARCH64_SP]; } 345aa37019dSmatt setSP(uint64_t value)346aa37019dSmatt void setSP(uint64_t value) { reg[REGNO_AARCH64_SP] = value; } 347aa37019dSmatt validFloatVectorRegister(int num) const348aa37019dSmatt bool validFloatVectorRegister(int num) const { 349aa37019dSmatt return (num >= REGNO_AARCH64_V0 && num <= REGNO_AARCH64_V31); 350aa37019dSmatt } 351aa37019dSmatt copyFloatVectorRegister(int num,uint64_t addr_)352aa37019dSmatt void copyFloatVectorRegister(int num, uint64_t addr_) { 353aa37019dSmatt const void *addr = reinterpret_cast<const void *>(addr_); 35428f5faf2Sjoerg memcpy(vecreg + (num - REGNO_AARCH64_V0), addr, 16); 355aa37019dSmatt } 356aa37019dSmatt 357aa37019dSmatt __dso_hidden void jumpto() const __dead; 358aa37019dSmatt 359aa37019dSmatt private: 36028f5faf2Sjoerg uint64_t reg[REGNO_AARCH64_SP + 1]; 36128f5faf2Sjoerg uint64_t vecreg[64]; 362ba371b84Sthorpej uint64_t sigreturn_reg; 363aa37019dSmatt }; 364aa37019dSmatt 365aa37019dSmatt enum { 366eb98b3ccSmatt DWARF_ARM32_R0 = 0, 367eb98b3ccSmatt DWARF_ARM32_R15 = 15, 368eb98b3ccSmatt DWARF_ARM32_SPSR = 128, 369155a9ee6Sjoerg DWARF_ARM32_S0 = 64, 3708026a450Srin DWARF_ARM32_S31 = 95, 371bdd3372bSjoerg DWARF_ARM32_D0 = 256, 372eb98b3ccSmatt DWARF_ARM32_D31 = 287, 373eb98b3ccSmatt REGNO_ARM32_R0 = 0, 374eb98b3ccSmatt REGNO_ARM32_SP = 13, 375eb98b3ccSmatt REGNO_ARM32_R15 = 15, 376eb98b3ccSmatt REGNO_ARM32_SPSR = 16, 377bdd3372bSjoerg REGNO_ARM32_D0 = 17, 378bdd3372bSjoerg REGNO_ARM32_D15 = 32, 379bdd3372bSjoerg REGNO_ARM32_D31 = 48, 380155a9ee6Sjoerg REGNO_ARM32_S0 = 49, 3818026a450Srin REGNO_ARM32_S31 = 80, 382eb98b3ccSmatt }; 383eb98b3ccSmatt 3841a44aed1Srin #define FLAGS_VFPV2_USED 0x1 3851a44aed1Srin #define FLAGS_VFPV3_USED 0x2 3861a44aed1Srin #define FLAGS_LEGACY_VFPV2_REGNO 0x4 3871a44aed1Srin #define FLAGS_EXTENDED_VFPV2_REGNO 0x8 3881a44aed1Srin 389eb98b3ccSmatt class Registers_arm32 { 390eb98b3ccSmatt public: 391eb98b3ccSmatt enum { 3921b5786f9Srin LAST_REGISTER = REGNO_ARM32_S31, 3931b5786f9Srin LAST_RESTORE_REG = REGNO_ARM32_S31, 3949788222aSjoerg RETURN_OFFSET = 0, 3950282220bSjoerg RETURN_MASK = 0, 396eb98b3ccSmatt }; 397eb98b3ccSmatt 398eb98b3ccSmatt __dso_hidden Registers_arm32(); 399eb98b3ccSmatt dwarf2regno(int num)400eb98b3ccSmatt static int dwarf2regno(int num) { 401eb98b3ccSmatt if (num >= DWARF_ARM32_R0 && num <= DWARF_ARM32_R15) 402eb98b3ccSmatt return REGNO_ARM32_R0 + (num - DWARF_ARM32_R0); 403eb98b3ccSmatt if (num == DWARF_ARM32_SPSR) 404eb98b3ccSmatt return REGNO_ARM32_SPSR; 405bdd3372bSjoerg if (num >= DWARF_ARM32_D0 && num <= DWARF_ARM32_D31) 406bdd3372bSjoerg return REGNO_ARM32_D0 + (num - DWARF_ARM32_D0); 40785f18f75Srin if (num >= DWARF_ARM32_S0 && num <= DWARF_ARM32_S31) 408155a9ee6Sjoerg return REGNO_ARM32_S0 + (num - DWARF_ARM32_S0); 409eb98b3ccSmatt return LAST_REGISTER + 1; 410eb98b3ccSmatt } 411eb98b3ccSmatt validRegister(int num) const412eb98b3ccSmatt bool validRegister(int num) const { 413bdd3372bSjoerg return num >= 0 && num <= REGNO_ARM32_SPSR; 414eb98b3ccSmatt } 415eb98b3ccSmatt getRegister(int num) const416eb98b3ccSmatt uint64_t getRegister(int num) const { 417eb98b3ccSmatt assert(validRegister(num)); 418eb98b3ccSmatt return reg[num]; 419eb98b3ccSmatt } 420eb98b3ccSmatt setRegister(int num,uint64_t value)421eb98b3ccSmatt void setRegister(int num, uint64_t value) { 422eb98b3ccSmatt assert(validRegister(num)); 423eb98b3ccSmatt reg[num] = value; 424eb98b3ccSmatt } 425eb98b3ccSmatt getIP() const426eb98b3ccSmatt uint64_t getIP() const { return reg[REGNO_ARM32_R15]; } 427eb98b3ccSmatt setIP(uint64_t value)428eb98b3ccSmatt void setIP(uint64_t value) { reg[REGNO_ARM32_R15] = value; } 429eb98b3ccSmatt getSP() const430eb98b3ccSmatt uint64_t getSP() const { return reg[REGNO_ARM32_SP]; } 431eb98b3ccSmatt setSP(uint64_t value)432eb98b3ccSmatt void setSP(uint64_t value) { reg[REGNO_ARM32_SP] = value; } 433eb98b3ccSmatt validFloatVectorRegister(int num) const434eb98b3ccSmatt bool validFloatVectorRegister(int num) const { 435155a9ee6Sjoerg return (num >= REGNO_ARM32_D0 && num <= REGNO_ARM32_S31); 436eb98b3ccSmatt } 437eb98b3ccSmatt copyFloatVectorRegister(int num,uint64_t addr_)438eb98b3ccSmatt void copyFloatVectorRegister(int num, uint64_t addr_) { 439d03fef5bSrin assert(validFloatVectorRegister(num)); 440155a9ee6Sjoerg const void *addr = reinterpret_cast<const void *>(addr_); 441155a9ee6Sjoerg if (num >= REGNO_ARM32_S0 && num <= REGNO_ARM32_S31) { 4421b5786f9Srin /* 4431b5786f9Srin * XXX 4441b5786f9Srin * There are two numbering schemes for VFPv2 registers: s0-s31 4451b5786f9Srin * (used by GCC) and d0-d15 (used by LLVM). We won't support both 4461b5786f9Srin * schemes simultaneously in a same frame. 4471b5786f9Srin */ 4481b5786f9Srin assert((flags & FLAGS_EXTENDED_VFPV2_REGNO) == 0); 4491b5786f9Srin flags |= FLAGS_LEGACY_VFPV2_REGNO; 45085f18f75Srin if ((flags & FLAGS_VFPV2_USED) == 0) { 45185f18f75Srin lazyVFPv2(); 45285f18f75Srin flags |= FLAGS_VFPV2_USED; 453155a9ee6Sjoerg } 454155a9ee6Sjoerg /* 455155a9ee6Sjoerg * Emulate single precision register as half of the 456155a9ee6Sjoerg * corresponding double register. 457155a9ee6Sjoerg */ 458155a9ee6Sjoerg int dnum = (num - REGNO_ARM32_S0) / 2; 459155a9ee6Sjoerg int part = (num - REGNO_ARM32_S0) % 2; 460155a9ee6Sjoerg #if _BYTE_ORDER == _BIG_ENDIAN 461155a9ee6Sjoerg part = 1 - part; 462155a9ee6Sjoerg #endif 463c2f619e8Srin memcpy((uint8_t *)(fpreg + dnum) + part * sizeof(fpreg[0]) / 2, 464155a9ee6Sjoerg addr, sizeof(fpreg[0]) / 2); 465994a5fb3Srin } else { 466bdd3372bSjoerg if (num <= REGNO_ARM32_D15) { 4671b5786f9Srin /* 4681b5786f9Srin * XXX 4691b5786f9Srin * See XXX comment above. 4701b5786f9Srin */ 4711b5786f9Srin assert((flags & FLAGS_LEGACY_VFPV2_REGNO) == 0); 4721b5786f9Srin flags |= FLAGS_EXTENDED_VFPV2_REGNO; 47385f18f75Srin if ((flags & FLAGS_VFPV2_USED) == 0) { 47485f18f75Srin lazyVFPv2(); 47585f18f75Srin flags |= FLAGS_VFPV2_USED; 476bdd3372bSjoerg } 477bdd3372bSjoerg } else { 47885f18f75Srin if ((flags & FLAGS_VFPV3_USED) == 0) { 47985f18f75Srin lazyVFPv3(); 48085f18f75Srin flags |= FLAGS_VFPV3_USED; 481bdd3372bSjoerg } 482bdd3372bSjoerg } 483eb98b3ccSmatt memcpy(fpreg + (num - REGNO_ARM32_D0), addr, sizeof(fpreg[0])); 484eb98b3ccSmatt } 485994a5fb3Srin } 486eb98b3ccSmatt 48785f18f75Srin __dso_hidden void lazyVFPv2(); 48885f18f75Srin __dso_hidden void lazyVFPv3(); 489eb98b3ccSmatt __dso_hidden void jumpto() const __dead; 490eb98b3ccSmatt 491eb98b3ccSmatt private: 492eb98b3ccSmatt uint32_t reg[REGNO_ARM32_SPSR + 1]; 493bdd3372bSjoerg uint32_t flags; 494eb98b3ccSmatt uint64_t fpreg[32]; 4951a44aed1Srin }; 49685f18f75Srin 4971a44aed1Srin #undef FLAGS_VFPV2_USED 4981a44aed1Srin #undef FLAGS_VFPV3_USED 4991a44aed1Srin #undef FLAGS_LEGACY_VFPV2_REGNO 5001a44aed1Srin #undef FLAGS_EXTENDED_VFPV2_REGNO 501eb98b3ccSmatt 502396ee378Sjoerg enum { 503396ee378Sjoerg DWARF_VAX_R0 = 0, 504396ee378Sjoerg DWARF_VAX_R15 = 15, 505396ee378Sjoerg DWARF_VAX_PSW = 16, 506396ee378Sjoerg 507396ee378Sjoerg REGNO_VAX_R0 = 0, 508396ee378Sjoerg REGNO_VAX_R14 = 14, 509396ee378Sjoerg REGNO_VAX_R15 = 15, 510396ee378Sjoerg REGNO_VAX_PSW = 16, 511396ee378Sjoerg }; 512396ee378Sjoerg 513396ee378Sjoerg class Registers_vax { 514396ee378Sjoerg public: 515396ee378Sjoerg enum { 516396ee378Sjoerg LAST_REGISTER = REGNO_VAX_PSW, 517396ee378Sjoerg LAST_RESTORE_REG = REGNO_VAX_PSW, 5189788222aSjoerg RETURN_OFFSET = 0, 5190282220bSjoerg RETURN_MASK = 0, 520396ee378Sjoerg }; 521396ee378Sjoerg 522396ee378Sjoerg __dso_hidden Registers_vax(); 523396ee378Sjoerg dwarf2regno(int num)524396ee378Sjoerg static int dwarf2regno(int num) { 525396ee378Sjoerg if (num >= DWARF_VAX_R0 && num <= DWARF_VAX_R15) 526396ee378Sjoerg return REGNO_VAX_R0 + (num - DWARF_VAX_R0); 527396ee378Sjoerg if (num == DWARF_VAX_PSW) 528396ee378Sjoerg return REGNO_VAX_PSW; 529396ee378Sjoerg return LAST_REGISTER + 1; 530396ee378Sjoerg } 531396ee378Sjoerg validRegister(int num) const532396ee378Sjoerg bool validRegister(int num) const { 533396ee378Sjoerg return num >= 0 && num <= LAST_RESTORE_REG; 534396ee378Sjoerg } 535396ee378Sjoerg getRegister(int num) const536396ee378Sjoerg uint64_t getRegister(int num) const { 537396ee378Sjoerg assert(validRegister(num)); 538396ee378Sjoerg return reg[num]; 539396ee378Sjoerg } 540396ee378Sjoerg setRegister(int num,uint64_t value)541396ee378Sjoerg void setRegister(int num, uint64_t value) { 542396ee378Sjoerg assert(validRegister(num)); 543396ee378Sjoerg reg[num] = value; 544396ee378Sjoerg } 545396ee378Sjoerg getIP() const546396ee378Sjoerg uint64_t getIP() const { return reg[REGNO_VAX_R15]; } 547396ee378Sjoerg setIP(uint64_t value)548396ee378Sjoerg void setIP(uint64_t value) { reg[REGNO_VAX_R15] = value; } 549396ee378Sjoerg getSP() const550396ee378Sjoerg uint64_t getSP() const { return reg[REGNO_VAX_R14]; } 551396ee378Sjoerg setSP(uint64_t value)552396ee378Sjoerg void setSP(uint64_t value) { reg[REGNO_VAX_R14] = value; } 553396ee378Sjoerg validFloatVectorRegister(int num) const554396ee378Sjoerg bool validFloatVectorRegister(int num) const { 555396ee378Sjoerg return false; 556396ee378Sjoerg } 557396ee378Sjoerg copyFloatVectorRegister(int num,uint64_t addr_)558396ee378Sjoerg void copyFloatVectorRegister(int num, uint64_t addr_) { 559396ee378Sjoerg } 560396ee378Sjoerg 561396ee378Sjoerg __dso_hidden void jumpto() const __dead; 562396ee378Sjoerg 563396ee378Sjoerg private: 564396ee378Sjoerg uint32_t reg[REGNO_VAX_PSW + 1]; 565396ee378Sjoerg }; 566396ee378Sjoerg 567a55c6bd8Sjoerg enum { 568a55c6bd8Sjoerg DWARF_M68K_A0 = 0, 569a55c6bd8Sjoerg DWARF_M68K_A7 = 7, 570a55c6bd8Sjoerg DWARF_M68K_D0 = 8, 571a55c6bd8Sjoerg DWARF_M68K_D7 = 15, 572c05d688cSjoerg DWARF_M68K_FP0 = 16, 573c05d688cSjoerg DWARF_M68K_FP7 = 23, 574a55c6bd8Sjoerg DWARF_M68K_PC = 24, 57535a0f472Sthorpej // DWARF pseudo-register that is an alternate that may be used 57635a0f472Sthorpej // for the return address. 57735a0f472Sthorpej DWARF_M68K_ALT_PC = 25, 578a55c6bd8Sjoerg 579a55c6bd8Sjoerg REGNO_M68K_A0 = 0, 580a55c6bd8Sjoerg REGNO_M68K_A7 = 7, 581a55c6bd8Sjoerg REGNO_M68K_D0 = 8, 582a55c6bd8Sjoerg REGNO_M68K_D7 = 15, 583a55c6bd8Sjoerg REGNO_M68K_PC = 16, 584c05d688cSjoerg REGNO_M68K_FP0 = 17, 585c05d688cSjoerg REGNO_M68K_FP7 = 24, 586a55c6bd8Sjoerg }; 587a55c6bd8Sjoerg 588a55c6bd8Sjoerg class Registers_M68K { 589a55c6bd8Sjoerg public: 590a55c6bd8Sjoerg enum { 591c05d688cSjoerg LAST_REGISTER = REGNO_M68K_FP7, 592c05d688cSjoerg LAST_RESTORE_REG = REGNO_M68K_FP7, 5939788222aSjoerg RETURN_OFFSET = 0, 5940282220bSjoerg RETURN_MASK = 0, 595a55c6bd8Sjoerg }; 596a55c6bd8Sjoerg 597a55c6bd8Sjoerg __dso_hidden Registers_M68K(); 598a55c6bd8Sjoerg dwarf2regno(int num)599a55c6bd8Sjoerg static int dwarf2regno(int num) { 600a55c6bd8Sjoerg if (num >= DWARF_M68K_A0 && num <= DWARF_M68K_A7) 601a55c6bd8Sjoerg return REGNO_M68K_A0 + (num - DWARF_M68K_A0); 602a55c6bd8Sjoerg if (num >= DWARF_M68K_D0 && num <= DWARF_M68K_D7) 603a55c6bd8Sjoerg return REGNO_M68K_D0 + (num - DWARF_M68K_D0); 604c05d688cSjoerg if (num >= DWARF_M68K_FP0 && num <= DWARF_M68K_FP7) 605c05d688cSjoerg return REGNO_M68K_FP0 + (num - DWARF_M68K_FP0); 60635a0f472Sthorpej if (num == DWARF_M68K_PC || num == DWARF_M68K_ALT_PC) 607a55c6bd8Sjoerg return REGNO_M68K_PC; 608a55c6bd8Sjoerg return LAST_REGISTER + 1; 609a55c6bd8Sjoerg } 610a55c6bd8Sjoerg validRegister(int num) const611a55c6bd8Sjoerg bool validRegister(int num) const { 612c05d688cSjoerg return num >= 0 && num <= REGNO_M68K_PC; 613a55c6bd8Sjoerg } 614a55c6bd8Sjoerg getRegister(int num) const615a55c6bd8Sjoerg uint64_t getRegister(int num) const { 616a55c6bd8Sjoerg assert(validRegister(num)); 617a55c6bd8Sjoerg return reg[num]; 618a55c6bd8Sjoerg } 619a55c6bd8Sjoerg setRegister(int num,uint64_t value)620a55c6bd8Sjoerg void setRegister(int num, uint64_t value) { 621a55c6bd8Sjoerg assert(validRegister(num)); 622a55c6bd8Sjoerg reg[num] = value; 623a55c6bd8Sjoerg } 624a55c6bd8Sjoerg getIP() const625a55c6bd8Sjoerg uint64_t getIP() const { return reg[REGNO_M68K_PC]; } 626a55c6bd8Sjoerg setIP(uint64_t value)627a55c6bd8Sjoerg void setIP(uint64_t value) { reg[REGNO_M68K_PC] = value; } 628a55c6bd8Sjoerg getSP() const629a55c6bd8Sjoerg uint64_t getSP() const { return reg[REGNO_M68K_A7]; } 630a55c6bd8Sjoerg setSP(uint64_t value)631a55c6bd8Sjoerg void setSP(uint64_t value) { reg[REGNO_M68K_A7] = value; } 632a55c6bd8Sjoerg validFloatVectorRegister(int num) const633a55c6bd8Sjoerg bool validFloatVectorRegister(int num) const { 634c05d688cSjoerg return num >= REGNO_M68K_FP0 && num <= REGNO_M68K_FP7; 635a55c6bd8Sjoerg } 636a55c6bd8Sjoerg copyFloatVectorRegister(int num,uint64_t addr_)637a55c6bd8Sjoerg void copyFloatVectorRegister(int num, uint64_t addr_) { 638c05d688cSjoerg assert(validFloatVectorRegister(num)); 639c05d688cSjoerg const void *addr = reinterpret_cast<const void *>(addr_); 640c05d688cSjoerg memcpy(fpreg + (num - REGNO_M68K_FP0), addr, sizeof(fpreg[0])); 641a55c6bd8Sjoerg } 642a55c6bd8Sjoerg 643a55c6bd8Sjoerg __dso_hidden void jumpto() const __dead; 644a55c6bd8Sjoerg 645a55c6bd8Sjoerg private: 646c05d688cSjoerg typedef uint32_t fpreg_t[3]; 647c05d688cSjoerg 648a55c6bd8Sjoerg uint32_t reg[REGNO_M68K_PC + 1]; 649c05d688cSjoerg uint32_t dummy; 650c05d688cSjoerg fpreg_t fpreg[8]; 651a55c6bd8Sjoerg }; 652a55c6bd8Sjoerg 653a280fb92Sjoerg enum { 654a280fb92Sjoerg DWARF_SH3_R0 = 0, 655a280fb92Sjoerg DWARF_SH3_R15 = 15, 656a280fb92Sjoerg DWARF_SH3_PC = 16, 657a280fb92Sjoerg DWARF_SH3_PR = 17, 658241d2befSthorpej DWARF_SH3_GBR = 18, 659241d2befSthorpej DWARF_SH3_MACH = 20, 660241d2befSthorpej DWARF_SH3_MACL = 21, 661241d2befSthorpej DWARF_SH3_SR = 22, 662a280fb92Sjoerg 663a280fb92Sjoerg REGNO_SH3_R0 = 0, 664a280fb92Sjoerg REGNO_SH3_R15 = 15, 665a280fb92Sjoerg REGNO_SH3_PC = 16, 666a280fb92Sjoerg REGNO_SH3_PR = 17, 667241d2befSthorpej REGNO_SH3_GBR = 18, 668241d2befSthorpej REGNO_SH3_MACH = 20, 669241d2befSthorpej REGNO_SH3_MACL = 21, 670241d2befSthorpej REGNO_SH3_SR = 22, 671a280fb92Sjoerg }; 672a280fb92Sjoerg 673a280fb92Sjoerg class Registers_SH3 { 674a280fb92Sjoerg public: 675a280fb92Sjoerg enum { 676241d2befSthorpej LAST_REGISTER = REGNO_SH3_SR, 677241d2befSthorpej LAST_RESTORE_REG = REGNO_SH3_SR, 6789788222aSjoerg RETURN_OFFSET = 0, 6790282220bSjoerg RETURN_MASK = 0, 680a280fb92Sjoerg }; 681a280fb92Sjoerg 682a280fb92Sjoerg __dso_hidden Registers_SH3(); 683a280fb92Sjoerg dwarf2regno(int num)684a280fb92Sjoerg static int dwarf2regno(int num) { 685a280fb92Sjoerg if (num >= DWARF_SH3_R0 && num <= DWARF_SH3_R15) 686a280fb92Sjoerg return REGNO_SH3_R0 + (num - DWARF_SH3_R0); 687241d2befSthorpej switch (num) { 688241d2befSthorpej case DWARF_SH3_PC: 689a280fb92Sjoerg return REGNO_SH3_PC; 690241d2befSthorpej case DWARF_SH3_PR: 691a280fb92Sjoerg return REGNO_SH3_PR; 692241d2befSthorpej case DWARF_SH3_GBR: 693241d2befSthorpej return REGNO_SH3_GBR; 694241d2befSthorpej case DWARF_SH3_MACH: 695241d2befSthorpej return REGNO_SH3_MACH; 696241d2befSthorpej case DWARF_SH3_MACL: 697241d2befSthorpej return REGNO_SH3_MACL; 698241d2befSthorpej case DWARF_SH3_SR: 699241d2befSthorpej return REGNO_SH3_SR; 700241d2befSthorpej default: 701a280fb92Sjoerg return LAST_REGISTER + 1; 702a280fb92Sjoerg } 703241d2befSthorpej } 704a280fb92Sjoerg validRegister(int num) const705a280fb92Sjoerg bool validRegister(int num) const { 706241d2befSthorpej return (num >= 0 && num <= REGNO_SH3_GBR) || 707241d2befSthorpej (num >= REGNO_SH3_MACH && num <= REGNO_SH3_SR); 708a280fb92Sjoerg } 709a280fb92Sjoerg getRegister(int num) const710a280fb92Sjoerg uint64_t getRegister(int num) const { 711a280fb92Sjoerg assert(validRegister(num)); 712a280fb92Sjoerg return reg[num]; 713a280fb92Sjoerg } 714a280fb92Sjoerg setRegister(int num,uint64_t value)715a280fb92Sjoerg void setRegister(int num, uint64_t value) { 716a280fb92Sjoerg assert(validRegister(num)); 717a280fb92Sjoerg reg[num] = value; 718a280fb92Sjoerg } 719a280fb92Sjoerg getIP() const720a280fb92Sjoerg uint64_t getIP() const { return reg[REGNO_SH3_PC]; } 721a280fb92Sjoerg setIP(uint64_t value)722a280fb92Sjoerg void setIP(uint64_t value) { reg[REGNO_SH3_PC] = value; } 723a280fb92Sjoerg getSP() const724a280fb92Sjoerg uint64_t getSP() const { return reg[REGNO_SH3_R15]; } 725a280fb92Sjoerg setSP(uint64_t value)726a280fb92Sjoerg void setSP(uint64_t value) { reg[REGNO_SH3_R15] = value; } 727a280fb92Sjoerg validFloatVectorRegister(int num) const728a280fb92Sjoerg bool validFloatVectorRegister(int num) const { return false; } 729a280fb92Sjoerg copyFloatVectorRegister(int num,uint64_t addr_)730a280fb92Sjoerg void copyFloatVectorRegister(int num, uint64_t addr_) {} 731a280fb92Sjoerg 732a280fb92Sjoerg __dso_hidden void jumpto() const __dead; 733a280fb92Sjoerg 734a280fb92Sjoerg private: 735241d2befSthorpej uint32_t reg[REGNO_SH3_SR + 1]; 736a280fb92Sjoerg }; 737a280fb92Sjoerg 738f5cf7457Sjoerg enum { 739f5cf7457Sjoerg DWARF_SPARC64_R0 = 0, 740f5cf7457Sjoerg DWARF_SPARC64_R31 = 31, 741f5cf7457Sjoerg DWARF_SPARC64_PC = 32, 742f5cf7457Sjoerg 743f5cf7457Sjoerg REGNO_SPARC64_R0 = 0, 744f5cf7457Sjoerg REGNO_SPARC64_R14 = 14, 745f5cf7457Sjoerg REGNO_SPARC64_R15 = 15, 746f5cf7457Sjoerg REGNO_SPARC64_R31 = 31, 747f5cf7457Sjoerg REGNO_SPARC64_PC = 32, 748f5cf7457Sjoerg }; 749f5cf7457Sjoerg 750f5cf7457Sjoerg class Registers_SPARC64 { 751f5cf7457Sjoerg public: 752f5cf7457Sjoerg enum { 753f5cf7457Sjoerg LAST_REGISTER = REGNO_SPARC64_PC, 754f5cf7457Sjoerg LAST_RESTORE_REG = REGNO_SPARC64_PC, 755f5cf7457Sjoerg RETURN_OFFSET = 8, 7560282220bSjoerg RETURN_MASK = 0, 757f5cf7457Sjoerg }; 758f5cf7457Sjoerg typedef uint64_t reg_t; 759f5cf7457Sjoerg 760f5cf7457Sjoerg __dso_hidden Registers_SPARC64(); 761f5cf7457Sjoerg dwarf2regno(int num)762f5cf7457Sjoerg static int dwarf2regno(int num) { 763f5cf7457Sjoerg if (num >= DWARF_SPARC64_R0 && num <= DWARF_SPARC64_R31) 764f5cf7457Sjoerg return REGNO_SPARC64_R0 + (num - DWARF_SPARC64_R0); 765f5cf7457Sjoerg if (num == DWARF_SPARC64_PC) 766f5cf7457Sjoerg return REGNO_SPARC64_PC; 767f5cf7457Sjoerg return LAST_REGISTER + 1; 768f5cf7457Sjoerg } 769f5cf7457Sjoerg validRegister(int num) const770f5cf7457Sjoerg bool validRegister(int num) const { 771f5cf7457Sjoerg return num >= 0 && num <= REGNO_SPARC64_PC; 772f5cf7457Sjoerg } 773f5cf7457Sjoerg getRegister(int num) const774f5cf7457Sjoerg uint64_t getRegister(int num) const { 775f5cf7457Sjoerg assert(validRegister(num)); 776f5cf7457Sjoerg return reg[num]; 777f5cf7457Sjoerg } 778f5cf7457Sjoerg setRegister(int num,uint64_t value)779f5cf7457Sjoerg void setRegister(int num, uint64_t value) { 780f5cf7457Sjoerg assert(validRegister(num)); 781f5cf7457Sjoerg reg[num] = value; 782f5cf7457Sjoerg } 783f5cf7457Sjoerg getIP() const784f5cf7457Sjoerg uint64_t getIP() const { return reg[REGNO_SPARC64_PC]; } 785f5cf7457Sjoerg setIP(uint64_t value)786f5cf7457Sjoerg void setIP(uint64_t value) { reg[REGNO_SPARC64_PC] = value; } 787f5cf7457Sjoerg getSP() const788f5cf7457Sjoerg uint64_t getSP() const { return reg[REGNO_SPARC64_R14]; } 789f5cf7457Sjoerg setSP(uint64_t value)790f5cf7457Sjoerg void setSP(uint64_t value) { reg[REGNO_SPARC64_R14] = value; } 791f5cf7457Sjoerg validFloatVectorRegister(int num) const792f5cf7457Sjoerg bool validFloatVectorRegister(int num) const { return false; } 793f5cf7457Sjoerg copyFloatVectorRegister(int num,uint64_t addr_)794f5cf7457Sjoerg void copyFloatVectorRegister(int num, uint64_t addr_) {} 795f5cf7457Sjoerg 796f5cf7457Sjoerg __dso_hidden void jumpto() const __dead; 797f5cf7457Sjoerg 798f5cf7457Sjoerg private: 799f5cf7457Sjoerg uint64_t reg[REGNO_SPARC64_PC + 1]; 800f5cf7457Sjoerg }; 801f5cf7457Sjoerg 802f5cf7457Sjoerg enum { 803f5cf7457Sjoerg DWARF_SPARC_R0 = 0, 804f5cf7457Sjoerg DWARF_SPARC_R31 = 31, 805f5cf7457Sjoerg DWARF_SPARC_PC = 32, 806f5cf7457Sjoerg 807f5cf7457Sjoerg REGNO_SPARC_R0 = 0, 808f5cf7457Sjoerg REGNO_SPARC_R14 = 14, 809f5cf7457Sjoerg REGNO_SPARC_R15 = 15, 810f5cf7457Sjoerg REGNO_SPARC_R31 = 31, 811f5cf7457Sjoerg REGNO_SPARC_PC = 32, 812f5cf7457Sjoerg }; 813f5cf7457Sjoerg 814f5cf7457Sjoerg class Registers_SPARC { 815f5cf7457Sjoerg public: 816f5cf7457Sjoerg enum { 817f5cf7457Sjoerg LAST_REGISTER = REGNO_SPARC_PC, 818f5cf7457Sjoerg LAST_RESTORE_REG = REGNO_SPARC_PC, 819f5cf7457Sjoerg RETURN_OFFSET = 8, 8200282220bSjoerg RETURN_MASK = 0, 821f5cf7457Sjoerg }; 822f5cf7457Sjoerg typedef uint32_t reg_t; 823f5cf7457Sjoerg 824f5cf7457Sjoerg __dso_hidden Registers_SPARC(); 825f5cf7457Sjoerg dwarf2regno(int num)826f5cf7457Sjoerg static int dwarf2regno(int num) { 827f5cf7457Sjoerg if (num >= DWARF_SPARC_R0 && num <= DWARF_SPARC_R31) 828f5cf7457Sjoerg return REGNO_SPARC_R0 + (num - DWARF_SPARC_R0); 829f5cf7457Sjoerg if (num == DWARF_SPARC_PC) 830f5cf7457Sjoerg return REGNO_SPARC_PC; 831f5cf7457Sjoerg return LAST_REGISTER + 1; 832f5cf7457Sjoerg } 833f5cf7457Sjoerg validRegister(int num) const834f5cf7457Sjoerg bool validRegister(int num) const { 835f5cf7457Sjoerg return num >= 0 && num <= REGNO_SPARC_PC; 836f5cf7457Sjoerg } 837f5cf7457Sjoerg getRegister(int num) const838f5cf7457Sjoerg uint64_t getRegister(int num) const { 839f5cf7457Sjoerg assert(validRegister(num)); 840f5cf7457Sjoerg return reg[num]; 841f5cf7457Sjoerg } 842f5cf7457Sjoerg setRegister(int num,uint64_t value)843f5cf7457Sjoerg void setRegister(int num, uint64_t value) { 844f5cf7457Sjoerg assert(validRegister(num)); 845f5cf7457Sjoerg reg[num] = value; 846f5cf7457Sjoerg } 847f5cf7457Sjoerg getIP() const848f5cf7457Sjoerg uint64_t getIP() const { return reg[REGNO_SPARC_PC]; } 849f5cf7457Sjoerg setIP(uint64_t value)850f5cf7457Sjoerg void setIP(uint64_t value) { reg[REGNO_SPARC_PC] = value; } 851f5cf7457Sjoerg getSP() const852f5cf7457Sjoerg uint64_t getSP() const { return reg[REGNO_SPARC_R14]; } 853f5cf7457Sjoerg setSP(uint64_t value)854f5cf7457Sjoerg void setSP(uint64_t value) { reg[REGNO_SPARC_R14] = value; } 855f5cf7457Sjoerg validFloatVectorRegister(int num) const856f5cf7457Sjoerg bool validFloatVectorRegister(int num) const { return false; } 857f5cf7457Sjoerg copyFloatVectorRegister(int num,uint64_t addr_)858f5cf7457Sjoerg void copyFloatVectorRegister(int num, uint64_t addr_) {} 859f5cf7457Sjoerg 860f5cf7457Sjoerg __dso_hidden void jumpto() const __dead; 861f5cf7457Sjoerg 862f5cf7457Sjoerg private: 863f5cf7457Sjoerg uint32_t reg[REGNO_SPARC_PC + 1]; 864f5cf7457Sjoerg }; 865f5cf7457Sjoerg 866e3d4269aSjoerg enum { 867e3d4269aSjoerg DWARF_ALPHA_R0 = 0, 868e3d4269aSjoerg DWARF_ALPHA_R30 = 30, 869e3d4269aSjoerg DWARF_ALPHA_F0 = 32, 870e3d4269aSjoerg DWARF_ALPHA_F30 = 62, 871aa2e0e12Sthorpej DWARF_ALPHA_SIGRETURN = 64, 872e3d4269aSjoerg 873e3d4269aSjoerg REGNO_ALPHA_R0 = 0, 874e3d4269aSjoerg REGNO_ALPHA_R26 = 26, 875e3d4269aSjoerg REGNO_ALPHA_R30 = 30, 876e3d4269aSjoerg REGNO_ALPHA_PC = 31, 877e3d4269aSjoerg REGNO_ALPHA_F0 = 32, 878e3d4269aSjoerg REGNO_ALPHA_F30 = 62, 879aa2e0e12Sthorpej REGNO_ALPHA_SIGRETURN = 64, 880e3d4269aSjoerg }; 881e3d4269aSjoerg 882e3d4269aSjoerg class Registers_Alpha { 883e3d4269aSjoerg public: 884e3d4269aSjoerg enum { 885aa2e0e12Sthorpej LAST_REGISTER = REGNO_ALPHA_SIGRETURN, 886aa2e0e12Sthorpej LAST_RESTORE_REG = REGNO_ALPHA_SIGRETURN, 887e3d4269aSjoerg RETURN_OFFSET = 0, 8880282220bSjoerg RETURN_MASK = 0, 889e3d4269aSjoerg }; 890e3d4269aSjoerg typedef uint32_t reg_t; 891e3d4269aSjoerg 892e3d4269aSjoerg __dso_hidden Registers_Alpha(); 893e3d4269aSjoerg dwarf2regno(int num)894e3d4269aSjoerg static int dwarf2regno(int num) { return num; } 895e3d4269aSjoerg validRegister(int num) const896e3d4269aSjoerg bool validRegister(int num) const { 897aa2e0e12Sthorpej return (num >= 0 && num <= REGNO_ALPHA_PC) || 898aa2e0e12Sthorpej num == REGNO_ALPHA_SIGRETURN; 899e3d4269aSjoerg } 900e3d4269aSjoerg getRegister(int num) const901e3d4269aSjoerg uint64_t getRegister(int num) const { 902e3d4269aSjoerg assert(validRegister(num)); 903aa2e0e12Sthorpej if (num == REGNO_ALPHA_SIGRETURN) 904aa2e0e12Sthorpej return sigreturn_reg; 905aa2e0e12Sthorpej else 906e3d4269aSjoerg return reg[num]; 907e3d4269aSjoerg } 908e3d4269aSjoerg setRegister(int num,uint64_t value)909e3d4269aSjoerg void setRegister(int num, uint64_t value) { 910e3d4269aSjoerg assert(validRegister(num)); 911aa2e0e12Sthorpej if (num == REGNO_ALPHA_SIGRETURN) 912aa2e0e12Sthorpej sigreturn_reg = value; 913aa2e0e12Sthorpej else 914e3d4269aSjoerg reg[num] = value; 915e3d4269aSjoerg } 916e3d4269aSjoerg getIP() const917e3d4269aSjoerg uint64_t getIP() const { return reg[REGNO_ALPHA_PC]; } 918e3d4269aSjoerg setIP(uint64_t value)919e3d4269aSjoerg void setIP(uint64_t value) { reg[REGNO_ALPHA_PC] = value; } 920e3d4269aSjoerg getSP() const921e3d4269aSjoerg uint64_t getSP() const { return reg[REGNO_ALPHA_R30]; } 922e3d4269aSjoerg setSP(uint64_t value)923e3d4269aSjoerg void setSP(uint64_t value) { reg[REGNO_ALPHA_R30] = value; } 924e3d4269aSjoerg validFloatVectorRegister(int num) const925e3d4269aSjoerg bool validFloatVectorRegister(int num) const { 926e3d4269aSjoerg return num >= REGNO_ALPHA_F0 && num <= REGNO_ALPHA_F30; 927e3d4269aSjoerg } 928e3d4269aSjoerg copyFloatVectorRegister(int num,uint64_t addr_)929e3d4269aSjoerg void copyFloatVectorRegister(int num, uint64_t addr_) { 930e3d4269aSjoerg assert(validFloatVectorRegister(num)); 931e3d4269aSjoerg const void *addr = reinterpret_cast<const void *>(addr_); 932e3d4269aSjoerg memcpy(fpreg + (num - REGNO_ALPHA_F0), addr, sizeof(fpreg[0])); 933e3d4269aSjoerg } 934e3d4269aSjoerg 935e3d4269aSjoerg __dso_hidden void jumpto() const __dead; 936e3d4269aSjoerg 937e3d4269aSjoerg private: 938e3d4269aSjoerg uint64_t reg[REGNO_ALPHA_PC + 1]; 939e3d4269aSjoerg uint64_t fpreg[31]; 940aa2e0e12Sthorpej uint64_t sigreturn_reg; 941e3d4269aSjoerg }; 942e3d4269aSjoerg 943a78e9b23Sjoerg enum { 944a78e9b23Sjoerg DWARF_HPPA_R1 = 1, 945a78e9b23Sjoerg DWARF_HPPA_R31 = 31, 946a78e9b23Sjoerg DWARF_HPPA_FR4L = 32, 947a78e9b23Sjoerg DWARF_HPPA_FR31H = 87, 94872dc0638Sskrll DWARF_HPPA_SIGRETURN = 89, 949a78e9b23Sjoerg 950a78e9b23Sjoerg REGNO_HPPA_PC = 0, 951a78e9b23Sjoerg REGNO_HPPA_R1 = 1, 952a78e9b23Sjoerg REGNO_HPPA_R2 = 2, 953a78e9b23Sjoerg REGNO_HPPA_R30 = 30, 954a78e9b23Sjoerg REGNO_HPPA_R31 = 31, 955a78e9b23Sjoerg REGNO_HPPA_FR4L = 32, 956a78e9b23Sjoerg REGNO_HPPA_FR31H = 87, 95772dc0638Sskrll REGNO_HPPA_SIGRETURN = 89, 958a78e9b23Sjoerg }; 959a78e9b23Sjoerg 960a78e9b23Sjoerg class Registers_HPPA { 961a78e9b23Sjoerg public: 962a78e9b23Sjoerg enum { 963a78e9b23Sjoerg LAST_REGISTER = REGNO_HPPA_FR31H, 96472dc0638Sskrll LAST_RESTORE_REG = REGNO_HPPA_SIGRETURN, 9650282220bSjoerg RETURN_OFFSET = 0, 9660282220bSjoerg RETURN_MASK = 3, 967a78e9b23Sjoerg }; 968a78e9b23Sjoerg 969a78e9b23Sjoerg __dso_hidden Registers_HPPA(); 970a78e9b23Sjoerg dwarf2regno(int num)971a78e9b23Sjoerg static int dwarf2regno(int num) { 972a78e9b23Sjoerg if (num >= DWARF_HPPA_R1 && num <= DWARF_HPPA_R31) 973a78e9b23Sjoerg return REGNO_HPPA_R1 + (num - DWARF_HPPA_R1); 974a78e9b23Sjoerg if (num >= DWARF_HPPA_FR4L && num <= DWARF_HPPA_FR31H) 975a78e9b23Sjoerg return REGNO_HPPA_FR4L + (num - DWARF_HPPA_FR31H); 97672dc0638Sskrll if (num == DWARF_HPPA_SIGRETURN) 97772dc0638Sskrll return REGNO_HPPA_SIGRETURN; 978a78e9b23Sjoerg return LAST_REGISTER + 1; 979a78e9b23Sjoerg } 980a78e9b23Sjoerg validRegister(int num) const981a78e9b23Sjoerg bool validRegister(int num) const { 982*3a9ee431Smartin return (num >= REGNO_HPPA_PC && num <= REGNO_HPPA_R31) || 98372dc0638Sskrll num == REGNO_HPPA_SIGRETURN; 984a78e9b23Sjoerg } 985a78e9b23Sjoerg getRegister(int num) const986a78e9b23Sjoerg uint64_t getRegister(int num) const { 987a78e9b23Sjoerg assert(validRegister(num)); 98872dc0638Sskrll if (num == REGNO_HPPA_SIGRETURN) 98972dc0638Sskrll return sigreturn_reg; 99072dc0638Sskrll else 991a78e9b23Sjoerg return reg[num]; 992a78e9b23Sjoerg } 993a78e9b23Sjoerg setRegister(int num,uint64_t value)994a78e9b23Sjoerg void setRegister(int num, uint64_t value) { 995a78e9b23Sjoerg assert(validRegister(num)); 99672dc0638Sskrll if (num == REGNO_HPPA_SIGRETURN) 99772dc0638Sskrll sigreturn_reg = value; 99872dc0638Sskrll else 999a78e9b23Sjoerg reg[num] = value; 1000a78e9b23Sjoerg } 1001a78e9b23Sjoerg getIP() const1002a78e9b23Sjoerg uint64_t getIP() const { return reg[REGNO_HPPA_PC]; } 1003a78e9b23Sjoerg setIP(uint64_t value)1004a78e9b23Sjoerg void setIP(uint64_t value) { reg[REGNO_HPPA_PC] = value; } 1005a78e9b23Sjoerg getSP() const1006a78e9b23Sjoerg uint64_t getSP() const { return reg[REGNO_HPPA_R30]; } 1007a78e9b23Sjoerg setSP(uint64_t value)1008a78e9b23Sjoerg void setSP(uint64_t value) { reg[REGNO_HPPA_R30] = value; } 1009a78e9b23Sjoerg validFloatVectorRegister(int num) const1010a78e9b23Sjoerg bool validFloatVectorRegister(int num) const { 1011a78e9b23Sjoerg return num >= REGNO_HPPA_FR4L && num <= REGNO_HPPA_FR31H; 1012a78e9b23Sjoerg } 1013a78e9b23Sjoerg copyFloatVectorRegister(int num,uint64_t addr_)1014a78e9b23Sjoerg void copyFloatVectorRegister(int num, uint64_t addr_) { 1015a78e9b23Sjoerg assert(validFloatVectorRegister(num)); 1016a78e9b23Sjoerg const void *addr = reinterpret_cast<const void *>(addr_); 1017a78e9b23Sjoerg memcpy(fpreg + (num - REGNO_HPPA_FR4L), addr, sizeof(fpreg[0])); 1018a78e9b23Sjoerg } 1019a78e9b23Sjoerg 1020a78e9b23Sjoerg __dso_hidden void jumpto() const __dead; 1021a78e9b23Sjoerg 1022a78e9b23Sjoerg private: 1023a78e9b23Sjoerg uint32_t reg[REGNO_HPPA_R31 + 1]; 1024a78e9b23Sjoerg uint32_t fpreg[56]; 102572dc0638Sskrll uint32_t sigreturn_reg; 1026a78e9b23Sjoerg }; 1027a78e9b23Sjoerg 1028ed444622Sjoerg enum { 1029ed444622Sjoerg DWARF_MIPS_R1 = 0, 1030ed444622Sjoerg DWARF_MIPS_R31 = 31, 1031ed444622Sjoerg DWARF_MIPS_F0 = 32, 1032ed444622Sjoerg DWARF_MIPS_F31 = 63, 103392db81e4Sthorpej // DWARF Pseudo-registers used by GCC on MIPS for MD{HI,LO} and 103492db81e4Sthorpej // signal handler return address. 103592db81e4Sthorpej DWARF_MIPS_MDHI = 64, 103692db81e4Sthorpej DWARF_MIPS_MDLO = 65, 103792db81e4Sthorpej DWARF_MIPS_SIGRETURN = 66, 1038ed444622Sjoerg 1039ed444622Sjoerg REGNO_MIPS_PC = 0, 1040ed444622Sjoerg REGNO_MIPS_R1 = 0, 1041ed444622Sjoerg REGNO_MIPS_R29 = 29, 1042ed444622Sjoerg REGNO_MIPS_R31 = 31, 1043ed444622Sjoerg REGNO_MIPS_F0 = 33, 104492db81e4Sthorpej REGNO_MIPS_F31 = 64, 104592db81e4Sthorpej // these live in other_reg[] 104692db81e4Sthorpej REGNO_MIPS_MDHI = 65, 104792db81e4Sthorpej REGNO_MIPS_MDLO = 66, 104892db81e4Sthorpej REGNO_MIPS_SIGRETURN = 67 1049ed444622Sjoerg }; 1050ed444622Sjoerg 1051ed444622Sjoerg class Registers_MIPS { 1052ed444622Sjoerg public: 1053ed444622Sjoerg enum { 105492db81e4Sthorpej LAST_REGISTER = REGNO_MIPS_SIGRETURN, 105592db81e4Sthorpej LAST_RESTORE_REG = REGNO_MIPS_SIGRETURN, 1056ed444622Sjoerg RETURN_OFFSET = 0, 10570282220bSjoerg RETURN_MASK = 0, 1058ed444622Sjoerg }; 1059ed444622Sjoerg 1060ed444622Sjoerg __dso_hidden Registers_MIPS(); 1061ed444622Sjoerg dwarf2regno(int num)1062ed444622Sjoerg static int dwarf2regno(int num) { 1063ed444622Sjoerg if (num >= DWARF_MIPS_R1 && num <= DWARF_MIPS_R31) 1064ed444622Sjoerg return REGNO_MIPS_R1 + (num - DWARF_MIPS_R1); 1065ed444622Sjoerg if (num >= DWARF_MIPS_F0 && num <= DWARF_MIPS_F31) 1066ed444622Sjoerg return REGNO_MIPS_F0 + (num - DWARF_MIPS_F0); 106792db81e4Sthorpej if (num >= DWARF_MIPS_MDHI && num <= DWARF_MIPS_SIGRETURN) 106892db81e4Sthorpej return REGNO_MIPS_MDHI + (num - DWARF_MIPS_MDHI); 1069ed444622Sjoerg return LAST_REGISTER + 1; 1070ed444622Sjoerg } 1071ed444622Sjoerg validRegister(int num) const1072ed444622Sjoerg bool validRegister(int num) const { 107392db81e4Sthorpej return (num >= REGNO_MIPS_PC && num <= REGNO_MIPS_R31) || 107492db81e4Sthorpej (num >= REGNO_MIPS_MDHI && num <= REGNO_MIPS_SIGRETURN); 1075ed444622Sjoerg } 1076ed444622Sjoerg getRegister(int num) const1077ed444622Sjoerg uint64_t getRegister(int num) const { 1078ed444622Sjoerg assert(validRegister(num)); 107992db81e4Sthorpej if (num >= REGNO_MIPS_MDHI && num <= REGNO_MIPS_SIGRETURN) 108092db81e4Sthorpej return other_reg[num - REGNO_MIPS_MDHI]; 1081ed444622Sjoerg return reg[num]; 1082ed444622Sjoerg } 1083ed444622Sjoerg setRegister(int num,uint64_t value)1084ed444622Sjoerg void setRegister(int num, uint64_t value) { 1085ed444622Sjoerg assert(validRegister(num)); 108692db81e4Sthorpej if (num >= REGNO_MIPS_MDHI && num <= REGNO_MIPS_SIGRETURN) 108792db81e4Sthorpej other_reg[num - REGNO_MIPS_MDHI] = value; 108892db81e4Sthorpej else 1089ed444622Sjoerg reg[num] = value; 1090ed444622Sjoerg } 1091ed444622Sjoerg getIP() const1092ed444622Sjoerg uint64_t getIP() const { return reg[REGNO_MIPS_PC]; } 1093ed444622Sjoerg setIP(uint64_t value)1094ed444622Sjoerg void setIP(uint64_t value) { reg[REGNO_MIPS_PC] = value; } 1095ed444622Sjoerg getSP() const1096ed444622Sjoerg uint64_t getSP() const { return reg[REGNO_MIPS_R29]; } 1097ed444622Sjoerg setSP(uint64_t value)1098ed444622Sjoerg void setSP(uint64_t value) { reg[REGNO_MIPS_R29] = value; } 1099ed444622Sjoerg validFloatVectorRegister(int num) const1100ed444622Sjoerg bool validFloatVectorRegister(int num) const { 110192db81e4Sthorpej return num >= REGNO_MIPS_F0 && num <= REGNO_MIPS_F31; 1102ed444622Sjoerg } 1103ed444622Sjoerg copyFloatVectorRegister(int num,uint64_t addr_)1104ed444622Sjoerg void copyFloatVectorRegister(int num, uint64_t addr_) { 1105ed444622Sjoerg assert(validFloatVectorRegister(num)); 1106ed444622Sjoerg const void *addr = reinterpret_cast<const void *>(addr_); 1107ed444622Sjoerg memcpy(fpreg + (num - REGNO_MIPS_F0), addr, sizeof(fpreg[0])); 1108ed444622Sjoerg } 1109ed444622Sjoerg 1110ed444622Sjoerg __dso_hidden void jumpto() const __dead; 1111ed444622Sjoerg 1112ed444622Sjoerg private: 1113ed444622Sjoerg uint32_t reg[REGNO_MIPS_R31 + 1]; 1114ed444622Sjoerg uint64_t fpreg[32]; 111592db81e4Sthorpej uint32_t other_reg[3]; 1116ed444622Sjoerg }; 1117ed444622Sjoerg 1118ed444622Sjoerg enum { 1119ed444622Sjoerg DWARF_MIPS64_R1 = 0, 1120ed444622Sjoerg DWARF_MIPS64_R31 = 31, 1121ed444622Sjoerg DWARF_MIPS64_F0 = 32, 1122ed444622Sjoerg DWARF_MIPS64_F31 = 63, 1123b751d63aSthorpej // DWARF Pseudo-registers used by GCC on MIPS for MD{HI,LO} and 1124b751d63aSthorpej // signal handler return address. 1125b751d63aSthorpej DWARF_MIPS64_MDHI = 64, 1126b751d63aSthorpej DWARF_MIPS64_MDLO = 65, 1127b751d63aSthorpej DWARF_MIPS64_SIGRETURN = 66, 1128ed444622Sjoerg 1129ed444622Sjoerg REGNO_MIPS64_PC = 0, 1130ed444622Sjoerg REGNO_MIPS64_R1 = 0, 1131ed444622Sjoerg REGNO_MIPS64_R29 = 29, 1132ed444622Sjoerg REGNO_MIPS64_R31 = 31, 1133ed444622Sjoerg REGNO_MIPS64_F0 = 33, 1134b751d63aSthorpej REGNO_MIPS64_F31 = 64, 1135b751d63aSthorpej // these live in other_reg[] 1136b751d63aSthorpej REGNO_MIPS64_MDHI = 65, 1137b751d63aSthorpej REGNO_MIPS64_MDLO = 66, 1138b751d63aSthorpej REGNO_MIPS64_SIGRETURN = 67 1139ed444622Sjoerg }; 1140ed444622Sjoerg 1141ed444622Sjoerg class Registers_MIPS64 { 1142ed444622Sjoerg public: 1143ed444622Sjoerg enum { 1144b751d63aSthorpej LAST_REGISTER = REGNO_MIPS_SIGRETURN, 1145b751d63aSthorpej LAST_RESTORE_REG = REGNO_MIPS_SIGRETURN, 1146ed444622Sjoerg RETURN_OFFSET = 0, 11470282220bSjoerg RETURN_MASK = 0, 1148ed444622Sjoerg }; 1149ed444622Sjoerg 1150ed444622Sjoerg __dso_hidden Registers_MIPS64(); 1151ed444622Sjoerg dwarf2regno(int num)1152ed444622Sjoerg static int dwarf2regno(int num) { 1153ed444622Sjoerg if (num >= DWARF_MIPS64_R1 && num <= DWARF_MIPS64_R31) 1154ed444622Sjoerg return REGNO_MIPS64_R1 + (num - DWARF_MIPS64_R1); 1155ed444622Sjoerg if (num >= DWARF_MIPS64_F0 && num <= DWARF_MIPS64_F31) 1156ed444622Sjoerg return REGNO_MIPS64_F0 + (num - DWARF_MIPS64_F0); 1157b751d63aSthorpej if (num >= DWARF_MIPS64_MDHI && num <= DWARF_MIPS64_SIGRETURN) 1158b751d63aSthorpej return REGNO_MIPS64_MDHI + (num - DWARF_MIPS64_MDHI); 1159ed444622Sjoerg return LAST_REGISTER + 1; 1160ed444622Sjoerg } 1161ed444622Sjoerg validRegister(int num) const1162ed444622Sjoerg bool validRegister(int num) const { 1163b7465dafSskrll return (num >= REGNO_MIPS64_PC && num <= REGNO_MIPS64_R31) || 1164b751d63aSthorpej (num >= REGNO_MIPS64_MDHI && num <= REGNO_MIPS64_SIGRETURN); 1165ed444622Sjoerg } 1166ed444622Sjoerg getRegister(int num) const1167ed444622Sjoerg uint64_t getRegister(int num) const { 1168ed444622Sjoerg assert(validRegister(num)); 1169b751d63aSthorpej if (num >= REGNO_MIPS64_MDHI && num <= REGNO_MIPS64_SIGRETURN) 1170b751d63aSthorpej return other_reg[num - REGNO_MIPS64_MDHI]; 1171ed444622Sjoerg return reg[num]; 1172ed444622Sjoerg } 1173ed444622Sjoerg setRegister(int num,uint64_t value)1174ed444622Sjoerg void setRegister(int num, uint64_t value) { 1175ed444622Sjoerg assert(validRegister(num)); 1176b751d63aSthorpej if (num >= REGNO_MIPS64_MDHI && num <= REGNO_MIPS64_SIGRETURN) 1177b751d63aSthorpej other_reg[num - REGNO_MIPS64_MDHI] = value; 1178b751d63aSthorpej else 1179ed444622Sjoerg reg[num] = value; 1180ed444622Sjoerg } 1181ed444622Sjoerg getIP() const1182ed444622Sjoerg uint64_t getIP() const { return reg[REGNO_MIPS64_PC]; } 1183ed444622Sjoerg setIP(uint64_t value)1184ed444622Sjoerg void setIP(uint64_t value) { reg[REGNO_MIPS64_PC] = value; } 1185ed444622Sjoerg getSP() const1186ed444622Sjoerg uint64_t getSP() const { return reg[REGNO_MIPS64_R29]; } 1187ed444622Sjoerg setSP(uint64_t value)1188ed444622Sjoerg void setSP(uint64_t value) { reg[REGNO_MIPS64_R29] = value; } 1189ed444622Sjoerg validFloatVectorRegister(int num) const1190ed444622Sjoerg bool validFloatVectorRegister(int num) const { 1191b751d63aSthorpej return num >= REGNO_MIPS64_F0 && num <= REGNO_MIPS64_F31; 1192ed444622Sjoerg } 1193ed444622Sjoerg copyFloatVectorRegister(int num,uint64_t addr_)1194ed444622Sjoerg void copyFloatVectorRegister(int num, uint64_t addr_) { 1195ed444622Sjoerg assert(validFloatVectorRegister(num)); 1196ed444622Sjoerg const void *addr = reinterpret_cast<const void *>(addr_); 1197ed444622Sjoerg memcpy(fpreg + (num - REGNO_MIPS64_F0), addr, sizeof(fpreg[0])); 1198ed444622Sjoerg } 1199ed444622Sjoerg 1200ed444622Sjoerg __dso_hidden void jumpto() const __dead; 1201ed444622Sjoerg 1202ed444622Sjoerg private: 1203ed444622Sjoerg uint64_t reg[REGNO_MIPS64_R31 + 1]; 1204ed444622Sjoerg uint64_t fpreg[32]; 1205b751d63aSthorpej uint64_t other_reg[3]; 1206ed444622Sjoerg }; 1207ed444622Sjoerg 1208938bf86eSmatt enum { 1209938bf86eSmatt DWARF_OR1K_R0 = 0, 1210938bf86eSmatt DWARF_OR1K_SP = 1, 1211938bf86eSmatt DWARF_OR1K_LR = 9, 1212938bf86eSmatt DWARF_OR1K_R31 = 31, 1213938bf86eSmatt DWARF_OR1K_FPCSR = 32, 1214938bf86eSmatt 1215938bf86eSmatt REGNO_OR1K_R0 = 0, 1216938bf86eSmatt REGNO_OR1K_SP = 1, 1217938bf86eSmatt REGNO_OR1K_LR = 9, 1218938bf86eSmatt REGNO_OR1K_R31 = 31, 1219938bf86eSmatt REGNO_OR1K_FPCSR = 32, 1220938bf86eSmatt }; 1221938bf86eSmatt 1222938bf86eSmatt class Registers_or1k { 1223938bf86eSmatt public: 1224938bf86eSmatt enum { 1225938bf86eSmatt LAST_REGISTER = REGNO_OR1K_FPCSR, 1226938bf86eSmatt LAST_RESTORE_REG = REGNO_OR1K_FPCSR, 1227938bf86eSmatt RETURN_OFFSET = 0, 12280282220bSjoerg RETURN_MASK = 0, 1229938bf86eSmatt }; 1230938bf86eSmatt 1231938bf86eSmatt __dso_hidden Registers_or1k(); 1232938bf86eSmatt dwarf2regno(int num)1233938bf86eSmatt static int dwarf2regno(int num) { 1234938bf86eSmatt if (num >= DWARF_OR1K_R0 && num <= DWARF_OR1K_R31) 1235938bf86eSmatt return REGNO_OR1K_R0 + (num - DWARF_OR1K_R0); 1236938bf86eSmatt if (num == DWARF_OR1K_FPCSR) 1237938bf86eSmatt return REGNO_OR1K_FPCSR; 1238938bf86eSmatt return LAST_REGISTER + 1; 1239938bf86eSmatt } 1240938bf86eSmatt validRegister(int num) const1241938bf86eSmatt bool validRegister(int num) const { 1242938bf86eSmatt return num >= 0 && num <= LAST_RESTORE_REG; 1243938bf86eSmatt } 1244938bf86eSmatt getRegister(int num) const1245938bf86eSmatt uint64_t getRegister(int num) const { 1246938bf86eSmatt assert(validRegister(num)); 1247938bf86eSmatt return reg[num]; 1248938bf86eSmatt } 1249938bf86eSmatt setRegister(int num,uint64_t value)1250938bf86eSmatt void setRegister(int num, uint64_t value) { 1251938bf86eSmatt assert(validRegister(num)); 1252938bf86eSmatt reg[num] = value; 1253938bf86eSmatt } 1254938bf86eSmatt getIP() const1255938bf86eSmatt uint64_t getIP() const { return reg[REGNO_OR1K_LR]; } 1256938bf86eSmatt setIP(uint64_t value)1257938bf86eSmatt void setIP(uint64_t value) { reg[REGNO_OR1K_LR] = value; } 1258938bf86eSmatt getSP() const1259938bf86eSmatt uint64_t getSP() const { return reg[REGNO_OR1K_SP]; } 1260938bf86eSmatt setSP(uint64_t value)1261938bf86eSmatt void setSP(uint64_t value) { reg[REGNO_OR1K_SP] = value; } 1262938bf86eSmatt validFloatVectorRegister(int num) const1263938bf86eSmatt bool validFloatVectorRegister(int num) const { 1264938bf86eSmatt return false; 1265938bf86eSmatt } 1266938bf86eSmatt copyFloatVectorRegister(int num,uint64_t addr_)1267938bf86eSmatt void copyFloatVectorRegister(int num, uint64_t addr_) { 1268938bf86eSmatt } 1269938bf86eSmatt 1270938bf86eSmatt __dso_hidden void jumpto() const __dead; 1271938bf86eSmatt 1272938bf86eSmatt private: 1273938bf86eSmatt uint32_t reg[REGNO_OR1K_FPCSR + 1]; 1274938bf86eSmatt }; 1275938bf86eSmatt 1276a6ecde39Sjoerg #if __i386__ 1277a6ecde39Sjoerg typedef Registers_x86 NativeUnwindRegisters; 1278a6ecde39Sjoerg #elif __x86_64__ 1279a6ecde39Sjoerg typedef Registers_x86_64 NativeUnwindRegisters; 1280a6ecde39Sjoerg #elif __powerpc__ 1281a6ecde39Sjoerg typedef Registers_ppc32 NativeUnwindRegisters; 1282aa37019dSmatt #elif __aarch64__ 1283aa37019dSmatt typedef Registers_aarch64 NativeUnwindRegisters; 1284bdd3372bSjoerg #elif __arm__ 1285a6ecde39Sjoerg typedef Registers_arm32 NativeUnwindRegisters; 1286a6ecde39Sjoerg #elif __vax__ 1287a6ecde39Sjoerg typedef Registers_vax NativeUnwindRegisters; 1288a6ecde39Sjoerg #elif __m68k__ 1289a6ecde39Sjoerg typedef Registers_M68K NativeUnwindRegisters; 1290ed444622Sjoerg #elif __mips_n64 || __mips_n32 1291ed444622Sjoerg typedef Registers_MIPS64 NativeUnwindRegisters; 1292ed444622Sjoerg #elif __mips__ 1293ed444622Sjoerg typedef Registers_MIPS NativeUnwindRegisters; 1294a6ecde39Sjoerg #elif __sh3__ 1295a6ecde39Sjoerg typedef Registers_SH3 NativeUnwindRegisters; 1296f5cf7457Sjoerg #elif __sparc64__ 1297f5cf7457Sjoerg typedef Registers_SPARC64 NativeUnwindRegisters; 1298f5cf7457Sjoerg #elif __sparc__ 1299f5cf7457Sjoerg typedef Registers_SPARC NativeUnwindRegisters; 1300e3d4269aSjoerg #elif __alpha__ 1301e3d4269aSjoerg typedef Registers_Alpha NativeUnwindRegisters; 1302a78e9b23Sjoerg #elif __hppa__ 1303a78e9b23Sjoerg typedef Registers_HPPA NativeUnwindRegisters; 1304938bf86eSmatt #elif __or1k__ 1305938bf86eSmatt typedef Registers_or1k NativeUnwindRegisters; 1306a6ecde39Sjoerg #endif 1307aa0b96d0Sjoerg } // namespace _Unwind 1308aa0b96d0Sjoerg 1309aa0b96d0Sjoerg #endif // __REGISTERS_HPP__ 1310