xref: /netbsd/sys/lib/libunwind/Registers.hpp (revision 8026a450)
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 
44aa0b96d0Sjoerg   static int dwarf2regno(int num) { return num; }
45aa0b96d0Sjoerg 
46aa0b96d0Sjoerg   bool validRegister(int num) const {
47aa0b96d0Sjoerg     return num >= REGNO_X86_EAX && num <= REGNO_X86_EDI;
48aa0b96d0Sjoerg   }
49aa0b96d0Sjoerg 
50aa0b96d0Sjoerg   uint32_t getRegister(int num) const {
51aa0b96d0Sjoerg     assert(validRegister(num));
52aa0b96d0Sjoerg     return reg[num];
53aa0b96d0Sjoerg   }
54aa0b96d0Sjoerg 
55aa0b96d0Sjoerg   void setRegister(int num, uint32_t value) {
56aa0b96d0Sjoerg     assert(validRegister(num));
57aa0b96d0Sjoerg     reg[num] = value;
58aa0b96d0Sjoerg   }
59aa0b96d0Sjoerg 
60aa0b96d0Sjoerg   uint32_t getIP() const { return reg[REGNO_X86_EIP]; }
61aa0b96d0Sjoerg 
62aa0b96d0Sjoerg   void setIP(uint32_t value) { reg[REGNO_X86_EIP] = value; }
63aa0b96d0Sjoerg 
64aa0b96d0Sjoerg   uint32_t getSP() const { return reg[REGNO_X86_ESP]; }
65aa0b96d0Sjoerg 
66aa0b96d0Sjoerg   void setSP(uint32_t value) { reg[REGNO_X86_ESP] = value; }
67aa0b96d0Sjoerg 
68aa0b96d0Sjoerg   bool validFloatVectorRegister(int num) const { return false; }
69aa0b96d0Sjoerg 
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 
110aa0b96d0Sjoerg   static int dwarf2regno(int num) { return num; }
111aa0b96d0Sjoerg 
112aa0b96d0Sjoerg   bool validRegister(int num) const {
113aa0b96d0Sjoerg     return num >= REGNO_X86_64_RAX && num <= REGNO_X86_64_R15;
114aa0b96d0Sjoerg   }
115aa0b96d0Sjoerg 
116aa0b96d0Sjoerg   uint64_t getRegister(int num) const {
117aa0b96d0Sjoerg     assert(validRegister(num));
118aa0b96d0Sjoerg     return reg[num];
119aa0b96d0Sjoerg   }
120aa0b96d0Sjoerg 
121aa0b96d0Sjoerg   void setRegister(int num, uint64_t value) {
122aa0b96d0Sjoerg     assert(validRegister(num));
123aa0b96d0Sjoerg     reg[num] = value;
124aa0b96d0Sjoerg   }
125aa0b96d0Sjoerg 
126aa0b96d0Sjoerg   uint64_t getIP() const { return reg[REGNO_X86_64_RIP]; }
127aa0b96d0Sjoerg 
128aa0b96d0Sjoerg   void setIP(uint64_t value) { reg[REGNO_X86_64_RIP] = value; }
129aa0b96d0Sjoerg 
130aa0b96d0Sjoerg   uint64_t getSP() const { return reg[REGNO_X86_64_RSP]; }
131aa0b96d0Sjoerg 
132aa0b96d0Sjoerg   void setSP(uint64_t value) { reg[REGNO_X86_64_RSP] = value; }
133aa0b96d0Sjoerg 
134aa0b96d0Sjoerg   bool validFloatVectorRegister(int num) const { return false; }
135aa0b96d0Sjoerg 
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,
151b238bfcaSjoerg   DWARF_PPC32_CR = 70,
152b238bfcaSjoerg   DWARF_PPC32_V0 = 77,
153b238bfcaSjoerg   DWARF_PPC32_V31 = 108,
154b238bfcaSjoerg 
155aa0b96d0Sjoerg   REGNO_PPC32_R0 = 0,
156b238bfcaSjoerg   REGNO_PPC32_R1 = 1,
157aa0b96d0Sjoerg   REGNO_PPC32_R31 = 31,
158b238bfcaSjoerg   REGNO_PPC32_LR = 32,
159b238bfcaSjoerg   REGNO_PPC32_CR = 33,
160b238bfcaSjoerg   REGNO_PPC32_SRR0 = 34,
161b238bfcaSjoerg 
162aa0b96d0Sjoerg   REGNO_PPC32_F0 = REGNO_PPC32_SRR0 + 1,
163aa0b96d0Sjoerg   REGNO_PPC32_F31 = REGNO_PPC32_F0 + 31,
164aa0b96d0Sjoerg   REGNO_PPC32_V0 = REGNO_PPC32_F31 + 1,
165aa0b96d0Sjoerg   REGNO_PPC32_V31 = REGNO_PPC32_V0 + 31,
166aa0b96d0Sjoerg };
167aa0b96d0Sjoerg 
168aa0b96d0Sjoerg class Registers_ppc32 {
169aa0b96d0Sjoerg public:
170aa0b96d0Sjoerg   enum {
171aa0b96d0Sjoerg     LAST_REGISTER = REGNO_PPC32_V31,
172916de6d0Sjoerg     LAST_RESTORE_REG = REGNO_PPC32_V31,
1739788222aSjoerg     RETURN_OFFSET = 0,
1740282220bSjoerg     RETURN_MASK = 0,
175aa0b96d0Sjoerg   };
176aa0b96d0Sjoerg 
177aa0b96d0Sjoerg   __dso_hidden Registers_ppc32();
178aa0b96d0Sjoerg 
179aa0b96d0Sjoerg   static int dwarf2regno(int num) {
180aa0b96d0Sjoerg     if (num >= DWARF_PPC32_R0 && num <= DWARF_PPC32_R31)
181aa0b96d0Sjoerg       return REGNO_PPC32_R0 + (num - DWARF_PPC32_R0);
182aa0b96d0Sjoerg     if (num >= DWARF_PPC32_F0 && num <= DWARF_PPC32_F31)
183aa0b96d0Sjoerg       return REGNO_PPC32_F0 + (num - DWARF_PPC32_F0);
184aa0b96d0Sjoerg     if (num >= DWARF_PPC32_V0 && num <= DWARF_PPC32_V31)
185aa0b96d0Sjoerg       return REGNO_PPC32_V0 + (num - DWARF_PPC32_V0);
186b238bfcaSjoerg     switch (num) {
187b238bfcaSjoerg     case DWARF_PPC32_LR:
188b238bfcaSjoerg       return REGNO_PPC32_LR;
189b238bfcaSjoerg     case DWARF_PPC32_CR:
190b238bfcaSjoerg       return REGNO_PPC32_CR;
191b238bfcaSjoerg     default:
192aa0b96d0Sjoerg       return LAST_REGISTER + 1;
193aa0b96d0Sjoerg     }
194b238bfcaSjoerg   }
195aa0b96d0Sjoerg 
196aa0b96d0Sjoerg   bool validRegister(int num) const {
197aa0b96d0Sjoerg     return num >= 0 && num <= LAST_RESTORE_REG;
198aa0b96d0Sjoerg   }
199aa0b96d0Sjoerg 
200aa0b96d0Sjoerg   uint64_t getRegister(int num) const {
201aa0b96d0Sjoerg     assert(validRegister(num));
202aa0b96d0Sjoerg     return reg[num];
203aa0b96d0Sjoerg   }
204aa0b96d0Sjoerg 
205aa0b96d0Sjoerg   void setRegister(int num, uint64_t value) {
206aa0b96d0Sjoerg     assert(validRegister(num));
207aa0b96d0Sjoerg     reg[num] = value;
208aa0b96d0Sjoerg   }
209aa0b96d0Sjoerg 
210aa0b96d0Sjoerg   uint64_t getIP() const { return reg[REGNO_PPC32_SRR0]; }
211aa0b96d0Sjoerg 
212aa0b96d0Sjoerg   void setIP(uint64_t value) { reg[REGNO_PPC32_SRR0] = value; }
213aa0b96d0Sjoerg 
214aa0b96d0Sjoerg   uint64_t getSP() const { return reg[REGNO_PPC32_R1]; }
215aa0b96d0Sjoerg 
216aa0b96d0Sjoerg   void setSP(uint64_t value) { reg[REGNO_PPC32_R1] = value; }
217aa0b96d0Sjoerg 
218aa0b96d0Sjoerg   bool validFloatVectorRegister(int num) const {
219aa0b96d0Sjoerg     return (num >= REGNO_PPC32_F0 && num <= REGNO_PPC32_F31) ||
220aa0b96d0Sjoerg            (num >= REGNO_PPC32_V0 && num <= REGNO_PPC32_V31);
221aa0b96d0Sjoerg   }
222aa0b96d0Sjoerg 
223aa0b96d0Sjoerg   void copyFloatVectorRegister(int num, uint64_t addr_) {
224aa0b96d0Sjoerg     const void *addr = reinterpret_cast<const void *>(addr_);
225aa0b96d0Sjoerg     if (num >= REGNO_PPC32_F0 && num <= REGNO_PPC32_F31)
226aa0b96d0Sjoerg       memcpy(fpreg + (num - REGNO_PPC32_F0), addr, sizeof(fpreg[0]));
227aa0b96d0Sjoerg     else
228aa0b96d0Sjoerg       memcpy(vecreg + (num - REGNO_PPC32_V0), addr, sizeof(vecreg[0]));
229aa0b96d0Sjoerg   }
230aa0b96d0Sjoerg 
231aa0b96d0Sjoerg   __dso_hidden void jumpto() const __dead;
232aa0b96d0Sjoerg 
233aa0b96d0Sjoerg private:
234aa0b96d0Sjoerg   struct vecreg_t {
235aa0b96d0Sjoerg     uint64_t low, high;
236aa0b96d0Sjoerg   };
237aa0b96d0Sjoerg   uint32_t reg[REGNO_PPC32_SRR0 + 1];
238b238bfcaSjoerg   uint32_t dummy;
239aa0b96d0Sjoerg   uint64_t fpreg[32];
240aa0b96d0Sjoerg   vecreg_t vecreg[64];
241aa0b96d0Sjoerg };
242aa0b96d0Sjoerg 
243eb98b3ccSmatt enum {
244aa37019dSmatt   DWARF_AARCH64_X0 = 0,
245aa37019dSmatt   DWARF_AARCH64_X30 = 30,
246aa37019dSmatt   DWARF_AARCH64_SP = 31,
247aa37019dSmatt   DWARF_AARCH64_V0 = 64,
248aa37019dSmatt   DWARF_AARCH64_V31 = 95,
249aa37019dSmatt 
250aa37019dSmatt   REGNO_AARCH64_X0 = 0,
251aa37019dSmatt   REGNO_AARCH64_X30 = 30,
252aa37019dSmatt   REGNO_AARCH64_SP = 31,
25328f5faf2Sjoerg   REGNO_AARCH64_V0 = 32,
25428f5faf2Sjoerg   REGNO_AARCH64_V31 = 63,
255aa37019dSmatt };
256aa37019dSmatt 
257aa37019dSmatt class Registers_aarch64 {
258aa37019dSmatt public:
259aa37019dSmatt   enum {
260aa37019dSmatt     LAST_RESTORE_REG = REGNO_AARCH64_V31,
261aa37019dSmatt     LAST_REGISTER = REGNO_AARCH64_V31,
262aa37019dSmatt     RETURN_OFFSET = 0,
2630282220bSjoerg     RETURN_MASK = 0,
264aa37019dSmatt   };
265aa37019dSmatt 
266aa37019dSmatt   __dso_hidden Registers_aarch64();
267aa37019dSmatt 
268aa37019dSmatt   static int dwarf2regno(int num) {
269aa37019dSmatt     if (num >= DWARF_AARCH64_X0 && num <= DWARF_AARCH64_X30)
270aa37019dSmatt       return REGNO_AARCH64_X0 + (num - DWARF_AARCH64_X0);
271aa37019dSmatt     if (num == DWARF_AARCH64_SP)
272aa37019dSmatt       return REGNO_AARCH64_SP;
273aa37019dSmatt     if (num >= DWARF_AARCH64_V0 && num <= DWARF_AARCH64_V31)
274aa37019dSmatt       return REGNO_AARCH64_V0 + (num - DWARF_AARCH64_V0);
275aa37019dSmatt     return LAST_REGISTER + 1;
276aa37019dSmatt   }
277aa37019dSmatt 
278aa37019dSmatt   bool validRegister(int num) const {
279aa37019dSmatt     return num >= 0 && num <= LAST_RESTORE_REG;
280aa37019dSmatt   }
281aa37019dSmatt 
282aa37019dSmatt   uint64_t getRegister(int num) const {
283aa37019dSmatt     assert(validRegister(num));
284aa37019dSmatt     return reg[num];
285aa37019dSmatt   }
286aa37019dSmatt 
287aa37019dSmatt   void setRegister(int num, uint64_t value) {
288aa37019dSmatt     assert(validRegister(num));
289aa37019dSmatt     reg[num] = value;
290aa37019dSmatt   }
291aa37019dSmatt 
292aa37019dSmatt   uint64_t getIP() const { return reg[REGNO_AARCH64_X30]; }
293aa37019dSmatt 
294aa37019dSmatt   void setIP(uint64_t value) { reg[REGNO_AARCH64_X30] = value; }
295aa37019dSmatt 
296aa37019dSmatt   uint64_t getSP() const { return reg[REGNO_AARCH64_SP]; }
297aa37019dSmatt 
298aa37019dSmatt   void setSP(uint64_t value) { reg[REGNO_AARCH64_SP] = value; }
299aa37019dSmatt 
300aa37019dSmatt   bool validFloatVectorRegister(int num) const {
301aa37019dSmatt     return (num >= REGNO_AARCH64_V0 && num <= REGNO_AARCH64_V31);
302aa37019dSmatt   }
303aa37019dSmatt 
304aa37019dSmatt   void copyFloatVectorRegister(int num, uint64_t addr_) {
305aa37019dSmatt     const void *addr = reinterpret_cast<const void *>(addr_);
30628f5faf2Sjoerg     memcpy(vecreg + (num - REGNO_AARCH64_V0), addr, 16);
307aa37019dSmatt   }
308aa37019dSmatt 
309aa37019dSmatt   __dso_hidden void jumpto() const __dead;
310aa37019dSmatt 
311aa37019dSmatt private:
31228f5faf2Sjoerg   uint64_t reg[REGNO_AARCH64_SP + 1];
31328f5faf2Sjoerg   uint64_t vecreg[64];
314aa37019dSmatt };
315aa37019dSmatt 
316aa37019dSmatt enum {
317eb98b3ccSmatt   DWARF_ARM32_R0 = 0,
318eb98b3ccSmatt   DWARF_ARM32_R15 = 15,
319eb98b3ccSmatt   DWARF_ARM32_SPSR = 128,
320155a9ee6Sjoerg   DWARF_ARM32_S0 = 64,
321*8026a450Srin   DWARF_ARM32_S31 = 95,
322bdd3372bSjoerg   DWARF_ARM32_D0 = 256,
323eb98b3ccSmatt   DWARF_ARM32_D31 = 287,
324eb98b3ccSmatt   REGNO_ARM32_R0 = 0,
325eb98b3ccSmatt   REGNO_ARM32_SP = 13,
326eb98b3ccSmatt   REGNO_ARM32_R15 = 15,
327eb98b3ccSmatt   REGNO_ARM32_SPSR = 16,
328bdd3372bSjoerg   REGNO_ARM32_D0 = 17,
329bdd3372bSjoerg   REGNO_ARM32_D15 = 32,
330bdd3372bSjoerg   REGNO_ARM32_D31 = 48,
331155a9ee6Sjoerg   REGNO_ARM32_S0 = 49,
332*8026a450Srin   REGNO_ARM32_S31 = 80,
333eb98b3ccSmatt };
334eb98b3ccSmatt 
335eb98b3ccSmatt class Registers_arm32 {
336eb98b3ccSmatt public:
337eb98b3ccSmatt   enum {
338eb98b3ccSmatt     LAST_REGISTER = REGNO_ARM32_D31,
339bdd3372bSjoerg     LAST_RESTORE_REG = REGNO_ARM32_D31,
3409788222aSjoerg     RETURN_OFFSET = 0,
3410282220bSjoerg     RETURN_MASK = 0,
342eb98b3ccSmatt   };
343eb98b3ccSmatt 
344eb98b3ccSmatt   __dso_hidden Registers_arm32();
345eb98b3ccSmatt 
346eb98b3ccSmatt   static int dwarf2regno(int num) {
347eb98b3ccSmatt     if (num >= DWARF_ARM32_R0 && num <= DWARF_ARM32_R15)
348eb98b3ccSmatt       return REGNO_ARM32_R0 + (num - DWARF_ARM32_R0);
349eb98b3ccSmatt     if (num == DWARF_ARM32_SPSR)
350eb98b3ccSmatt       return REGNO_ARM32_SPSR;
351bdd3372bSjoerg     if (num >= DWARF_ARM32_D0 && num <= DWARF_ARM32_D31)
352bdd3372bSjoerg       return REGNO_ARM32_D0 + (num - DWARF_ARM32_D0);
35385f18f75Srin     if (num >= DWARF_ARM32_S0 && num <= DWARF_ARM32_S31)
354155a9ee6Sjoerg       return REGNO_ARM32_S0 + (num - DWARF_ARM32_S0);
355eb98b3ccSmatt     return LAST_REGISTER + 1;
356eb98b3ccSmatt   }
357eb98b3ccSmatt 
358eb98b3ccSmatt   bool validRegister(int num) const {
359bdd3372bSjoerg     return num >= 0 && num <= REGNO_ARM32_SPSR;
360eb98b3ccSmatt   }
361eb98b3ccSmatt 
362eb98b3ccSmatt   uint64_t getRegister(int num) const {
363eb98b3ccSmatt     assert(validRegister(num));
364eb98b3ccSmatt     return reg[num];
365eb98b3ccSmatt   }
366eb98b3ccSmatt 
367eb98b3ccSmatt   void setRegister(int num, uint64_t value) {
368eb98b3ccSmatt     assert(validRegister(num));
369eb98b3ccSmatt     reg[num] = value;
370eb98b3ccSmatt   }
371eb98b3ccSmatt 
372eb98b3ccSmatt   uint64_t getIP() const { return reg[REGNO_ARM32_R15]; }
373eb98b3ccSmatt 
374eb98b3ccSmatt   void setIP(uint64_t value) { reg[REGNO_ARM32_R15] = value; }
375eb98b3ccSmatt 
376eb98b3ccSmatt   uint64_t getSP() const { return reg[REGNO_ARM32_SP]; }
377eb98b3ccSmatt 
378eb98b3ccSmatt   void setSP(uint64_t value) { reg[REGNO_ARM32_SP] = value; }
379eb98b3ccSmatt 
380eb98b3ccSmatt   bool validFloatVectorRegister(int num) const {
381155a9ee6Sjoerg     return (num >= REGNO_ARM32_D0 && num <= REGNO_ARM32_S31);
382eb98b3ccSmatt   }
383eb98b3ccSmatt 
384eb98b3ccSmatt   void copyFloatVectorRegister(int num, uint64_t addr_) {
385d03fef5bSrin     assert(validFloatVectorRegister(num));
386155a9ee6Sjoerg     const void *addr = reinterpret_cast<const void *>(addr_);
387155a9ee6Sjoerg     if (num >= REGNO_ARM32_S0 && num <= REGNO_ARM32_S31) {
38885f18f75Srin       if ((flags & FLAGS_VFPV2_USED) == 0) {
38985f18f75Srin         lazyVFPv2();
39085f18f75Srin         flags |= FLAGS_VFPV2_USED;
391155a9ee6Sjoerg       }
392155a9ee6Sjoerg       /*
393155a9ee6Sjoerg        * Emulate single precision register as half of the
394155a9ee6Sjoerg        * corresponding double register.
395155a9ee6Sjoerg        */
396155a9ee6Sjoerg       int dnum = (num - REGNO_ARM32_S0) / 2;
397155a9ee6Sjoerg       int part = (num - REGNO_ARM32_S0) % 2;
398155a9ee6Sjoerg #if _BYTE_ORDER == _BIG_ENDIAN
399155a9ee6Sjoerg       part = 1 - part;
400155a9ee6Sjoerg #endif
401155a9ee6Sjoerg       memcpy(fpreg + dnum + part * sizeof(fpreg[0]) / 2,
402155a9ee6Sjoerg         addr, sizeof(fpreg[0]) / 2);
403155a9ee6Sjoerg     }
404bdd3372bSjoerg     if (num <= REGNO_ARM32_D15) {
40585f18f75Srin       if ((flags & FLAGS_VFPV2_USED) == 0) {
40685f18f75Srin         lazyVFPv2();
40785f18f75Srin         flags |= FLAGS_VFPV2_USED;
408bdd3372bSjoerg       }
409bdd3372bSjoerg     } else {
41085f18f75Srin       if ((flags & FLAGS_VFPV3_USED) == 0) {
41185f18f75Srin         lazyVFPv3();
41285f18f75Srin         flags |= FLAGS_VFPV3_USED;
413bdd3372bSjoerg       }
414bdd3372bSjoerg     }
415eb98b3ccSmatt     memcpy(fpreg + (num - REGNO_ARM32_D0), addr, sizeof(fpreg[0]));
416eb98b3ccSmatt   }
417eb98b3ccSmatt 
41885f18f75Srin   __dso_hidden void lazyVFPv2();
41985f18f75Srin   __dso_hidden void lazyVFPv3();
420eb98b3ccSmatt   __dso_hidden void jumpto() const __dead;
421eb98b3ccSmatt 
422eb98b3ccSmatt private:
423eb98b3ccSmatt   uint32_t reg[REGNO_ARM32_SPSR + 1];
424bdd3372bSjoerg   uint32_t flags;
425eb98b3ccSmatt   uint64_t fpreg[32];
42685f18f75Srin 
42785f18f75Srin   enum {
42885f18f75Srin     FLAGS_VFPV2_USED = 0x1,
42985f18f75Srin     FLAGS_VFPV3_USED = 0x2,
43085f18f75Srin   };
431eb98b3ccSmatt };
432eb98b3ccSmatt 
433396ee378Sjoerg enum {
434396ee378Sjoerg   DWARF_VAX_R0 = 0,
435396ee378Sjoerg   DWARF_VAX_R15 = 15,
436396ee378Sjoerg   DWARF_VAX_PSW = 16,
437396ee378Sjoerg 
438396ee378Sjoerg   REGNO_VAX_R0 = 0,
439396ee378Sjoerg   REGNO_VAX_R14 = 14,
440396ee378Sjoerg   REGNO_VAX_R15 = 15,
441396ee378Sjoerg   REGNO_VAX_PSW = 16,
442396ee378Sjoerg };
443396ee378Sjoerg 
444396ee378Sjoerg class Registers_vax {
445396ee378Sjoerg public:
446396ee378Sjoerg   enum {
447396ee378Sjoerg     LAST_REGISTER = REGNO_VAX_PSW,
448396ee378Sjoerg     LAST_RESTORE_REG = REGNO_VAX_PSW,
4499788222aSjoerg     RETURN_OFFSET = 0,
4500282220bSjoerg     RETURN_MASK = 0,
451396ee378Sjoerg   };
452396ee378Sjoerg 
453396ee378Sjoerg   __dso_hidden Registers_vax();
454396ee378Sjoerg 
455396ee378Sjoerg   static int dwarf2regno(int num) {
456396ee378Sjoerg     if (num >= DWARF_VAX_R0 && num <= DWARF_VAX_R15)
457396ee378Sjoerg       return REGNO_VAX_R0 + (num - DWARF_VAX_R0);
458396ee378Sjoerg     if (num == DWARF_VAX_PSW)
459396ee378Sjoerg       return REGNO_VAX_PSW;
460396ee378Sjoerg     return LAST_REGISTER + 1;
461396ee378Sjoerg   }
462396ee378Sjoerg 
463396ee378Sjoerg   bool validRegister(int num) const {
464396ee378Sjoerg     return num >= 0 && num <= LAST_RESTORE_REG;
465396ee378Sjoerg   }
466396ee378Sjoerg 
467396ee378Sjoerg   uint64_t getRegister(int num) const {
468396ee378Sjoerg     assert(validRegister(num));
469396ee378Sjoerg     return reg[num];
470396ee378Sjoerg   }
471396ee378Sjoerg 
472396ee378Sjoerg   void setRegister(int num, uint64_t value) {
473396ee378Sjoerg     assert(validRegister(num));
474396ee378Sjoerg     reg[num] = value;
475396ee378Sjoerg   }
476396ee378Sjoerg 
477396ee378Sjoerg   uint64_t getIP() const { return reg[REGNO_VAX_R15]; }
478396ee378Sjoerg 
479396ee378Sjoerg   void setIP(uint64_t value) { reg[REGNO_VAX_R15] = value; }
480396ee378Sjoerg 
481396ee378Sjoerg   uint64_t getSP() const { return reg[REGNO_VAX_R14]; }
482396ee378Sjoerg 
483396ee378Sjoerg   void setSP(uint64_t value) { reg[REGNO_VAX_R14] = value; }
484396ee378Sjoerg 
485396ee378Sjoerg   bool validFloatVectorRegister(int num) const {
486396ee378Sjoerg     return false;
487396ee378Sjoerg   }
488396ee378Sjoerg 
489396ee378Sjoerg   void copyFloatVectorRegister(int num, uint64_t addr_) {
490396ee378Sjoerg   }
491396ee378Sjoerg 
492396ee378Sjoerg   __dso_hidden void jumpto() const __dead;
493396ee378Sjoerg 
494396ee378Sjoerg private:
495396ee378Sjoerg   uint32_t reg[REGNO_VAX_PSW + 1];
496396ee378Sjoerg };
497396ee378Sjoerg 
498a55c6bd8Sjoerg enum {
499a55c6bd8Sjoerg   DWARF_M68K_A0 = 0,
500a55c6bd8Sjoerg   DWARF_M68K_A7 = 7,
501a55c6bd8Sjoerg   DWARF_M68K_D0 = 8,
502a55c6bd8Sjoerg   DWARF_M68K_D7 = 15,
503c05d688cSjoerg   DWARF_M68K_FP0 = 16,
504c05d688cSjoerg   DWARF_M68K_FP7 = 23,
505a55c6bd8Sjoerg   DWARF_M68K_PC = 24,
506a55c6bd8Sjoerg 
507a55c6bd8Sjoerg   REGNO_M68K_A0 = 0,
508a55c6bd8Sjoerg   REGNO_M68K_A7 = 7,
509a55c6bd8Sjoerg   REGNO_M68K_D0 = 8,
510a55c6bd8Sjoerg   REGNO_M68K_D7 = 15,
511a55c6bd8Sjoerg   REGNO_M68K_PC = 16,
512c05d688cSjoerg   REGNO_M68K_FP0 = 17,
513c05d688cSjoerg   REGNO_M68K_FP7 = 24,
514a55c6bd8Sjoerg };
515a55c6bd8Sjoerg 
516a55c6bd8Sjoerg class Registers_M68K {
517a55c6bd8Sjoerg public:
518a55c6bd8Sjoerg   enum {
519c05d688cSjoerg     LAST_REGISTER = REGNO_M68K_FP7,
520c05d688cSjoerg     LAST_RESTORE_REG = REGNO_M68K_FP7,
5219788222aSjoerg     RETURN_OFFSET = 0,
5220282220bSjoerg     RETURN_MASK = 0,
523a55c6bd8Sjoerg   };
524a55c6bd8Sjoerg 
525a55c6bd8Sjoerg   __dso_hidden Registers_M68K();
526a55c6bd8Sjoerg 
527a55c6bd8Sjoerg   static int dwarf2regno(int num) {
528a55c6bd8Sjoerg     if (num >= DWARF_M68K_A0 && num <= DWARF_M68K_A7)
529a55c6bd8Sjoerg       return REGNO_M68K_A0 + (num - DWARF_M68K_A0);
530a55c6bd8Sjoerg     if (num >= DWARF_M68K_D0 && num <= DWARF_M68K_D7)
531a55c6bd8Sjoerg       return REGNO_M68K_D0 + (num - DWARF_M68K_D0);
532c05d688cSjoerg     if (num >= DWARF_M68K_FP0 && num <= DWARF_M68K_FP7)
533c05d688cSjoerg       return REGNO_M68K_FP0 + (num - DWARF_M68K_FP0);
534a55c6bd8Sjoerg     if (num == DWARF_M68K_PC)
535a55c6bd8Sjoerg       return REGNO_M68K_PC;
536a55c6bd8Sjoerg     return LAST_REGISTER + 1;
537a55c6bd8Sjoerg   }
538a55c6bd8Sjoerg 
539a55c6bd8Sjoerg   bool validRegister(int num) const {
540c05d688cSjoerg     return num >= 0 && num <= REGNO_M68K_PC;
541a55c6bd8Sjoerg   }
542a55c6bd8Sjoerg 
543a55c6bd8Sjoerg   uint64_t getRegister(int num) const {
544a55c6bd8Sjoerg     assert(validRegister(num));
545a55c6bd8Sjoerg     return reg[num];
546a55c6bd8Sjoerg   }
547a55c6bd8Sjoerg 
548a55c6bd8Sjoerg   void setRegister(int num, uint64_t value) {
549a55c6bd8Sjoerg     assert(validRegister(num));
550a55c6bd8Sjoerg     reg[num] = value;
551a55c6bd8Sjoerg   }
552a55c6bd8Sjoerg 
553a55c6bd8Sjoerg   uint64_t getIP() const { return reg[REGNO_M68K_PC]; }
554a55c6bd8Sjoerg 
555a55c6bd8Sjoerg   void setIP(uint64_t value) { reg[REGNO_M68K_PC] = value; }
556a55c6bd8Sjoerg 
557a55c6bd8Sjoerg   uint64_t getSP() const { return reg[REGNO_M68K_A7]; }
558a55c6bd8Sjoerg 
559a55c6bd8Sjoerg   void setSP(uint64_t value) { reg[REGNO_M68K_A7] = value; }
560a55c6bd8Sjoerg 
561a55c6bd8Sjoerg   bool validFloatVectorRegister(int num) const {
562c05d688cSjoerg     return num >= REGNO_M68K_FP0 && num <= REGNO_M68K_FP7;
563a55c6bd8Sjoerg   }
564a55c6bd8Sjoerg 
565a55c6bd8Sjoerg   void copyFloatVectorRegister(int num, uint64_t addr_) {
566c05d688cSjoerg     assert(validFloatVectorRegister(num));
567c05d688cSjoerg     const void *addr = reinterpret_cast<const void *>(addr_);
568c05d688cSjoerg     memcpy(fpreg + (num - REGNO_M68K_FP0), addr, sizeof(fpreg[0]));
569a55c6bd8Sjoerg   }
570a55c6bd8Sjoerg 
571a55c6bd8Sjoerg   __dso_hidden void jumpto() const __dead;
572a55c6bd8Sjoerg 
573a55c6bd8Sjoerg private:
574c05d688cSjoerg   typedef uint32_t fpreg_t[3];
575c05d688cSjoerg 
576a55c6bd8Sjoerg   uint32_t reg[REGNO_M68K_PC + 1];
577c05d688cSjoerg   uint32_t dummy;
578c05d688cSjoerg   fpreg_t fpreg[8];
579a55c6bd8Sjoerg };
580a55c6bd8Sjoerg 
581a280fb92Sjoerg enum {
582a280fb92Sjoerg   DWARF_SH3_R0 = 0,
583a280fb92Sjoerg   DWARF_SH3_R15 = 15,
584a280fb92Sjoerg   DWARF_SH3_PC = 16,
585a280fb92Sjoerg   DWARF_SH3_PR = 17,
586a280fb92Sjoerg 
587a280fb92Sjoerg   REGNO_SH3_R0 = 0,
588a280fb92Sjoerg   REGNO_SH3_R15 = 15,
589a280fb92Sjoerg   REGNO_SH3_PC = 16,
590a280fb92Sjoerg   REGNO_SH3_PR = 17,
591a280fb92Sjoerg };
592a280fb92Sjoerg 
593a280fb92Sjoerg class Registers_SH3 {
594a280fb92Sjoerg public:
595a280fb92Sjoerg   enum {
596a280fb92Sjoerg     LAST_REGISTER = REGNO_SH3_PR,
597a280fb92Sjoerg     LAST_RESTORE_REG = REGNO_SH3_PR,
5989788222aSjoerg     RETURN_OFFSET = 0,
5990282220bSjoerg     RETURN_MASK = 0,
600a280fb92Sjoerg   };
601a280fb92Sjoerg 
602a280fb92Sjoerg   __dso_hidden Registers_SH3();
603a280fb92Sjoerg 
604a280fb92Sjoerg   static int dwarf2regno(int num) {
605a280fb92Sjoerg     if (num >= DWARF_SH3_R0 && num <= DWARF_SH3_R15)
606a280fb92Sjoerg       return REGNO_SH3_R0 + (num - DWARF_SH3_R0);
607a280fb92Sjoerg     if (num == DWARF_SH3_PC)
608a280fb92Sjoerg       return REGNO_SH3_PC;
609a280fb92Sjoerg     if (num == DWARF_SH3_PR)
610a280fb92Sjoerg       return REGNO_SH3_PR;
611a280fb92Sjoerg     return LAST_REGISTER + 1;
612a280fb92Sjoerg   }
613a280fb92Sjoerg 
614a280fb92Sjoerg   bool validRegister(int num) const {
615a280fb92Sjoerg     return num >= 0 && num <= REGNO_SH3_PR;
616a280fb92Sjoerg   }
617a280fb92Sjoerg 
618a280fb92Sjoerg   uint64_t getRegister(int num) const {
619a280fb92Sjoerg     assert(validRegister(num));
620a280fb92Sjoerg     return reg[num];
621a280fb92Sjoerg   }
622a280fb92Sjoerg 
623a280fb92Sjoerg   void setRegister(int num, uint64_t value) {
624a280fb92Sjoerg     assert(validRegister(num));
625a280fb92Sjoerg     reg[num] = value;
626a280fb92Sjoerg   }
627a280fb92Sjoerg 
628a280fb92Sjoerg   uint64_t getIP() const { return reg[REGNO_SH3_PC]; }
629a280fb92Sjoerg 
630a280fb92Sjoerg   void setIP(uint64_t value) { reg[REGNO_SH3_PC] = value; }
631a280fb92Sjoerg 
632a280fb92Sjoerg   uint64_t getSP() const { return reg[REGNO_SH3_R15]; }
633a280fb92Sjoerg 
634a280fb92Sjoerg   void setSP(uint64_t value) { reg[REGNO_SH3_R15] = value; }
635a280fb92Sjoerg 
636a280fb92Sjoerg   bool validFloatVectorRegister(int num) const { return false; }
637a280fb92Sjoerg 
638a280fb92Sjoerg   void copyFloatVectorRegister(int num, uint64_t addr_) {}
639a280fb92Sjoerg 
640a280fb92Sjoerg   __dso_hidden void jumpto() const __dead;
641a280fb92Sjoerg 
642a280fb92Sjoerg private:
643a280fb92Sjoerg   uint32_t reg[REGNO_SH3_PR + 1];
644a280fb92Sjoerg };
645a280fb92Sjoerg 
646f5cf7457Sjoerg enum {
647f5cf7457Sjoerg   DWARF_SPARC64_R0 = 0,
648f5cf7457Sjoerg   DWARF_SPARC64_R31 = 31,
649f5cf7457Sjoerg   DWARF_SPARC64_PC = 32,
650f5cf7457Sjoerg 
651f5cf7457Sjoerg   REGNO_SPARC64_R0 = 0,
652f5cf7457Sjoerg   REGNO_SPARC64_R14 = 14,
653f5cf7457Sjoerg   REGNO_SPARC64_R15 = 15,
654f5cf7457Sjoerg   REGNO_SPARC64_R31 = 31,
655f5cf7457Sjoerg   REGNO_SPARC64_PC = 32,
656f5cf7457Sjoerg };
657f5cf7457Sjoerg 
658f5cf7457Sjoerg class Registers_SPARC64 {
659f5cf7457Sjoerg public:
660f5cf7457Sjoerg   enum {
661f5cf7457Sjoerg     LAST_REGISTER = REGNO_SPARC64_PC,
662f5cf7457Sjoerg     LAST_RESTORE_REG = REGNO_SPARC64_PC,
663f5cf7457Sjoerg     RETURN_OFFSET = 8,
6640282220bSjoerg     RETURN_MASK = 0,
665f5cf7457Sjoerg   };
666f5cf7457Sjoerg   typedef uint64_t reg_t;
667f5cf7457Sjoerg 
668f5cf7457Sjoerg   __dso_hidden Registers_SPARC64();
669f5cf7457Sjoerg 
670f5cf7457Sjoerg   static int dwarf2regno(int num) {
671f5cf7457Sjoerg     if (num >= DWARF_SPARC64_R0 && num <= DWARF_SPARC64_R31)
672f5cf7457Sjoerg       return REGNO_SPARC64_R0 + (num - DWARF_SPARC64_R0);
673f5cf7457Sjoerg     if (num == DWARF_SPARC64_PC)
674f5cf7457Sjoerg       return REGNO_SPARC64_PC;
675f5cf7457Sjoerg     return LAST_REGISTER + 1;
676f5cf7457Sjoerg   }
677f5cf7457Sjoerg 
678f5cf7457Sjoerg   bool validRegister(int num) const {
679f5cf7457Sjoerg     return num >= 0 && num <= REGNO_SPARC64_PC;
680f5cf7457Sjoerg   }
681f5cf7457Sjoerg 
682f5cf7457Sjoerg   uint64_t getRegister(int num) const {
683f5cf7457Sjoerg     assert(validRegister(num));
684f5cf7457Sjoerg     return reg[num];
685f5cf7457Sjoerg   }
686f5cf7457Sjoerg 
687f5cf7457Sjoerg   void setRegister(int num, uint64_t value) {
688f5cf7457Sjoerg     assert(validRegister(num));
689f5cf7457Sjoerg     reg[num] = value;
690f5cf7457Sjoerg   }
691f5cf7457Sjoerg 
692f5cf7457Sjoerg   uint64_t getIP() const { return reg[REGNO_SPARC64_PC]; }
693f5cf7457Sjoerg 
694f5cf7457Sjoerg   void setIP(uint64_t value) { reg[REGNO_SPARC64_PC] = value; }
695f5cf7457Sjoerg 
696f5cf7457Sjoerg   uint64_t getSP() const { return reg[REGNO_SPARC64_R14]; }
697f5cf7457Sjoerg 
698f5cf7457Sjoerg   void setSP(uint64_t value) { reg[REGNO_SPARC64_R14] = value; }
699f5cf7457Sjoerg 
700f5cf7457Sjoerg   bool validFloatVectorRegister(int num) const { return false; }
701f5cf7457Sjoerg 
702f5cf7457Sjoerg   void copyFloatVectorRegister(int num, uint64_t addr_) {}
703f5cf7457Sjoerg 
704f5cf7457Sjoerg   __dso_hidden void jumpto() const __dead;
705f5cf7457Sjoerg 
706f5cf7457Sjoerg private:
707f5cf7457Sjoerg   uint64_t reg[REGNO_SPARC64_PC + 1];
708f5cf7457Sjoerg };
709f5cf7457Sjoerg 
710f5cf7457Sjoerg enum {
711f5cf7457Sjoerg   DWARF_SPARC_R0 = 0,
712f5cf7457Sjoerg   DWARF_SPARC_R31 = 31,
713f5cf7457Sjoerg   DWARF_SPARC_PC = 32,
714f5cf7457Sjoerg 
715f5cf7457Sjoerg   REGNO_SPARC_R0 = 0,
716f5cf7457Sjoerg   REGNO_SPARC_R14 = 14,
717f5cf7457Sjoerg   REGNO_SPARC_R15 = 15,
718f5cf7457Sjoerg   REGNO_SPARC_R31 = 31,
719f5cf7457Sjoerg   REGNO_SPARC_PC = 32,
720f5cf7457Sjoerg };
721f5cf7457Sjoerg 
722f5cf7457Sjoerg class Registers_SPARC {
723f5cf7457Sjoerg public:
724f5cf7457Sjoerg   enum {
725f5cf7457Sjoerg     LAST_REGISTER = REGNO_SPARC_PC,
726f5cf7457Sjoerg     LAST_RESTORE_REG = REGNO_SPARC_PC,
727f5cf7457Sjoerg     RETURN_OFFSET = 8,
7280282220bSjoerg     RETURN_MASK = 0,
729f5cf7457Sjoerg   };
730f5cf7457Sjoerg   typedef uint32_t reg_t;
731f5cf7457Sjoerg 
732f5cf7457Sjoerg   __dso_hidden Registers_SPARC();
733f5cf7457Sjoerg 
734f5cf7457Sjoerg   static int dwarf2regno(int num) {
735f5cf7457Sjoerg     if (num >= DWARF_SPARC_R0 && num <= DWARF_SPARC_R31)
736f5cf7457Sjoerg       return REGNO_SPARC_R0 + (num - DWARF_SPARC_R0);
737f5cf7457Sjoerg     if (num == DWARF_SPARC_PC)
738f5cf7457Sjoerg       return REGNO_SPARC_PC;
739f5cf7457Sjoerg     return LAST_REGISTER + 1;
740f5cf7457Sjoerg   }
741f5cf7457Sjoerg 
742f5cf7457Sjoerg   bool validRegister(int num) const {
743f5cf7457Sjoerg     return num >= 0 && num <= REGNO_SPARC_PC;
744f5cf7457Sjoerg   }
745f5cf7457Sjoerg 
746f5cf7457Sjoerg   uint64_t getRegister(int num) const {
747f5cf7457Sjoerg     assert(validRegister(num));
748f5cf7457Sjoerg     return reg[num];
749f5cf7457Sjoerg   }
750f5cf7457Sjoerg 
751f5cf7457Sjoerg   void setRegister(int num, uint64_t value) {
752f5cf7457Sjoerg     assert(validRegister(num));
753f5cf7457Sjoerg     reg[num] = value;
754f5cf7457Sjoerg   }
755f5cf7457Sjoerg 
756f5cf7457Sjoerg   uint64_t getIP() const { return reg[REGNO_SPARC_PC]; }
757f5cf7457Sjoerg 
758f5cf7457Sjoerg   void setIP(uint64_t value) { reg[REGNO_SPARC_PC] = value; }
759f5cf7457Sjoerg 
760f5cf7457Sjoerg   uint64_t getSP() const { return reg[REGNO_SPARC_R14]; }
761f5cf7457Sjoerg 
762f5cf7457Sjoerg   void setSP(uint64_t value) { reg[REGNO_SPARC_R14] = value; }
763f5cf7457Sjoerg 
764f5cf7457Sjoerg   bool validFloatVectorRegister(int num) const { return false; }
765f5cf7457Sjoerg 
766f5cf7457Sjoerg   void copyFloatVectorRegister(int num, uint64_t addr_) {}
767f5cf7457Sjoerg 
768f5cf7457Sjoerg   __dso_hidden void jumpto() const __dead;
769f5cf7457Sjoerg 
770f5cf7457Sjoerg private:
771f5cf7457Sjoerg   uint32_t reg[REGNO_SPARC_PC + 1];
772f5cf7457Sjoerg };
773f5cf7457Sjoerg 
774e3d4269aSjoerg enum {
775e3d4269aSjoerg   DWARF_ALPHA_R0 = 0,
776e3d4269aSjoerg   DWARF_ALPHA_R30 = 30,
777e3d4269aSjoerg   DWARF_ALPHA_F0 = 32,
778e3d4269aSjoerg   DWARF_ALPHA_F30 = 62,
779e3d4269aSjoerg 
780e3d4269aSjoerg   REGNO_ALPHA_R0 = 0,
781e3d4269aSjoerg   REGNO_ALPHA_R26 = 26,
782e3d4269aSjoerg   REGNO_ALPHA_R30 = 30,
783e3d4269aSjoerg   REGNO_ALPHA_PC = 31,
784e3d4269aSjoerg   REGNO_ALPHA_F0 = 32,
785e3d4269aSjoerg   REGNO_ALPHA_F30 = 62,
786e3d4269aSjoerg };
787e3d4269aSjoerg 
788e3d4269aSjoerg class Registers_Alpha {
789e3d4269aSjoerg public:
790e3d4269aSjoerg   enum {
791e3d4269aSjoerg     LAST_REGISTER = REGNO_ALPHA_F30,
792e3d4269aSjoerg     LAST_RESTORE_REG = REGNO_ALPHA_F30,
793e3d4269aSjoerg     RETURN_OFFSET = 0,
7940282220bSjoerg     RETURN_MASK = 0,
795e3d4269aSjoerg   };
796e3d4269aSjoerg   typedef uint32_t reg_t;
797e3d4269aSjoerg 
798e3d4269aSjoerg   __dso_hidden Registers_Alpha();
799e3d4269aSjoerg 
800e3d4269aSjoerg   static int dwarf2regno(int num) { return num; }
801e3d4269aSjoerg 
802e3d4269aSjoerg   bool validRegister(int num) const {
803e3d4269aSjoerg     return num >= 0 && num <= REGNO_ALPHA_PC;
804e3d4269aSjoerg   }
805e3d4269aSjoerg 
806e3d4269aSjoerg   uint64_t getRegister(int num) const {
807e3d4269aSjoerg     assert(validRegister(num));
808e3d4269aSjoerg     return reg[num];
809e3d4269aSjoerg   }
810e3d4269aSjoerg 
811e3d4269aSjoerg   void setRegister(int num, uint64_t value) {
812e3d4269aSjoerg     assert(validRegister(num));
813e3d4269aSjoerg     reg[num] = value;
814e3d4269aSjoerg   }
815e3d4269aSjoerg 
816e3d4269aSjoerg   uint64_t getIP() const { return reg[REGNO_ALPHA_PC]; }
817e3d4269aSjoerg 
818e3d4269aSjoerg   void setIP(uint64_t value) { reg[REGNO_ALPHA_PC] = value; }
819e3d4269aSjoerg 
820e3d4269aSjoerg   uint64_t getSP() const { return reg[REGNO_ALPHA_R30]; }
821e3d4269aSjoerg 
822e3d4269aSjoerg   void setSP(uint64_t value) { reg[REGNO_ALPHA_R30] = value; }
823e3d4269aSjoerg 
824e3d4269aSjoerg   bool validFloatVectorRegister(int num) const {
825e3d4269aSjoerg     return num >= REGNO_ALPHA_F0 && num <= REGNO_ALPHA_F30;
826e3d4269aSjoerg   }
827e3d4269aSjoerg 
828e3d4269aSjoerg   void copyFloatVectorRegister(int num, uint64_t addr_) {
829e3d4269aSjoerg     assert(validFloatVectorRegister(num));
830e3d4269aSjoerg     const void *addr = reinterpret_cast<const void *>(addr_);
831e3d4269aSjoerg     memcpy(fpreg + (num - REGNO_ALPHA_F0), addr, sizeof(fpreg[0]));
832e3d4269aSjoerg   }
833e3d4269aSjoerg 
834e3d4269aSjoerg   __dso_hidden void jumpto() const __dead;
835e3d4269aSjoerg 
836e3d4269aSjoerg private:
837e3d4269aSjoerg   uint64_t reg[REGNO_ALPHA_PC + 1];
838e3d4269aSjoerg   uint64_t fpreg[31];
839e3d4269aSjoerg };
840e3d4269aSjoerg 
841a78e9b23Sjoerg enum {
842a78e9b23Sjoerg   DWARF_HPPA_R1 = 1,
843a78e9b23Sjoerg   DWARF_HPPA_R31 = 31,
844a78e9b23Sjoerg   DWARF_HPPA_FR4L = 32,
845a78e9b23Sjoerg   DWARF_HPPA_FR31H = 87,
846a78e9b23Sjoerg 
847a78e9b23Sjoerg   REGNO_HPPA_PC = 0,
848a78e9b23Sjoerg   REGNO_HPPA_R1 = 1,
849a78e9b23Sjoerg   REGNO_HPPA_R2 = 2,
850a78e9b23Sjoerg   REGNO_HPPA_R30 = 30,
851a78e9b23Sjoerg   REGNO_HPPA_R31 = 31,
852a78e9b23Sjoerg   REGNO_HPPA_FR4L = 32,
853a78e9b23Sjoerg   REGNO_HPPA_FR31H = 87,
854a78e9b23Sjoerg };
855a78e9b23Sjoerg 
856a78e9b23Sjoerg class Registers_HPPA {
857a78e9b23Sjoerg public:
858a78e9b23Sjoerg   enum {
859a78e9b23Sjoerg     LAST_REGISTER = REGNO_HPPA_FR31H,
860a78e9b23Sjoerg     LAST_RESTORE_REG = REGNO_HPPA_FR31H,
8610282220bSjoerg     RETURN_OFFSET = 0,
8620282220bSjoerg     RETURN_MASK = 3,
863a78e9b23Sjoerg   };
864a78e9b23Sjoerg 
865a78e9b23Sjoerg   __dso_hidden Registers_HPPA();
866a78e9b23Sjoerg 
867a78e9b23Sjoerg   static int dwarf2regno(int num) {
868a78e9b23Sjoerg     if (num >= DWARF_HPPA_R1 && num <= DWARF_HPPA_R31)
869a78e9b23Sjoerg       return REGNO_HPPA_R1 + (num - DWARF_HPPA_R1);
870a78e9b23Sjoerg     if (num >= DWARF_HPPA_FR4L && num <= DWARF_HPPA_FR31H)
871a78e9b23Sjoerg       return REGNO_HPPA_FR4L + (num - DWARF_HPPA_FR31H);
872a78e9b23Sjoerg     return LAST_REGISTER + 1;
873a78e9b23Sjoerg   }
874a78e9b23Sjoerg 
875a78e9b23Sjoerg   bool validRegister(int num) const {
876a78e9b23Sjoerg     return num >= REGNO_HPPA_PC && num <= REGNO_HPPA_R31;
877a78e9b23Sjoerg   }
878a78e9b23Sjoerg 
879a78e9b23Sjoerg   uint64_t getRegister(int num) const {
880a78e9b23Sjoerg     assert(validRegister(num));
881a78e9b23Sjoerg     return reg[num];
882a78e9b23Sjoerg   }
883a78e9b23Sjoerg 
884a78e9b23Sjoerg   void setRegister(int num, uint64_t value) {
885a78e9b23Sjoerg     assert(validRegister(num));
886a78e9b23Sjoerg     reg[num] = value;
887a78e9b23Sjoerg   }
888a78e9b23Sjoerg 
889a78e9b23Sjoerg   uint64_t getIP() const { return reg[REGNO_HPPA_PC]; }
890a78e9b23Sjoerg 
891a78e9b23Sjoerg   void setIP(uint64_t value) { reg[REGNO_HPPA_PC] = value; }
892a78e9b23Sjoerg 
893a78e9b23Sjoerg   uint64_t getSP() const { return reg[REGNO_HPPA_R30]; }
894a78e9b23Sjoerg 
895a78e9b23Sjoerg   void setSP(uint64_t value) { reg[REGNO_HPPA_R30] = value; }
896a78e9b23Sjoerg 
897a78e9b23Sjoerg   bool validFloatVectorRegister(int num) const {
898a78e9b23Sjoerg     return num >= REGNO_HPPA_FR4L && num <= REGNO_HPPA_FR31H;
899a78e9b23Sjoerg   }
900a78e9b23Sjoerg 
901a78e9b23Sjoerg   void copyFloatVectorRegister(int num, uint64_t addr_) {
902a78e9b23Sjoerg     assert(validFloatVectorRegister(num));
903a78e9b23Sjoerg     const void *addr = reinterpret_cast<const void *>(addr_);
904a78e9b23Sjoerg     memcpy(fpreg + (num - REGNO_HPPA_FR4L), addr, sizeof(fpreg[0]));
905a78e9b23Sjoerg   }
906a78e9b23Sjoerg 
907a78e9b23Sjoerg   __dso_hidden void jumpto() const __dead;
908a78e9b23Sjoerg 
909a78e9b23Sjoerg private:
910a78e9b23Sjoerg   uint32_t reg[REGNO_HPPA_R31 + 1];
911a78e9b23Sjoerg   uint32_t fpreg[56];
912a78e9b23Sjoerg };
913a78e9b23Sjoerg 
914ed444622Sjoerg enum {
915ed444622Sjoerg   DWARF_MIPS_R1 = 0,
916ed444622Sjoerg   DWARF_MIPS_R31 = 31,
917ed444622Sjoerg   DWARF_MIPS_F0 = 32,
918ed444622Sjoerg   DWARF_MIPS_F31 = 63,
919ed444622Sjoerg 
920ed444622Sjoerg   REGNO_MIPS_PC = 0,
921ed444622Sjoerg   REGNO_MIPS_R1 = 0,
922ed444622Sjoerg   REGNO_MIPS_R29 = 29,
923ed444622Sjoerg   REGNO_MIPS_R31 = 31,
924ed444622Sjoerg   REGNO_MIPS_F0 = 33,
925ed444622Sjoerg   REGNO_MIPS_F31 = 64
926ed444622Sjoerg };
927ed444622Sjoerg 
928ed444622Sjoerg class Registers_MIPS {
929ed444622Sjoerg public:
930ed444622Sjoerg   enum {
931ed444622Sjoerg     LAST_REGISTER = REGNO_MIPS_F31,
932ed444622Sjoerg     LAST_RESTORE_REG = REGNO_MIPS_F31,
933ed444622Sjoerg     RETURN_OFFSET = 0,
9340282220bSjoerg     RETURN_MASK = 0,
935ed444622Sjoerg   };
936ed444622Sjoerg 
937ed444622Sjoerg   __dso_hidden Registers_MIPS();
938ed444622Sjoerg 
939ed444622Sjoerg   static int dwarf2regno(int num) {
940ed444622Sjoerg     if (num >= DWARF_MIPS_R1 && num <= DWARF_MIPS_R31)
941ed444622Sjoerg       return REGNO_MIPS_R1 + (num - DWARF_MIPS_R1);
942ed444622Sjoerg     if (num >= DWARF_MIPS_F0 && num <= DWARF_MIPS_F31)
943ed444622Sjoerg       return REGNO_MIPS_F0 + (num - DWARF_MIPS_F0);
944ed444622Sjoerg     return LAST_REGISTER + 1;
945ed444622Sjoerg   }
946ed444622Sjoerg 
947ed444622Sjoerg   bool validRegister(int num) const {
948ed444622Sjoerg     return num >= REGNO_MIPS_PC && num <= REGNO_MIPS_R31;
949ed444622Sjoerg   }
950ed444622Sjoerg 
951ed444622Sjoerg   uint64_t getRegister(int num) const {
952ed444622Sjoerg     assert(validRegister(num));
953ed444622Sjoerg     return reg[num];
954ed444622Sjoerg   }
955ed444622Sjoerg 
956ed444622Sjoerg   void setRegister(int num, uint64_t value) {
957ed444622Sjoerg     assert(validRegister(num));
958ed444622Sjoerg     reg[num] = value;
959ed444622Sjoerg   }
960ed444622Sjoerg 
961ed444622Sjoerg   uint64_t getIP() const { return reg[REGNO_MIPS_PC]; }
962ed444622Sjoerg 
963ed444622Sjoerg   void setIP(uint64_t value) { reg[REGNO_MIPS_PC] = value; }
964ed444622Sjoerg 
965ed444622Sjoerg   uint64_t getSP() const { return reg[REGNO_MIPS_R29]; }
966ed444622Sjoerg 
967ed444622Sjoerg   void setSP(uint64_t value) { reg[REGNO_MIPS_R29] = value; }
968ed444622Sjoerg 
969ed444622Sjoerg   bool validFloatVectorRegister(int num) const {
970ed444622Sjoerg     return num >= DWARF_MIPS_F0 && num <= DWARF_MIPS_F31;
971ed444622Sjoerg   }
972ed444622Sjoerg 
973ed444622Sjoerg   void copyFloatVectorRegister(int num, uint64_t addr_) {
974ed444622Sjoerg     assert(validFloatVectorRegister(num));
975ed444622Sjoerg     const void *addr = reinterpret_cast<const void *>(addr_);
976ed444622Sjoerg     memcpy(fpreg + (num - REGNO_MIPS_F0), addr, sizeof(fpreg[0]));
977ed444622Sjoerg   }
978ed444622Sjoerg 
979ed444622Sjoerg   __dso_hidden void jumpto() const __dead;
980ed444622Sjoerg 
981ed444622Sjoerg private:
982ed444622Sjoerg   uint32_t reg[REGNO_MIPS_R31 + 1];
983ed444622Sjoerg   uint64_t fpreg[32];
984ed444622Sjoerg };
985ed444622Sjoerg 
986ed444622Sjoerg enum {
987ed444622Sjoerg   DWARF_MIPS64_R1 = 0,
988ed444622Sjoerg   DWARF_MIPS64_R31 = 31,
989ed444622Sjoerg   DWARF_MIPS64_F0 = 32,
990ed444622Sjoerg   DWARF_MIPS64_F31 = 63,
991ed444622Sjoerg 
992ed444622Sjoerg   REGNO_MIPS64_PC = 0,
993ed444622Sjoerg   REGNO_MIPS64_R1 = 0,
994ed444622Sjoerg   REGNO_MIPS64_R29 = 29,
995ed444622Sjoerg   REGNO_MIPS64_R31 = 31,
996ed444622Sjoerg   REGNO_MIPS64_F0 = 33,
997ed444622Sjoerg   REGNO_MIPS64_F31 = 64
998ed444622Sjoerg };
999ed444622Sjoerg 
1000ed444622Sjoerg class Registers_MIPS64 {
1001ed444622Sjoerg public:
1002ed444622Sjoerg   enum {
1003ed444622Sjoerg     LAST_REGISTER = REGNO_MIPS64_F31,
1004ed444622Sjoerg     LAST_RESTORE_REG = REGNO_MIPS64_F31,
1005ed444622Sjoerg     RETURN_OFFSET = 0,
10060282220bSjoerg     RETURN_MASK = 0,
1007ed444622Sjoerg   };
1008ed444622Sjoerg 
1009ed444622Sjoerg   __dso_hidden Registers_MIPS64();
1010ed444622Sjoerg 
1011ed444622Sjoerg   static int dwarf2regno(int num) {
1012ed444622Sjoerg     if (num >= DWARF_MIPS64_R1 && num <= DWARF_MIPS64_R31)
1013ed444622Sjoerg       return REGNO_MIPS64_R1 + (num - DWARF_MIPS64_R1);
1014ed444622Sjoerg     if (num >= DWARF_MIPS64_F0 && num <= DWARF_MIPS64_F31)
1015ed444622Sjoerg       return REGNO_MIPS64_F0 + (num - DWARF_MIPS64_F0);
1016ed444622Sjoerg     return LAST_REGISTER + 1;
1017ed444622Sjoerg   }
1018ed444622Sjoerg 
1019ed444622Sjoerg   bool validRegister(int num) const {
1020ed444622Sjoerg     return num >= REGNO_MIPS64_PC && num <= REGNO_MIPS64_R31;
1021ed444622Sjoerg   }
1022ed444622Sjoerg 
1023ed444622Sjoerg   uint64_t getRegister(int num) const {
1024ed444622Sjoerg     assert(validRegister(num));
1025ed444622Sjoerg     return reg[num];
1026ed444622Sjoerg   }
1027ed444622Sjoerg 
1028ed444622Sjoerg   void setRegister(int num, uint64_t value) {
1029ed444622Sjoerg     assert(validRegister(num));
1030ed444622Sjoerg     reg[num] = value;
1031ed444622Sjoerg   }
1032ed444622Sjoerg 
1033ed444622Sjoerg   uint64_t getIP() const { return reg[REGNO_MIPS64_PC]; }
1034ed444622Sjoerg 
1035ed444622Sjoerg   void setIP(uint64_t value) { reg[REGNO_MIPS64_PC] = value; }
1036ed444622Sjoerg 
1037ed444622Sjoerg   uint64_t getSP() const { return reg[REGNO_MIPS64_R29]; }
1038ed444622Sjoerg 
1039ed444622Sjoerg   void setSP(uint64_t value) { reg[REGNO_MIPS64_R29] = value; }
1040ed444622Sjoerg 
1041ed444622Sjoerg   bool validFloatVectorRegister(int num) const {
1042ed444622Sjoerg     return num >= DWARF_MIPS64_F0 && num <= DWARF_MIPS64_F31;
1043ed444622Sjoerg   }
1044ed444622Sjoerg 
1045ed444622Sjoerg   void copyFloatVectorRegister(int num, uint64_t addr_) {
1046ed444622Sjoerg     assert(validFloatVectorRegister(num));
1047ed444622Sjoerg     const void *addr = reinterpret_cast<const void *>(addr_);
1048ed444622Sjoerg     memcpy(fpreg + (num - REGNO_MIPS64_F0), addr, sizeof(fpreg[0]));
1049ed444622Sjoerg   }
1050ed444622Sjoerg 
1051ed444622Sjoerg   __dso_hidden void jumpto() const __dead;
1052ed444622Sjoerg 
1053ed444622Sjoerg private:
1054ed444622Sjoerg   uint64_t reg[REGNO_MIPS64_R31 + 1];
1055ed444622Sjoerg   uint64_t fpreg[32];
1056ed444622Sjoerg };
1057ed444622Sjoerg 
1058938bf86eSmatt enum {
1059938bf86eSmatt   DWARF_OR1K_R0 = 0,
1060938bf86eSmatt   DWARF_OR1K_SP = 1,
1061938bf86eSmatt   DWARF_OR1K_LR = 9,
1062938bf86eSmatt   DWARF_OR1K_R31 = 31,
1063938bf86eSmatt   DWARF_OR1K_FPCSR = 32,
1064938bf86eSmatt 
1065938bf86eSmatt   REGNO_OR1K_R0 = 0,
1066938bf86eSmatt   REGNO_OR1K_SP = 1,
1067938bf86eSmatt   REGNO_OR1K_LR = 9,
1068938bf86eSmatt   REGNO_OR1K_R31 = 31,
1069938bf86eSmatt   REGNO_OR1K_FPCSR = 32,
1070938bf86eSmatt };
1071938bf86eSmatt 
1072938bf86eSmatt class Registers_or1k {
1073938bf86eSmatt public:
1074938bf86eSmatt   enum {
1075938bf86eSmatt     LAST_REGISTER = REGNO_OR1K_FPCSR,
1076938bf86eSmatt     LAST_RESTORE_REG = REGNO_OR1K_FPCSR,
1077938bf86eSmatt     RETURN_OFFSET = 0,
10780282220bSjoerg     RETURN_MASK = 0,
1079938bf86eSmatt   };
1080938bf86eSmatt 
1081938bf86eSmatt   __dso_hidden Registers_or1k();
1082938bf86eSmatt 
1083938bf86eSmatt   static int dwarf2regno(int num) {
1084938bf86eSmatt     if (num >= DWARF_OR1K_R0 && num <= DWARF_OR1K_R31)
1085938bf86eSmatt       return REGNO_OR1K_R0 + (num - DWARF_OR1K_R0);
1086938bf86eSmatt     if (num == DWARF_OR1K_FPCSR)
1087938bf86eSmatt       return REGNO_OR1K_FPCSR;
1088938bf86eSmatt     return LAST_REGISTER + 1;
1089938bf86eSmatt   }
1090938bf86eSmatt 
1091938bf86eSmatt   bool validRegister(int num) const {
1092938bf86eSmatt     return num >= 0 && num <= LAST_RESTORE_REG;
1093938bf86eSmatt   }
1094938bf86eSmatt 
1095938bf86eSmatt   uint64_t getRegister(int num) const {
1096938bf86eSmatt     assert(validRegister(num));
1097938bf86eSmatt     return reg[num];
1098938bf86eSmatt   }
1099938bf86eSmatt 
1100938bf86eSmatt   void setRegister(int num, uint64_t value) {
1101938bf86eSmatt     assert(validRegister(num));
1102938bf86eSmatt     reg[num] = value;
1103938bf86eSmatt   }
1104938bf86eSmatt 
1105938bf86eSmatt   uint64_t getIP() const { return reg[REGNO_OR1K_LR]; }
1106938bf86eSmatt 
1107938bf86eSmatt   void setIP(uint64_t value) { reg[REGNO_OR1K_LR] = value; }
1108938bf86eSmatt 
1109938bf86eSmatt   uint64_t getSP() const { return reg[REGNO_OR1K_SP]; }
1110938bf86eSmatt 
1111938bf86eSmatt   void setSP(uint64_t value) { reg[REGNO_OR1K_SP] = value; }
1112938bf86eSmatt 
1113938bf86eSmatt   bool validFloatVectorRegister(int num) const {
1114938bf86eSmatt     return false;
1115938bf86eSmatt   }
1116938bf86eSmatt 
1117938bf86eSmatt   void copyFloatVectorRegister(int num, uint64_t addr_) {
1118938bf86eSmatt   }
1119938bf86eSmatt 
1120938bf86eSmatt   __dso_hidden void jumpto() const __dead;
1121938bf86eSmatt 
1122938bf86eSmatt private:
1123938bf86eSmatt   uint32_t reg[REGNO_OR1K_FPCSR + 1];
1124938bf86eSmatt };
1125938bf86eSmatt 
1126a6ecde39Sjoerg #if __i386__
1127a6ecde39Sjoerg typedef Registers_x86 NativeUnwindRegisters;
1128a6ecde39Sjoerg #elif __x86_64__
1129a6ecde39Sjoerg typedef Registers_x86_64 NativeUnwindRegisters;
1130a6ecde39Sjoerg #elif __powerpc__
1131a6ecde39Sjoerg typedef Registers_ppc32 NativeUnwindRegisters;
1132aa37019dSmatt #elif __aarch64__
1133aa37019dSmatt typedef Registers_aarch64 NativeUnwindRegisters;
1134bdd3372bSjoerg #elif __arm__
1135a6ecde39Sjoerg typedef Registers_arm32 NativeUnwindRegisters;
1136a6ecde39Sjoerg #elif __vax__
1137a6ecde39Sjoerg typedef Registers_vax NativeUnwindRegisters;
1138a6ecde39Sjoerg #elif __m68k__
1139a6ecde39Sjoerg typedef Registers_M68K NativeUnwindRegisters;
1140ed444622Sjoerg #elif __mips_n64 || __mips_n32
1141ed444622Sjoerg typedef Registers_MIPS64 NativeUnwindRegisters;
1142ed444622Sjoerg #elif __mips__
1143ed444622Sjoerg typedef Registers_MIPS NativeUnwindRegisters;
1144a6ecde39Sjoerg #elif __sh3__
1145a6ecde39Sjoerg typedef Registers_SH3 NativeUnwindRegisters;
1146f5cf7457Sjoerg #elif __sparc64__
1147f5cf7457Sjoerg typedef Registers_SPARC64 NativeUnwindRegisters;
1148f5cf7457Sjoerg #elif __sparc__
1149f5cf7457Sjoerg typedef Registers_SPARC NativeUnwindRegisters;
1150e3d4269aSjoerg #elif __alpha__
1151e3d4269aSjoerg typedef Registers_Alpha NativeUnwindRegisters;
1152a78e9b23Sjoerg #elif __hppa__
1153a78e9b23Sjoerg typedef Registers_HPPA NativeUnwindRegisters;
1154938bf86eSmatt #elif __or1k__
1155938bf86eSmatt typedef Registers_or1k NativeUnwindRegisters;
1156a6ecde39Sjoerg #endif
1157aa0b96d0Sjoerg } // namespace _Unwind
1158aa0b96d0Sjoerg 
1159aa0b96d0Sjoerg #endif // __REGISTERS_HPP__
1160