1207340Sjkim//===----------------------------- Registers.hpp --------------------------===//
2207340Sjkim//
3207340Sjkim//                     The LLVM Compiler Infrastructure
4207340Sjkim//
5207340Sjkim// This file is dual licensed under the MIT and the University of Illinois Open
6207340Sjkim// Source Licenses. See LICENSE.TXT for details.
7207340Sjkim//
8217365Sjkim//
9217365Sjkim//  Models register sets for supported processors.
10207340Sjkim//
11207340Sjkim//===----------------------------------------------------------------------===//
12217365Sjkim#ifndef __REGISTERS_HPP__
13217365Sjkim#define __REGISTERS_HPP__
14217365Sjkim
15217365Sjkim#include <sys/endian.h>
16217365Sjkim#include <cassert>
17217365Sjkim#include <cstdint>
18217365Sjkim
19217365Sjkimnamespace _Unwind {
20217365Sjkim
21217365Sjkimenum {
22217365Sjkim  REGNO_X86_EAX = 0,
23217365Sjkim  REGNO_X86_ECX = 1,
24217365Sjkim  REGNO_X86_EDX = 2,
25217365Sjkim  REGNO_X86_EBX = 3,
26207340Sjkim  REGNO_X86_ESP = 4,
27217365Sjkim  REGNO_X86_EBP = 5,
28217365Sjkim  REGNO_X86_ESI = 6,
29217365Sjkim  REGNO_X86_EDI = 7,
30207340Sjkim  REGNO_X86_EIP = 8,
31217365Sjkim};
32217365Sjkim
33217365Sjkimclass Registers_x86 {
34217365Sjkimpublic:
35217365Sjkim  enum {
36217365Sjkim    LAST_REGISTER = REGNO_X86_EIP,
37217365Sjkim    LAST_RESTORE_REG = REGNO_X86_EIP,
38217365Sjkim    RETURN_OFFSET = 0,
39217365Sjkim    RETURN_MASK = 0,
40217365Sjkim  };
41217365Sjkim
42217365Sjkim  __dso_hidden Registers_x86();
43217365Sjkim
44207340Sjkim  static int dwarf2regno(int num) { return num; }
45207340Sjkim
46207344Sjkim  bool validRegister(int num) const {
47207340Sjkim    return num >= REGNO_X86_EAX && num <= REGNO_X86_EDI;
48207340Sjkim  }
49207340Sjkim
50207340Sjkim  uint32_t getRegister(int num) const {
51207340Sjkim    assert(validRegister(num));
52207340Sjkim    return reg[num];
53207340Sjkim  }
54207340Sjkim
55207340Sjkim  void setRegister(int num, uint32_t value) {
56207340Sjkim    assert(validRegister(num));
57207340Sjkim    reg[num] = value;
58207340Sjkim  }
59207340Sjkim
60207340Sjkim  uint32_t getIP() const { return reg[REGNO_X86_EIP]; }
61207340Sjkim
62207340Sjkim  void setIP(uint32_t value) { reg[REGNO_X86_EIP] = value; }
63207340Sjkim
64207340Sjkim  uint32_t getSP() const { return reg[REGNO_X86_ESP]; }
65207340Sjkim
66207340Sjkim  void setSP(uint32_t value) { reg[REGNO_X86_ESP] = value; }
67207340Sjkim
68207340Sjkim  bool validFloatVectorRegister(int num) const { return false; }
69207340Sjkim
70207340Sjkim  void copyFloatVectorRegister(int num, uint32_t addr) {
71207340Sjkim  }
72207340Sjkim
73207340Sjkim  __dso_hidden void jumpto() const __dead;
74207340Sjkim
75207340Sjkimprivate:
76207340Sjkim  uint32_t reg[REGNO_X86_EIP + 1];
77207340Sjkim};
78207340Sjkim
79207340Sjkimenum {
80207340Sjkim  REGNO_X86_64_RAX = 0,
81207340Sjkim  REGNO_X86_64_RDX = 1,
82207340Sjkim  REGNO_X86_64_RCX = 2,
83207340Sjkim  REGNO_X86_64_RBX = 3,
84207340Sjkim  REGNO_X86_64_RSI = 4,
85207340Sjkim  REGNO_X86_64_RDI = 5,
86207340Sjkim  REGNO_X86_64_RBP = 6,
87207340Sjkim  REGNO_X86_64_RSP = 7,
88207340Sjkim  REGNO_X86_64_R8 = 8,
89207340Sjkim  REGNO_X86_64_R9 = 9,
90207340Sjkim  REGNO_X86_64_R10 = 10,
91207340Sjkim  REGNO_X86_64_R11 = 11,
92207340Sjkim  REGNO_X86_64_R12 = 12,
93207340Sjkim  REGNO_X86_64_R13 = 13,
94207340Sjkim  REGNO_X86_64_R14 = 14,
95207340Sjkim  REGNO_X86_64_R15 = 15,
96207340Sjkim  REGNO_X86_64_RIP = 16,
97207340Sjkim};
98207340Sjkim
99207340Sjkimclass Registers_x86_64 {
100207340Sjkimpublic:
101207340Sjkim  enum {
102207340Sjkim    LAST_REGISTER = REGNO_X86_64_RIP,
103207340Sjkim    LAST_RESTORE_REG = REGNO_X86_64_RIP,
104207340Sjkim    RETURN_OFFSET = 0,
105207340Sjkim    RETURN_MASK = 0,
106207340Sjkim  };
107207340Sjkim
108207340Sjkim  __dso_hidden Registers_x86_64();
109207340Sjkim
110207340Sjkim  static int dwarf2regno(int num) { return num; }
111207340Sjkim
112207340Sjkim  bool validRegister(int num) const {
113207340Sjkim    return num >= REGNO_X86_64_RAX && num <= REGNO_X86_64_R15;
114207340Sjkim  }
115207340Sjkim
116207340Sjkim  uint64_t getRegister(int num) const {
117207340Sjkim    assert(validRegister(num));
118207340Sjkim    return reg[num];
119207340Sjkim  }
120207340Sjkim
121207340Sjkim  void setRegister(int num, uint64_t value) {
122207340Sjkim    assert(validRegister(num));
123207340Sjkim    reg[num] = value;
124207340Sjkim  }
125207340Sjkim
126207340Sjkim  uint64_t getIP() const { return reg[REGNO_X86_64_RIP]; }
127207340Sjkim
128207340Sjkim  void setIP(uint64_t value) { reg[REGNO_X86_64_RIP] = value; }
129207340Sjkim
130207340Sjkim  uint64_t getSP() const { return reg[REGNO_X86_64_RSP]; }
131207340Sjkim
132207340Sjkim  void setSP(uint64_t value) { reg[REGNO_X86_64_RSP] = value; }
133207340Sjkim
134207340Sjkim  bool validFloatVectorRegister(int num) const { return false; }
135207340Sjkim
136207340Sjkim  void copyFloatVectorRegister(int num, uint64_t addr) {
137207340Sjkim  }
138207340Sjkim
139207340Sjkim  __dso_hidden void jumpto() const __dead;
140207340Sjkim
141207340Sjkimprivate:
142207340Sjkim  uint64_t reg[REGNO_X86_64_RIP + 1];
143207340Sjkim};
144207340Sjkim
145207340Sjkimenum {
146207340Sjkim  DWARF_PPC32_R0 = 0,
147207340Sjkim  DWARF_PPC32_R31 = 31,
148207340Sjkim  DWARF_PPC32_F0 = 32,
149207340Sjkim  DWARF_PPC32_F31 = 63,
150207340Sjkim  DWARF_PPC32_LR = 65,
151207340Sjkim  DWARF_PPC32_CTR = 66,
152207340Sjkim  DWARF_PPC32_CR = 70,
153207340Sjkim  DWARF_PPC32_XER = 76,
154207340Sjkim  DWARF_PPC32_V0 = 77,
155207340Sjkim  DWARF_PPC32_SIGRETURN = 99,
156207340Sjkim  DWARF_PPC32_V31 = 108,
157207340Sjkim
158207340Sjkim  REGNO_PPC32_R0 = 0,
159207340Sjkim  REGNO_PPC32_R1 = 1,
160207340Sjkim  REGNO_PPC32_R31 = 31,
161207340Sjkim  REGNO_PPC32_LR = 32,
162207340Sjkim  REGNO_PPC32_CR = 33,
163207340Sjkim  REGNO_PPC32_SRR0 = 34,
164207340Sjkim
165207340Sjkim  REGNO_PPC32_F0 = REGNO_PPC32_SRR0 + 1,
166207340Sjkim  REGNO_PPC32_F31 = REGNO_PPC32_F0 + 31,
167207340Sjkim  REGNO_PPC32_V0 = REGNO_PPC32_F31 + 1,
168207340Sjkim  REGNO_PPC32_V31 = REGNO_PPC32_V0 + 31,
169207340Sjkim
170207340Sjkim  REGNO_PPC32_CTR = REGNO_PPC32_V31 + 1,
171207340Sjkim  REGNO_PPC32_XER = REGNO_PPC32_CTR + 1,
172207340Sjkim  REGNO_PPC32_SIGRETURN = REGNO_PPC32_XER + 1
173207340Sjkim};
174207340Sjkim
175207340Sjkimclass Registers_ppc32 {
176207340Sjkimpublic:
177207340Sjkim  enum {
178207340Sjkim    LAST_REGISTER = REGNO_PPC32_SIGRETURN,
179207340Sjkim    LAST_RESTORE_REG = REGNO_PPC32_SIGRETURN,
180207340Sjkim    RETURN_OFFSET = 0,
181207340Sjkim    RETURN_MASK = 0,
182207340Sjkim  };
183207340Sjkim
184207340Sjkim  __dso_hidden Registers_ppc32();
185207340Sjkim
186207340Sjkim  static int dwarf2regno(int num) {
187207340Sjkim    if (num >= DWARF_PPC32_R0 && num <= DWARF_PPC32_R31)
188207340Sjkim      return REGNO_PPC32_R0 + (num - DWARF_PPC32_R0);
189207340Sjkim    if (num >= DWARF_PPC32_F0 && num <= DWARF_PPC32_F31)
190207340Sjkim      return REGNO_PPC32_F0 + (num - DWARF_PPC32_F0);
191207340Sjkim    if (num >= DWARF_PPC32_V0 && num <= DWARF_PPC32_V31)
192207340Sjkim      return REGNO_PPC32_V0 + (num - DWARF_PPC32_V0);
193207340Sjkim    switch (num) {
194207340Sjkim    case DWARF_PPC32_LR:
195207340Sjkim      return REGNO_PPC32_LR;
196207340Sjkim    case DWARF_PPC32_CR:
197207340Sjkim      return REGNO_PPC32_CR;
198207340Sjkim    case DWARF_PPC32_CTR:
199207340Sjkim      return REGNO_PPC32_CTR;
200207340Sjkim    case DWARF_PPC32_XER:
201207340Sjkim      return REGNO_PPC32_XER;
202207340Sjkim    case DWARF_PPC32_SIGRETURN:
203207340Sjkim      return REGNO_PPC32_SIGRETURN;
204207340Sjkim    default:
205207340Sjkim      return LAST_REGISTER + 1;
206207340Sjkim    }
207207340Sjkim  }
208207340Sjkim
209207340Sjkim  bool validRegister(int num) const {
210207340Sjkim    return (num >= 0 && num <= REGNO_PPC32_SRR0) ||
211207340Sjkim	(num >= REGNO_PPC32_CTR && num <= REGNO_PPC32_SIGRETURN);
212207340Sjkim  }
213207340Sjkim
214207340Sjkim  uint64_t getRegister(int num) const {
215207340Sjkim    assert(validRegister(num));
216207340Sjkim    switch (num) {
217207340Sjkim    case REGNO_PPC32_CTR:
218207340Sjkim      return ctr_reg;
219207340Sjkim    case REGNO_PPC32_XER:
220207340Sjkim      return xer_reg;
221207340Sjkim    case REGNO_PPC32_SIGRETURN:
222207340Sjkim      return sigreturn_reg;
223207340Sjkim    default:
224207340Sjkim      return reg[num];
225213806Sjkim    }
226207340Sjkim  }
227207340Sjkim
228207340Sjkim  void setRegister(int num, uint64_t value) {
229207340Sjkim    assert(validRegister(num));
230207340Sjkim    switch (num) {
231207340Sjkim    case REGNO_PPC32_CTR:
232207340Sjkim      ctr_reg = value;
233207340Sjkim      break;
234207340Sjkim    case REGNO_PPC32_XER:
235207340Sjkim      xer_reg = value;
236207340Sjkim      break;
237207340Sjkim    case REGNO_PPC32_SIGRETURN:
238207340Sjkim      sigreturn_reg = value;
239207340Sjkim      break;
240207340Sjkim    default:
241207340Sjkim      reg[num] = value;
242207340Sjkim    }
243207340Sjkim  }
244207340Sjkim
245207340Sjkim  uint64_t getIP() const { return reg[REGNO_PPC32_SRR0]; }
246207340Sjkim
247207340Sjkim  void setIP(uint64_t value) { reg[REGNO_PPC32_SRR0] = value; }
248207340Sjkim
249207340Sjkim  uint64_t getSP() const { return reg[REGNO_PPC32_R1]; }
250207340Sjkim
251207340Sjkim  void setSP(uint64_t value) { reg[REGNO_PPC32_R1] = value; }
252207340Sjkim
253207340Sjkim  bool validFloatVectorRegister(int num) const {
254207340Sjkim    return (num >= REGNO_PPC32_F0 && num <= REGNO_PPC32_F31) ||
255207340Sjkim           (num >= REGNO_PPC32_V0 && num <= REGNO_PPC32_V31);
256207340Sjkim  }
257207340Sjkim
258207340Sjkim  void copyFloatVectorRegister(int num, uint64_t addr_) {
259207340Sjkim    const void *addr = reinterpret_cast<const void *>(addr_);
260207340Sjkim    if (num >= REGNO_PPC32_F0 && num <= REGNO_PPC32_F31)
261207340Sjkim      memcpy(fpreg + (num - REGNO_PPC32_F0), addr, sizeof(fpreg[0]));
262207340Sjkim    else
263207340Sjkim      memcpy(vecreg + (num - REGNO_PPC32_V0), addr, sizeof(vecreg[0]));
264207340Sjkim  }
265207340Sjkim
266207340Sjkim  __dso_hidden void jumpto() const __dead;
267207340Sjkim
268207340Sjkimprivate:
269207340Sjkim  struct vecreg_t {
270207340Sjkim    uint64_t low, high;
271207340Sjkim  };
272207340Sjkim  uint32_t reg[REGNO_PPC32_SRR0 + 1];
273207340Sjkim  uint32_t dummy;
274207340Sjkim  uint64_t fpreg[32];
275207340Sjkim  vecreg_t vecreg[64];
276207340Sjkim  uint32_t ctr_reg;
277207340Sjkim  uint32_t xer_reg;
278207340Sjkim  uint32_t sigreturn_reg;
279207340Sjkim};
280207340Sjkim
281207340Sjkimenum {
282207340Sjkim  DWARF_AARCH64_X0 = 0,
283207340Sjkim  DWARF_AARCH64_X30 = 30,
284207340Sjkim  DWARF_AARCH64_SP = 31,
285207340Sjkim  DWARF_AARCH64_V0 = 64,
286207340Sjkim  DWARF_AARCH64_V31 = 95,
287207340Sjkim  DWARF_AARCH64_SIGRETURN = 96,
288207340Sjkim
289207340Sjkim  REGNO_AARCH64_X0 = 0,
290207340Sjkim  REGNO_AARCH64_X30 = 30,
291207340Sjkim  REGNO_AARCH64_SP = 31,
292207340Sjkim  REGNO_AARCH64_V0 = 32,
293207340Sjkim  REGNO_AARCH64_V31 = 63,
294207340Sjkim  REGNO_AARCH64_SIGRETURN = 64,
295207340Sjkim};
296207340Sjkim
297207340Sjkimclass Registers_aarch64 {
298207340Sjkimpublic:
299207340Sjkim  enum {
300207340Sjkim    LAST_RESTORE_REG = REGNO_AARCH64_SIGRETURN,
301207340Sjkim    LAST_REGISTER = REGNO_AARCH64_SIGRETURN,
302207340Sjkim    RETURN_OFFSET = 0,
303207340Sjkim    RETURN_MASK = 0,
304207340Sjkim  };
305207340Sjkim
306207340Sjkim  __dso_hidden Registers_aarch64();
307207340Sjkim
308207340Sjkim  static int dwarf2regno(int num) {
309207340Sjkim    if (num >= DWARF_AARCH64_X0 && num <= DWARF_AARCH64_X30)
310207340Sjkim      return REGNO_AARCH64_X0 + (num - DWARF_AARCH64_X0);
311207340Sjkim    if (num == DWARF_AARCH64_SP)
312207340Sjkim      return REGNO_AARCH64_SP;
313207340Sjkim    if (num >= DWARF_AARCH64_V0 && num <= DWARF_AARCH64_V31)
314207340Sjkim      return REGNO_AARCH64_V0 + (num - DWARF_AARCH64_V0);
315207340Sjkim    if (num == DWARF_AARCH64_SIGRETURN)
316207340Sjkim      return REGNO_AARCH64_SIGRETURN;
317207340Sjkim    return LAST_REGISTER + 1;
318207340Sjkim  }
319207340Sjkim
320207340Sjkim  bool validRegister(int num) const {
321207340Sjkim    return (num >= DWARF_AARCH64_X0 && num <= DWARF_AARCH64_SP) ||
322207340Sjkim	num == DWARF_AARCH64_SIGRETURN;
323207340Sjkim  }
324207340Sjkim
325207340Sjkim  uint64_t getRegister(int num) const {
326207340Sjkim    assert(validRegister(num));
327207340Sjkim    if (num == REGNO_AARCH64_SIGRETURN)
328207340Sjkim      return sigreturn_reg;
329207340Sjkim    return reg[num];
330207340Sjkim  }
331207340Sjkim
332207340Sjkim  void setRegister(int num, uint64_t value) {
333207340Sjkim    assert(validRegister(num));
334207340Sjkim    if (num == REGNO_AARCH64_SIGRETURN)
335207340Sjkim      sigreturn_reg = value;
336207340Sjkim    else
337207340Sjkim      reg[num] = value;
338207340Sjkim  }
339207340Sjkim
340207340Sjkim  uint64_t getIP() const { return reg[REGNO_AARCH64_X30]; }
341207340Sjkim
342207340Sjkim  void setIP(uint64_t value) { reg[REGNO_AARCH64_X30] = value; }
343207340Sjkim
344207340Sjkim  uint64_t getSP() const { return reg[REGNO_AARCH64_SP]; }
345207340Sjkim
346207340Sjkim  void setSP(uint64_t value) { reg[REGNO_AARCH64_SP] = value; }
347207340Sjkim
348207340Sjkim  bool validFloatVectorRegister(int num) const {
349207340Sjkim    return (num >= REGNO_AARCH64_V0 && num <= REGNO_AARCH64_V31);
350207340Sjkim  }
351207340Sjkim
352207340Sjkim  void copyFloatVectorRegister(int num, uint64_t addr_) {
353207340Sjkim    const void *addr = reinterpret_cast<const void *>(addr_);
354207340Sjkim    memcpy(vecreg + (num - REGNO_AARCH64_V0), addr, 16);
355207340Sjkim  }
356207340Sjkim
357207340Sjkim  __dso_hidden void jumpto() const __dead;
358207340Sjkim
359207340Sjkimprivate:
360207340Sjkim  uint64_t reg[REGNO_AARCH64_SP + 1];
361207340Sjkim  uint64_t vecreg[64];
362207340Sjkim  uint64_t sigreturn_reg;
363207340Sjkim};
364207340Sjkim
365207340Sjkimenum {
366207340Sjkim  DWARF_ARM32_R0 = 0,
367207340Sjkim  DWARF_ARM32_R15 = 15,
368207340Sjkim  DWARF_ARM32_SPSR = 128,
369207340Sjkim  DWARF_ARM32_S0 = 64,
370207340Sjkim  DWARF_ARM32_S31 = 95,
371207340Sjkim  DWARF_ARM32_D0 = 256,
372207340Sjkim  DWARF_ARM32_D31 = 287,
373207340Sjkim  REGNO_ARM32_R0 = 0,
374207340Sjkim  REGNO_ARM32_SP = 13,
375207340Sjkim  REGNO_ARM32_R15 = 15,
376207340Sjkim  REGNO_ARM32_SPSR = 16,
377207340Sjkim  REGNO_ARM32_D0 = 17,
378207340Sjkim  REGNO_ARM32_D15 = 32,
379207340Sjkim  REGNO_ARM32_D31 = 48,
380207340Sjkim  REGNO_ARM32_S0 = 49,
381207340Sjkim  REGNO_ARM32_S31 = 80,
382207340Sjkim};
383207340Sjkim
384207340Sjkim#define	FLAGS_VFPV2_USED		0x1
385207340Sjkim#define	FLAGS_VFPV3_USED		0x2
386207340Sjkim#define	FLAGS_LEGACY_VFPV2_REGNO	0x4
387207340Sjkim#define	FLAGS_EXTENDED_VFPV2_REGNO	0x8
388207340Sjkim
389207340Sjkimclass Registers_arm32 {
390207340Sjkimpublic:
391207340Sjkim  enum {
392207340Sjkim    LAST_REGISTER = REGNO_ARM32_S31,
393207340Sjkim    LAST_RESTORE_REG = REGNO_ARM32_S31,
394207340Sjkim    RETURN_OFFSET = 0,
395207340Sjkim    RETURN_MASK = 0,
396207340Sjkim  };
397207340Sjkim
398207340Sjkim  __dso_hidden Registers_arm32();
399207340Sjkim
400207340Sjkim  static int dwarf2regno(int num) {
401207340Sjkim    if (num >= DWARF_ARM32_R0 && num <= DWARF_ARM32_R15)
402207340Sjkim      return REGNO_ARM32_R0 + (num - DWARF_ARM32_R0);
403207340Sjkim    if (num == DWARF_ARM32_SPSR)
404207340Sjkim      return REGNO_ARM32_SPSR;
405207340Sjkim    if (num >= DWARF_ARM32_D0 && num <= DWARF_ARM32_D31)
406213806Sjkim      return REGNO_ARM32_D0 + (num - DWARF_ARM32_D0);
407207340Sjkim    if (num >= DWARF_ARM32_S0 && num <= DWARF_ARM32_S31)
408207340Sjkim      return REGNO_ARM32_S0 + (num - DWARF_ARM32_S0);
409207340Sjkim    return LAST_REGISTER + 1;
410207340Sjkim  }
411207340Sjkim
412207340Sjkim  bool validRegister(int num) const {
413207340Sjkim    return num >= 0 && num <= REGNO_ARM32_SPSR;
414207340Sjkim  }
415207340Sjkim
416207340Sjkim  uint64_t getRegister(int num) const {
417207340Sjkim    assert(validRegister(num));
418207340Sjkim    return reg[num];
419207340Sjkim  }
420207340Sjkim
421207340Sjkim  void setRegister(int num, uint64_t value) {
422207340Sjkim    assert(validRegister(num));
423207340Sjkim    reg[num] = value;
424207340Sjkim  }
425207340Sjkim
426207340Sjkim  uint64_t getIP() const { return reg[REGNO_ARM32_R15]; }
427207340Sjkim
428207340Sjkim  void setIP(uint64_t value) { reg[REGNO_ARM32_R15] = value; }
429207340Sjkim
430207340Sjkim  uint64_t getSP() const { return reg[REGNO_ARM32_SP]; }
431207340Sjkim
432207340Sjkim  void setSP(uint64_t value) { reg[REGNO_ARM32_SP] = value; }
433207340Sjkim
434207340Sjkim  bool validFloatVectorRegister(int num) const {
435207340Sjkim    return (num >= REGNO_ARM32_D0 && num <= REGNO_ARM32_S31);
436207340Sjkim  }
437207340Sjkim
438207340Sjkim  void copyFloatVectorRegister(int num, uint64_t addr_) {
439207340Sjkim    assert(validFloatVectorRegister(num));
440207340Sjkim    const void *addr = reinterpret_cast<const void *>(addr_);
441207340Sjkim    if (num >= REGNO_ARM32_S0 && num <= REGNO_ARM32_S31) {
442207340Sjkim      /*
443207340Sjkim       * XXX
444207340Sjkim       * There are two numbering schemes for VFPv2 registers: s0-s31
445207340Sjkim       * (used by GCC) and d0-d15 (used by LLVM). We won't support both
446207340Sjkim       * schemes simultaneously in a same frame.
447207340Sjkim       */
448207340Sjkim      assert((flags & FLAGS_EXTENDED_VFPV2_REGNO) == 0);
449207340Sjkim      flags |= FLAGS_LEGACY_VFPV2_REGNO;
450207340Sjkim      if ((flags & FLAGS_VFPV2_USED) == 0) {
451207340Sjkim        lazyVFPv2();
452207340Sjkim        flags |= FLAGS_VFPV2_USED;
453207340Sjkim      }
454207340Sjkim      /*
455207340Sjkim       * Emulate single precision register as half of the
456207340Sjkim       * corresponding double register.
457207340Sjkim       */
458207340Sjkim      int dnum = (num - REGNO_ARM32_S0) / 2;
459207340Sjkim      int part = (num - REGNO_ARM32_S0) % 2;
460207340Sjkim#if _BYTE_ORDER == _BIG_ENDIAN
461207340Sjkim      part = 1 - part;
462207340Sjkim#endif
463207340Sjkim      memcpy((uint8_t *)(fpreg + dnum) + part * sizeof(fpreg[0]) / 2,
464207340Sjkim        addr, sizeof(fpreg[0]) / 2);
465207340Sjkim    } else {
466207340Sjkim      if (num <= REGNO_ARM32_D15) {
467207340Sjkim	/*
468207340Sjkim	 * XXX
469207340Sjkim	 * See XXX comment above.
470207340Sjkim	 */
471207340Sjkim        assert((flags & FLAGS_LEGACY_VFPV2_REGNO) == 0);
472207340Sjkim        flags |= FLAGS_EXTENDED_VFPV2_REGNO;
473207340Sjkim        if ((flags & FLAGS_VFPV2_USED) == 0) {
474207340Sjkim          lazyVFPv2();
475207340Sjkim          flags |= FLAGS_VFPV2_USED;
476207340Sjkim        }
477207340Sjkim      } else {
478207340Sjkim        if ((flags & FLAGS_VFPV3_USED) == 0) {
479207340Sjkim          lazyVFPv3();
480207340Sjkim          flags |= FLAGS_VFPV3_USED;
481207340Sjkim        }
482207340Sjkim      }
483207340Sjkim      memcpy(fpreg + (num - REGNO_ARM32_D0), addr, sizeof(fpreg[0]));
484207340Sjkim    }
485207340Sjkim  }
486207340Sjkim
487207340Sjkim  __dso_hidden void lazyVFPv2();
488207340Sjkim  __dso_hidden void lazyVFPv3();
489207340Sjkim  __dso_hidden void jumpto() const __dead;
490207340Sjkim
491207340Sjkimprivate:
492207340Sjkim  uint32_t reg[REGNO_ARM32_SPSR + 1];
493207340Sjkim  uint32_t flags;
494207340Sjkim  uint64_t fpreg[32];
495207340Sjkim};
496207340Sjkim
497207340Sjkim#undef	FLAGS_VFPV2_USED
498207340Sjkim#undef	FLAGS_VFPV3_USED
499207340Sjkim#undef	FLAGS_LEGACY_VFPV2_REGNO
500207340Sjkim#undef	FLAGS_EXTENDED_VFPV2_REGNO
501207340Sjkim
502207340Sjkimenum {
503207340Sjkim  DWARF_VAX_R0 = 0,
504207340Sjkim  DWARF_VAX_R15 = 15,
505207340Sjkim  DWARF_VAX_PSW = 16,
506207340Sjkim
507207340Sjkim  REGNO_VAX_R0 = 0,
508207340Sjkim  REGNO_VAX_R14 = 14,
509207340Sjkim  REGNO_VAX_R15 = 15,
510207340Sjkim  REGNO_VAX_PSW = 16,
511207340Sjkim};
512207340Sjkim
513207340Sjkimclass Registers_vax {
514207340Sjkimpublic:
515207340Sjkim  enum {
516207340Sjkim    LAST_REGISTER = REGNO_VAX_PSW,
517207340Sjkim    LAST_RESTORE_REG = REGNO_VAX_PSW,
518207340Sjkim    RETURN_OFFSET = 0,
519207340Sjkim    RETURN_MASK = 0,
520207340Sjkim  };
521207340Sjkim
522207340Sjkim  __dso_hidden Registers_vax();
523207340Sjkim
524207340Sjkim  static int dwarf2regno(int num) {
525207340Sjkim    if (num >= DWARF_VAX_R0 && num <= DWARF_VAX_R15)
526207340Sjkim      return REGNO_VAX_R0 + (num - DWARF_VAX_R0);
527207340Sjkim    if (num == DWARF_VAX_PSW)
528207340Sjkim      return REGNO_VAX_PSW;
529207340Sjkim    return LAST_REGISTER + 1;
530207340Sjkim  }
531207340Sjkim
532207340Sjkim  bool validRegister(int num) const {
533207340Sjkim    return num >= 0 && num <= LAST_RESTORE_REG;
534207340Sjkim  }
535207340Sjkim
536207340Sjkim  uint64_t getRegister(int num) const {
537207340Sjkim    assert(validRegister(num));
538207340Sjkim    return reg[num];
539207340Sjkim  }
540207340Sjkim
541207340Sjkim  void setRegister(int num, uint64_t value) {
542207340Sjkim    assert(validRegister(num));
543207340Sjkim    reg[num] = value;
544207340Sjkim  }
545207340Sjkim
546207340Sjkim  uint64_t getIP() const { return reg[REGNO_VAX_R15]; }
547207340Sjkim
548207340Sjkim  void setIP(uint64_t value) { reg[REGNO_VAX_R15] = value; }
549207340Sjkim
550207340Sjkim  uint64_t getSP() const { return reg[REGNO_VAX_R14]; }
551207340Sjkim
552207340Sjkim  void setSP(uint64_t value) { reg[REGNO_VAX_R14] = value; }
553207340Sjkim
554207340Sjkim  bool validFloatVectorRegister(int num) const {
555207340Sjkim    return false;
556207340Sjkim  }
557207340Sjkim
558207340Sjkim  void copyFloatVectorRegister(int num, uint64_t addr_) {
559207340Sjkim  }
560207340Sjkim
561207340Sjkim  __dso_hidden void jumpto() const __dead;
562207340Sjkim
563207340Sjkimprivate:
564207340Sjkim  uint32_t reg[REGNO_VAX_PSW + 1];
565207340Sjkim};
566207340Sjkim
567207340Sjkimenum {
568207340Sjkim  DWARF_M68K_A0 = 0,
569213806Sjkim  DWARF_M68K_A7 = 7,
570207340Sjkim  DWARF_M68K_D0 = 8,
571207340Sjkim  DWARF_M68K_D7 = 15,
572207340Sjkim  DWARF_M68K_FP0 = 16,
573207340Sjkim  DWARF_M68K_FP7 = 23,
574  DWARF_M68K_PC = 24,
575  // DWARF pseudo-register that is an alternate that may be used
576  // for the return address.
577  DWARF_M68K_ALT_PC = 25,
578
579  REGNO_M68K_A0 = 0,
580  REGNO_M68K_A7 = 7,
581  REGNO_M68K_D0 = 8,
582  REGNO_M68K_D7 = 15,
583  REGNO_M68K_PC = 16,
584  REGNO_M68K_FP0 = 17,
585  REGNO_M68K_FP7 = 24,
586};
587
588class Registers_M68K {
589public:
590  enum {
591    LAST_REGISTER = REGNO_M68K_FP7,
592    LAST_RESTORE_REG = REGNO_M68K_FP7,
593    RETURN_OFFSET = 0,
594    RETURN_MASK = 0,
595  };
596
597  __dso_hidden Registers_M68K();
598
599  static int dwarf2regno(int num) {
600    if (num >= DWARF_M68K_A0 && num <= DWARF_M68K_A7)
601      return REGNO_M68K_A0 + (num - DWARF_M68K_A0);
602    if (num >= DWARF_M68K_D0 && num <= DWARF_M68K_D7)
603      return REGNO_M68K_D0 + (num - DWARF_M68K_D0);
604    if (num >= DWARF_M68K_FP0 && num <= DWARF_M68K_FP7)
605      return REGNO_M68K_FP0 + (num - DWARF_M68K_FP0);
606    if (num == DWARF_M68K_PC || num == DWARF_M68K_ALT_PC)
607      return REGNO_M68K_PC;
608    return LAST_REGISTER + 1;
609  }
610
611  bool validRegister(int num) const {
612    return num >= 0 && num <= REGNO_M68K_PC;
613  }
614
615  uint64_t getRegister(int num) const {
616    assert(validRegister(num));
617    return reg[num];
618  }
619
620  void setRegister(int num, uint64_t value) {
621    assert(validRegister(num));
622    reg[num] = value;
623  }
624
625  uint64_t getIP() const { return reg[REGNO_M68K_PC]; }
626
627  void setIP(uint64_t value) { reg[REGNO_M68K_PC] = value; }
628
629  uint64_t getSP() const { return reg[REGNO_M68K_A7]; }
630
631  void setSP(uint64_t value) { reg[REGNO_M68K_A7] = value; }
632
633  bool validFloatVectorRegister(int num) const {
634    return num >= REGNO_M68K_FP0 && num <= REGNO_M68K_FP7;
635  }
636
637  void copyFloatVectorRegister(int num, uint64_t addr_) {
638    assert(validFloatVectorRegister(num));
639    const void *addr = reinterpret_cast<const void *>(addr_);
640    memcpy(fpreg + (num - REGNO_M68K_FP0), addr, sizeof(fpreg[0]));
641  }
642
643  __dso_hidden void jumpto() const __dead;
644
645private:
646  typedef uint32_t fpreg_t[3];
647
648  uint32_t reg[REGNO_M68K_PC + 1];
649  uint32_t dummy;
650  fpreg_t fpreg[8];
651};
652
653enum {
654  DWARF_SH3_R0 = 0,
655  DWARF_SH3_R15 = 15,
656  DWARF_SH3_PC = 16,
657  DWARF_SH3_PR = 17,
658  DWARF_SH3_GBR = 18,
659  DWARF_SH3_MACH = 20,
660  DWARF_SH3_MACL = 21,
661  DWARF_SH3_SR = 22,
662
663  REGNO_SH3_R0 = 0,
664  REGNO_SH3_R15 = 15,
665  REGNO_SH3_PC = 16,
666  REGNO_SH3_PR = 17,
667  REGNO_SH3_GBR = 18,
668  REGNO_SH3_MACH = 20,
669  REGNO_SH3_MACL = 21,
670  REGNO_SH3_SR = 22,
671};
672
673class Registers_SH3 {
674public:
675  enum {
676    LAST_REGISTER = REGNO_SH3_SR,
677    LAST_RESTORE_REG = REGNO_SH3_SR,
678    RETURN_OFFSET = 0,
679    RETURN_MASK = 0,
680  };
681
682  __dso_hidden Registers_SH3();
683
684  static int dwarf2regno(int num) {
685    if (num >= DWARF_SH3_R0 && num <= DWARF_SH3_R15)
686      return REGNO_SH3_R0 + (num - DWARF_SH3_R0);
687    switch (num) {
688    case DWARF_SH3_PC:
689      return REGNO_SH3_PC;
690    case DWARF_SH3_PR:
691      return REGNO_SH3_PR;
692    case DWARF_SH3_GBR:
693      return REGNO_SH3_GBR;
694    case DWARF_SH3_MACH:
695      return REGNO_SH3_MACH;
696    case DWARF_SH3_MACL:
697      return REGNO_SH3_MACL;
698    case DWARF_SH3_SR:
699      return REGNO_SH3_SR;
700    default:
701      return LAST_REGISTER + 1;
702    }
703  }
704
705  bool validRegister(int num) const {
706    return (num >= 0 && num <= REGNO_SH3_GBR) ||
707	(num >= REGNO_SH3_MACH && num <= REGNO_SH3_SR);
708  }
709
710  uint64_t getRegister(int num) const {
711    assert(validRegister(num));
712    return reg[num];
713  }
714
715  void setRegister(int num, uint64_t value) {
716    assert(validRegister(num));
717    reg[num] = value;
718  }
719
720  uint64_t getIP() const { return reg[REGNO_SH3_PC]; }
721
722  void setIP(uint64_t value) { reg[REGNO_SH3_PC] = value; }
723
724  uint64_t getSP() const { return reg[REGNO_SH3_R15]; }
725
726  void setSP(uint64_t value) { reg[REGNO_SH3_R15] = value; }
727
728  bool validFloatVectorRegister(int num) const { return false; }
729
730  void copyFloatVectorRegister(int num, uint64_t addr_) {}
731
732  __dso_hidden void jumpto() const __dead;
733
734private:
735  uint32_t reg[REGNO_SH3_SR + 1];
736};
737
738enum {
739  DWARF_SPARC64_R0 = 0,
740  DWARF_SPARC64_R31 = 31,
741  DWARF_SPARC64_PC = 32,
742
743  REGNO_SPARC64_R0 = 0,
744  REGNO_SPARC64_R14 = 14,
745  REGNO_SPARC64_R15 = 15,
746  REGNO_SPARC64_R31 = 31,
747  REGNO_SPARC64_PC = 32,
748};
749
750class Registers_SPARC64 {
751public:
752  enum {
753    LAST_REGISTER = REGNO_SPARC64_PC,
754    LAST_RESTORE_REG = REGNO_SPARC64_PC,
755    RETURN_OFFSET = 8,
756    RETURN_MASK = 0,
757  };
758  typedef uint64_t reg_t;
759
760  __dso_hidden Registers_SPARC64();
761
762  static int dwarf2regno(int num) {
763    if (num >= DWARF_SPARC64_R0 && num <= DWARF_SPARC64_R31)
764      return REGNO_SPARC64_R0 + (num - DWARF_SPARC64_R0);
765    if (num == DWARF_SPARC64_PC)
766      return REGNO_SPARC64_PC;
767    return LAST_REGISTER + 1;
768  }
769
770  bool validRegister(int num) const {
771    return num >= 0 && num <= REGNO_SPARC64_PC;
772  }
773
774  uint64_t getRegister(int num) const {
775    assert(validRegister(num));
776    return reg[num];
777  }
778
779  void setRegister(int num, uint64_t value) {
780    assert(validRegister(num));
781    reg[num] = value;
782  }
783
784  uint64_t getIP() const { return reg[REGNO_SPARC64_PC]; }
785
786  void setIP(uint64_t value) { reg[REGNO_SPARC64_PC] = value; }
787
788  uint64_t getSP() const { return reg[REGNO_SPARC64_R14]; }
789
790  void setSP(uint64_t value) { reg[REGNO_SPARC64_R14] = value; }
791
792  bool validFloatVectorRegister(int num) const { return false; }
793
794  void copyFloatVectorRegister(int num, uint64_t addr_) {}
795
796  __dso_hidden void jumpto() const __dead;
797
798private:
799  uint64_t reg[REGNO_SPARC64_PC + 1];
800};
801
802enum {
803  DWARF_SPARC_R0 = 0,
804  DWARF_SPARC_R31 = 31,
805  DWARF_SPARC_PC = 32,
806
807  REGNO_SPARC_R0 = 0,
808  REGNO_SPARC_R14 = 14,
809  REGNO_SPARC_R15 = 15,
810  REGNO_SPARC_R31 = 31,
811  REGNO_SPARC_PC = 32,
812};
813
814class Registers_SPARC {
815public:
816  enum {
817    LAST_REGISTER = REGNO_SPARC_PC,
818    LAST_RESTORE_REG = REGNO_SPARC_PC,
819    RETURN_OFFSET = 8,
820    RETURN_MASK = 0,
821  };
822  typedef uint32_t reg_t;
823
824  __dso_hidden Registers_SPARC();
825
826  static int dwarf2regno(int num) {
827    if (num >= DWARF_SPARC_R0 && num <= DWARF_SPARC_R31)
828      return REGNO_SPARC_R0 + (num - DWARF_SPARC_R0);
829    if (num == DWARF_SPARC_PC)
830      return REGNO_SPARC_PC;
831    return LAST_REGISTER + 1;
832  }
833
834  bool validRegister(int num) const {
835    return num >= 0 && num <= REGNO_SPARC_PC;
836  }
837
838  uint64_t getRegister(int num) const {
839    assert(validRegister(num));
840    return reg[num];
841  }
842
843  void setRegister(int num, uint64_t value) {
844    assert(validRegister(num));
845    reg[num] = value;
846  }
847
848  uint64_t getIP() const { return reg[REGNO_SPARC_PC]; }
849
850  void setIP(uint64_t value) { reg[REGNO_SPARC_PC] = value; }
851
852  uint64_t getSP() const { return reg[REGNO_SPARC_R14]; }
853
854  void setSP(uint64_t value) { reg[REGNO_SPARC_R14] = value; }
855
856  bool validFloatVectorRegister(int num) const { return false; }
857
858  void copyFloatVectorRegister(int num, uint64_t addr_) {}
859
860  __dso_hidden void jumpto() const __dead;
861
862private:
863  uint32_t reg[REGNO_SPARC_PC + 1];
864};
865
866enum {
867  DWARF_ALPHA_R0 = 0,
868  DWARF_ALPHA_R30 = 30,
869  DWARF_ALPHA_F0 = 32,
870  DWARF_ALPHA_F30 = 62,
871  DWARF_ALPHA_SIGRETURN = 64,
872
873  REGNO_ALPHA_R0 = 0,
874  REGNO_ALPHA_R26 = 26,
875  REGNO_ALPHA_R30 = 30,
876  REGNO_ALPHA_PC = 31,
877  REGNO_ALPHA_F0 = 32,
878  REGNO_ALPHA_F30 = 62,
879  REGNO_ALPHA_SIGRETURN = 64,
880};
881
882class Registers_Alpha {
883public:
884  enum {
885    LAST_REGISTER = REGNO_ALPHA_SIGRETURN,
886    LAST_RESTORE_REG = REGNO_ALPHA_SIGRETURN,
887    RETURN_OFFSET = 0,
888    RETURN_MASK = 0,
889  };
890
891  __dso_hidden Registers_Alpha();
892
893  static int dwarf2regno(int num) { return num; }
894
895  bool validRegister(int num) const {
896    return (num >= 0 && num <= REGNO_ALPHA_PC) ||
897	num == REGNO_ALPHA_SIGRETURN;
898  }
899
900  uint64_t getRegister(int num) const {
901    assert(validRegister(num));
902    if (num == REGNO_ALPHA_SIGRETURN)
903      return sigreturn_reg;
904    else
905      return reg[num];
906  }
907
908  void setRegister(int num, uint64_t value) {
909    assert(validRegister(num));
910    if (num == REGNO_ALPHA_SIGRETURN)
911      sigreturn_reg = value;
912    else
913      reg[num] = value;
914  }
915
916  uint64_t getIP() const { return reg[REGNO_ALPHA_PC]; }
917
918  void setIP(uint64_t value) { reg[REGNO_ALPHA_PC] = value; }
919
920  uint64_t getSP() const { return reg[REGNO_ALPHA_R30]; }
921
922  void setSP(uint64_t value) { reg[REGNO_ALPHA_R30] = value; }
923
924  bool validFloatVectorRegister(int num) const {
925    return num >= REGNO_ALPHA_F0 && num <= REGNO_ALPHA_F30;
926  }
927
928  void copyFloatVectorRegister(int num, uint64_t addr_) {
929    assert(validFloatVectorRegister(num));
930    const void *addr = reinterpret_cast<const void *>(addr_);
931    memcpy(fpreg + (num - REGNO_ALPHA_F0), addr, sizeof(fpreg[0]));
932  }
933
934  __dso_hidden void jumpto() const __dead;
935
936private:
937  uint64_t reg[REGNO_ALPHA_PC + 1];
938  uint64_t fpreg[31];
939  uint64_t sigreturn_reg;
940};
941
942enum {
943  DWARF_HPPA_R1 = 1,
944  DWARF_HPPA_R31 = 31,
945  DWARF_HPPA_FR4L = 32,
946  DWARF_HPPA_FR31H = 87,
947  DWARF_HPPA_SIGRETURN = 89,
948
949  REGNO_HPPA_PC = 0,
950  REGNO_HPPA_R1 = 1,
951  REGNO_HPPA_R2 = 2,
952  REGNO_HPPA_R30 = 30,
953  REGNO_HPPA_R31 = 31,
954  REGNO_HPPA_FR4L = 32,
955  REGNO_HPPA_FR31H = 87,
956  REGNO_HPPA_SIGRETURN = 89,
957};
958
959class Registers_HPPA {
960public:
961  enum {
962    LAST_REGISTER = REGNO_HPPA_FR31H,
963    LAST_RESTORE_REG = REGNO_HPPA_SIGRETURN,
964    RETURN_OFFSET = 0,
965    RETURN_MASK = 3,
966  };
967
968  __dso_hidden Registers_HPPA();
969
970  static int dwarf2regno(int num) {
971    if (num >= DWARF_HPPA_R1 && num <= DWARF_HPPA_R31)
972      return REGNO_HPPA_R1 + (num - DWARF_HPPA_R1);
973    if (num >= DWARF_HPPA_FR4L && num <= DWARF_HPPA_FR31H)
974      return REGNO_HPPA_FR4L + (num - DWARF_HPPA_FR31H);
975    if (num == DWARF_HPPA_SIGRETURN)
976      return REGNO_HPPA_SIGRETURN;
977    return LAST_REGISTER + 1;
978  }
979
980  bool validRegister(int num) const {
981    return (num >= REGNO_HPPA_PC && num <= REGNO_HPPA_R31) ||
982       num == REGNO_HPPA_SIGRETURN;
983  }
984
985  uint64_t getRegister(int num) const {
986    assert(validRegister(num));
987    if (num == REGNO_HPPA_SIGRETURN)
988      return sigreturn_reg;
989    else
990      return reg[num];
991  }
992
993  void setRegister(int num, uint64_t value) {
994    assert(validRegister(num));
995    if (num == REGNO_HPPA_SIGRETURN)
996      sigreturn_reg = value;
997    else
998      reg[num] = value;
999  }
1000
1001  uint64_t getIP() const { return reg[REGNO_HPPA_PC]; }
1002
1003  void setIP(uint64_t value) { reg[REGNO_HPPA_PC] = value; }
1004
1005  uint64_t getSP() const { return reg[REGNO_HPPA_R30]; }
1006
1007  void setSP(uint64_t value) { reg[REGNO_HPPA_R30] = value; }
1008
1009  bool validFloatVectorRegister(int num) const {
1010    return num >= REGNO_HPPA_FR4L && num <= REGNO_HPPA_FR31H;
1011  }
1012
1013  void copyFloatVectorRegister(int num, uint64_t addr_) {
1014    assert(validFloatVectorRegister(num));
1015    const void *addr = reinterpret_cast<const void *>(addr_);
1016    memcpy(fpreg + (num - REGNO_HPPA_FR4L), addr, sizeof(fpreg[0]));
1017  }
1018
1019  __dso_hidden void jumpto() const __dead;
1020
1021private:
1022  uint32_t reg[REGNO_HPPA_R31 + 1];
1023  uint32_t fpreg[56];
1024  uint32_t sigreturn_reg;
1025};
1026
1027enum {
1028  DWARF_MIPS_R1 = 0,
1029  DWARF_MIPS_R31 = 31,
1030  DWARF_MIPS_F0 = 32,
1031  DWARF_MIPS_F31 = 63,
1032  // DWARF Pseudo-registers used by GCC on MIPS for MD{HI,LO} and
1033  // signal handler return address.
1034  DWARF_MIPS_MDHI = 64,
1035  DWARF_MIPS_MDLO = 65,
1036  DWARF_MIPS_SIGRETURN = 66,
1037
1038  REGNO_MIPS_PC = 0,
1039  REGNO_MIPS_R1 = 0,
1040  REGNO_MIPS_R29 = 29,
1041  REGNO_MIPS_R31 = 31,
1042  REGNO_MIPS_F0 = 33,
1043  REGNO_MIPS_F31 = 64,
1044  // these live in other_reg[]
1045  REGNO_MIPS_MDHI = 65,
1046  REGNO_MIPS_MDLO = 66,
1047  REGNO_MIPS_SIGRETURN = 67
1048};
1049
1050class Registers_MIPS {
1051public:
1052  enum {
1053    LAST_REGISTER = REGNO_MIPS_SIGRETURN,
1054    LAST_RESTORE_REG = REGNO_MIPS_SIGRETURN,
1055    RETURN_OFFSET = 0,
1056    RETURN_MASK = 0,
1057  };
1058
1059  __dso_hidden Registers_MIPS();
1060
1061  static int dwarf2regno(int num) {
1062    if (num >= DWARF_MIPS_R1 && num <= DWARF_MIPS_R31)
1063      return REGNO_MIPS_R1 + (num - DWARF_MIPS_R1);
1064    if (num >= DWARF_MIPS_F0 && num <= DWARF_MIPS_F31)
1065      return REGNO_MIPS_F0 + (num - DWARF_MIPS_F0);
1066    if (num >= DWARF_MIPS_MDHI && num <= DWARF_MIPS_SIGRETURN)
1067      return REGNO_MIPS_MDHI + (num - DWARF_MIPS_MDHI);
1068    return LAST_REGISTER + 1;
1069  }
1070
1071  bool validRegister(int num) const {
1072    return (num >= REGNO_MIPS_PC && num <= REGNO_MIPS_R31) ||
1073      (num >= REGNO_MIPS_MDHI && num <= REGNO_MIPS_SIGRETURN);
1074  }
1075
1076  uint64_t getRegister(int num) const {
1077    assert(validRegister(num));
1078    if (num >= REGNO_MIPS_MDHI && num <= REGNO_MIPS_SIGRETURN)
1079      return other_reg[num - REGNO_MIPS_MDHI];
1080    return reg[num];
1081  }
1082
1083  void setRegister(int num, uint64_t value) {
1084    assert(validRegister(num));
1085    if (num >= REGNO_MIPS_MDHI && num <= REGNO_MIPS_SIGRETURN)
1086      other_reg[num - REGNO_MIPS_MDHI] = value;
1087    else
1088      reg[num] = value;
1089  }
1090
1091  uint64_t getIP() const { return reg[REGNO_MIPS_PC]; }
1092
1093  void setIP(uint64_t value) { reg[REGNO_MIPS_PC] = value; }
1094
1095  uint64_t getSP() const { return reg[REGNO_MIPS_R29]; }
1096
1097  void setSP(uint64_t value) { reg[REGNO_MIPS_R29] = value; }
1098
1099  bool validFloatVectorRegister(int num) const {
1100    return num >= REGNO_MIPS_F0 && num <= REGNO_MIPS_F31;
1101  }
1102
1103  void copyFloatVectorRegister(int num, uint64_t addr_) {
1104    assert(validFloatVectorRegister(num));
1105    const void *addr = reinterpret_cast<const void *>(addr_);
1106    memcpy(fpreg + (num - REGNO_MIPS_F0), addr, sizeof(fpreg[0]));
1107  }
1108
1109  __dso_hidden void jumpto() const __dead;
1110
1111private:
1112  uint32_t reg[REGNO_MIPS_R31 + 1];
1113  uint64_t fpreg[32];
1114  uint32_t other_reg[3];
1115};
1116
1117enum {
1118  DWARF_MIPS64_R1 = 0,
1119  DWARF_MIPS64_R31 = 31,
1120  DWARF_MIPS64_F0 = 32,
1121  DWARF_MIPS64_F31 = 63,
1122  // DWARF Pseudo-registers used by GCC on MIPS for MD{HI,LO} and
1123  // signal handler return address.
1124  DWARF_MIPS64_MDHI = 64,
1125  DWARF_MIPS64_MDLO = 65,
1126  DWARF_MIPS64_SIGRETURN = 66,
1127
1128  REGNO_MIPS64_PC = 0,
1129  REGNO_MIPS64_R1 = 0,
1130  REGNO_MIPS64_R29 = 29,
1131  REGNO_MIPS64_R31 = 31,
1132  REGNO_MIPS64_F0 = 33,
1133  REGNO_MIPS64_F31 = 64,
1134  // these live in other_reg[]
1135  REGNO_MIPS64_MDHI = 65,
1136  REGNO_MIPS64_MDLO = 66,
1137  REGNO_MIPS64_SIGRETURN = 67
1138};
1139
1140class Registers_MIPS64 {
1141public:
1142  enum {
1143    LAST_REGISTER = REGNO_MIPS_SIGRETURN,
1144    LAST_RESTORE_REG = REGNO_MIPS_SIGRETURN,
1145    RETURN_OFFSET = 0,
1146    RETURN_MASK = 0,
1147  };
1148
1149  __dso_hidden Registers_MIPS64();
1150
1151  static int dwarf2regno(int num) {
1152    if (num >= DWARF_MIPS64_R1 && num <= DWARF_MIPS64_R31)
1153      return REGNO_MIPS64_R1 + (num - DWARF_MIPS64_R1);
1154    if (num >= DWARF_MIPS64_F0 && num <= DWARF_MIPS64_F31)
1155      return REGNO_MIPS64_F0 + (num - DWARF_MIPS64_F0);
1156    if (num >= DWARF_MIPS64_MDHI && num <= DWARF_MIPS64_SIGRETURN)
1157      return REGNO_MIPS64_MDHI + (num - DWARF_MIPS64_MDHI);
1158    return LAST_REGISTER + 1;
1159  }
1160
1161  bool validRegister(int num) const {
1162    return (num >= REGNO_MIPS64_PC && num <= REGNO_MIPS64_R31) ||
1163        (num >= REGNO_MIPS64_MDHI && num <= REGNO_MIPS64_SIGRETURN);
1164  }
1165
1166  uint64_t getRegister(int num) const {
1167    assert(validRegister(num));
1168    if (num >= REGNO_MIPS64_MDHI && num <= REGNO_MIPS64_SIGRETURN)
1169      return other_reg[num - REGNO_MIPS64_MDHI];
1170    return reg[num];
1171  }
1172
1173  void setRegister(int num, uint64_t value) {
1174    assert(validRegister(num));
1175    if (num >= REGNO_MIPS64_MDHI && num <= REGNO_MIPS64_SIGRETURN)
1176      other_reg[num - REGNO_MIPS64_MDHI] = value;
1177    else
1178      reg[num] = value;
1179  }
1180
1181  uint64_t getIP() const { return reg[REGNO_MIPS64_PC]; }
1182
1183  void setIP(uint64_t value) { reg[REGNO_MIPS64_PC] = value; }
1184
1185  uint64_t getSP() const { return reg[REGNO_MIPS64_R29]; }
1186
1187  void setSP(uint64_t value) { reg[REGNO_MIPS64_R29] = value; }
1188
1189  bool validFloatVectorRegister(int num) const {
1190    return num >= REGNO_MIPS64_F0 && num <= REGNO_MIPS64_F31;
1191  }
1192
1193  void copyFloatVectorRegister(int num, uint64_t addr_) {
1194    assert(validFloatVectorRegister(num));
1195    const void *addr = reinterpret_cast<const void *>(addr_);
1196    memcpy(fpreg + (num - REGNO_MIPS64_F0), addr, sizeof(fpreg[0]));
1197  }
1198
1199  __dso_hidden void jumpto() const __dead;
1200
1201private:
1202  uint64_t reg[REGNO_MIPS64_R31 + 1];
1203  uint64_t fpreg[32];
1204  uint64_t other_reg[3];
1205};
1206
1207enum {
1208  DWARF_OR1K_R0 = 0,
1209  DWARF_OR1K_SP = 1,
1210  DWARF_OR1K_LR = 9,
1211  DWARF_OR1K_R31 = 31,
1212  DWARF_OR1K_FPCSR = 32,
1213
1214  REGNO_OR1K_R0 = 0,
1215  REGNO_OR1K_SP = 1,
1216  REGNO_OR1K_LR = 9,
1217  REGNO_OR1K_R31 = 31,
1218  REGNO_OR1K_FPCSR = 32,
1219};
1220
1221class Registers_or1k {
1222public:
1223  enum {
1224    LAST_REGISTER = REGNO_OR1K_FPCSR,
1225    LAST_RESTORE_REG = REGNO_OR1K_FPCSR,
1226    RETURN_OFFSET = 0,
1227    RETURN_MASK = 0,
1228  };
1229
1230  __dso_hidden Registers_or1k();
1231
1232  static int dwarf2regno(int num) {
1233    if (num >= DWARF_OR1K_R0 && num <= DWARF_OR1K_R31)
1234      return REGNO_OR1K_R0 + (num - DWARF_OR1K_R0);
1235    if (num == DWARF_OR1K_FPCSR)
1236      return REGNO_OR1K_FPCSR;
1237    return LAST_REGISTER + 1;
1238  }
1239
1240  bool validRegister(int num) const {
1241    return num >= 0 && num <= LAST_RESTORE_REG;
1242  }
1243
1244  uint64_t getRegister(int num) const {
1245    assert(validRegister(num));
1246    return reg[num];
1247  }
1248
1249  void setRegister(int num, uint64_t value) {
1250    assert(validRegister(num));
1251    reg[num] = value;
1252  }
1253
1254  uint64_t getIP() const { return reg[REGNO_OR1K_LR]; }
1255
1256  void setIP(uint64_t value) { reg[REGNO_OR1K_LR] = value; }
1257
1258  uint64_t getSP() const { return reg[REGNO_OR1K_SP]; }
1259
1260  void setSP(uint64_t value) { reg[REGNO_OR1K_SP] = value; }
1261
1262  bool validFloatVectorRegister(int num) const {
1263    return false;
1264  }
1265
1266  void copyFloatVectorRegister(int num, uint64_t addr_) {
1267  }
1268
1269  __dso_hidden void jumpto() const __dead;
1270
1271private:
1272  uint32_t reg[REGNO_OR1K_FPCSR + 1];
1273};
1274
1275#if __i386__
1276typedef Registers_x86 NativeUnwindRegisters;
1277#elif __x86_64__
1278typedef Registers_x86_64 NativeUnwindRegisters;
1279#elif __powerpc__
1280typedef Registers_ppc32 NativeUnwindRegisters;
1281#elif __aarch64__
1282typedef Registers_aarch64 NativeUnwindRegisters;
1283#elif __arm__
1284typedef Registers_arm32 NativeUnwindRegisters;
1285#elif __vax__
1286typedef Registers_vax NativeUnwindRegisters;
1287#elif __m68k__
1288typedef Registers_M68K NativeUnwindRegisters;
1289#elif __mips_n64 || __mips_n32
1290typedef Registers_MIPS64 NativeUnwindRegisters;
1291#elif __mips__
1292typedef Registers_MIPS NativeUnwindRegisters;
1293#elif __sh3__
1294typedef Registers_SH3 NativeUnwindRegisters;
1295#elif __sparc64__
1296typedef Registers_SPARC64 NativeUnwindRegisters;
1297#elif __sparc__
1298typedef Registers_SPARC NativeUnwindRegisters;
1299#elif __alpha__
1300typedef Registers_Alpha NativeUnwindRegisters;
1301#elif __hppa__
1302typedef Registers_HPPA NativeUnwindRegisters;
1303#elif __or1k__
1304typedef Registers_or1k NativeUnwindRegisters;
1305#endif
1306} // namespace _Unwind
1307
1308#endif // __REGISTERS_HPP__
1309