xref: /netbsd/sys/lib/libunwind/Registers.hpp (revision 3a9ee431)
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