Register interface: Added converter to ROSE register type
[dyninst.git] / common / src / dyn_regs.C
1 /*
2  * Copyright (c) 1996-2009 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as "Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30  */
31
32 #define DYN_DEFINE_REGS
33 #include "dynutil/h/dyn_regs.h"
34
35 #include "external/rose/rose-compat.h"
36
37 namespace Dyninst {
38
39 std::map<signed int, const char *> *Dyninst::MachRegister::names;
40
41 MachRegister::MachRegister() :
42    reg(0)
43
44 }
45
46 MachRegister::MachRegister(signed int r) :
47    reg(r)
48 {
49 }
50  
51 MachRegister::MachRegister(const MachRegister& r) :
52         reg(r.reg)
53 {
54 }
55
56 MachRegister::MachRegister(signed int r, const char *n) :
57    reg(r)
58 {
59    if (!names) {
60       names = new std::map<signed int, const char *>();
61    }
62    (*names)[r] = n;
63 }
64
65 MachRegister::~MachRegister() {
66 }
67
68 MachRegister MachRegister::getBaseRegister() const { 
69    switch (getArchitecture()) {
70       case Arch_x86:
71       case Arch_x86_64:
72           return MachRegister(reg & 0xfffff0ff);
73       case Arch_ppc32:
74       case Arch_ppc64:
75          return *this;
76       case Arch_none:
77          return *this;
78    }
79    return InvalidReg;
80 }
81    
82 Architecture MachRegister::getArchitecture() const { 
83    return (Architecture) (reg & 0xff000000);
84 }
85
86 bool MachRegister::isValid() const {
87    return (reg != InvalidReg.reg);
88 }
89
90 MachRegisterVal MachRegister::getSubRegValue(const MachRegister subreg, 
91                                              MachRegisterVal &orig) const
92 {
93    if (subreg.reg == reg || 
94        getArchitecture() == Arch_ppc32 ||
95        getArchitecture() == Arch_ppc64)
96       return orig;
97
98    assert(subreg.getBaseRegister() == getBaseRegister());
99    switch ((subreg.reg & 0x00000f00) >> 8) {
100       case 0x0: return orig;
101       case 0x1: return (orig & 0xff);
102       case 0x2: return (orig & 0xff00) >> 8;              
103       case 0x3: return (orig & 0xffff);
104       case 0xf: return (orig & 0xffffffff);
105       default: assert(0); return orig;
106    }
107 }
108
109 const char *MachRegister::name() const { 
110    return (*names)[reg];
111 }
112
113 unsigned int MachRegister::size() const {
114    switch (getArchitecture())
115    {
116       case Arch_x86:
117          switch (reg & 0x0000ff00) {
118              case x86::L_REG: //L_REG
119             case x86::H_REG: //H_REG
120                return 1;
121                case x86::W_REG: //W_REG
122                return 2;
123                case x86::FULL: //FULL
124                return 4;
125              case x86::QUAD:
126                 return 8;
127              case x86::OCT:
128                  return 16;
129              case x86::FPDBL:
130                  return 10;
131              default:
132                assert(0);
133          }
134       case Arch_x86_64:
135          switch (reg & 0x0000ff00) {
136              case x86_64::L_REG: //L_REG
137              case x86_64::H_REG: //H_REG
138                 return 1;
139              case x86_64::W_REG: //W_REG
140                 return 2;
141              case x86_64::FULL: //FULL
142                 return 8;
143              case x86_64::D_REG:
144                  return 4;
145              case x86_64::OCT:
146                  return 16;
147              case x86_64::FPDBL:
148                  return 10;
149              default:
150                assert(0);
151          }
152       case Arch_ppc32: {
153          int reg_class = reg & 0x00ff0000;
154          if (reg_class == ppc32::FPR || reg_class == ppc32::FSR)
155             return 8;
156          return 4;
157       }
158       case Arch_ppc64:
159          return 8;
160       case Arch_none:
161          return 0;
162    }
163    return 0; //Unreachable, but disable warnings
164 }
165    
166 bool MachRegister::operator<(const MachRegister &a) const { 
167    return (reg < a.reg);
168 }
169  
170 bool MachRegister::operator==(const MachRegister &a) const { 
171    return (reg == a.reg);
172 }
173  
174 MachRegister::operator signed int() const {
175    return reg;
176 }
177
178 signed int MachRegister::val() const {
179    return reg;
180 }
181
182
183 MachRegister MachRegister::getPC(Dyninst::Architecture arch)
184 {
185    switch (arch)
186    {
187       case Arch_x86:
188          return x86::eip;
189       case Arch_x86_64:
190          return x86_64::rip;
191       case Arch_ppc32:
192          return ppc32::pc;
193       case Arch_ppc64:
194          return ppc64::pc;
195       case Arch_none:
196          return InvalidReg;
197    }
198    return InvalidReg;
199 }
200
201 MachRegister MachRegister::getFramePointer(Dyninst::Architecture arch)
202 {
203    switch (arch)
204    {
205       case Arch_x86:
206          return x86::ebp;
207       case Arch_x86_64:
208          return x86_64::rbp;
209       case Arch_ppc32:
210       case Arch_ppc64:
211          return FrameBase;
212       case Arch_none:
213          return InvalidReg;
214    }
215    return InvalidReg;
216 }
217
218 MachRegister MachRegister::getStackPointer(Dyninst::Architecture arch)
219 {
220    switch (arch)
221    {
222       case Arch_x86:
223          return x86::esp;
224       case Arch_x86_64:
225          return x86_64::rsp;
226       case Arch_ppc32:
227          return ppc32::r1;
228       case Arch_ppc64:
229          return ppc64::r1;
230       case Arch_none:
231          return InvalidReg;
232    }
233    return InvalidReg;
234 }
235
236 bool MachRegister::isPC() const
237 {
238    return (*this == x86_64::rip || *this == x86::eip ||
239            *this == ppc32::pc || *this == ppc64::pc);
240 }
241
242 bool MachRegister::isFramePointer() const
243 {
244    return (*this == x86_64::rbp || *this == x86::ebp ||
245            *this == FrameBase);
246 }
247
248 bool MachRegister::isStackPointer() const
249 {
250    return (*this == x86_64::rsp || *this == x86::esp ||
251            *this == ppc32::r1 || *this == ppc64::r1);
252 }
253
254 void MachRegister::getROSERegister(int &c, int &n, int &p)
255 {
256    // Rose: class, number, position
257    // Dyninst: category, base id, subrange
258
259    signed int category = (reg & 0x00ff0000);
260    signed int subrange = (reg & 0x0000ff00);
261    signed int baseID =   (reg & 0x000000ff);
262
263    switch (getArchitecture()) {
264       case Arch_x86:
265       case Arch_x86_64: // 64-bit not supported in ROSE
266          switch (category) {
267             case x86::GPR:
268                c = x86_regclass_gpr;
269                switch (baseID) {
270                   case x86::BASEA:
271                      n = x86_gpr_ax;
272                      break;
273                   case x86::BASEC:
274                      n = x86_gpr_cx;
275                      break;
276                   case x86::BASED:
277                      n = x86_gpr_dx;
278                      break;
279                   case x86::BASEB:
280                      n = x86_gpr_bx;
281                      break;
282                   case x86::BASESP:
283                      n = x86_gpr_sp;
284                      break;
285                   case x86::BASEBP:
286                      n = x86_gpr_bp;
287                      break;
288                   case x86::BASESI:
289                      n = x86_gpr_si;
290                      break;
291                   case x86::BASEDI:
292                      n = x86_gpr_di;
293                      break;
294                   default:
295                      n = 0;
296                      break;
297                }
298                break;
299             case x86::SEG:
300                c = x86_regclass_segment;
301                switch (baseID) {
302                   case 0x0:
303                      n = x86_segreg_ds;
304                      break;
305                   case 0x1:
306                      n = x86_segreg_es;
307                      break;
308                   case 0x2:
309                      n = x86_segreg_fs;
310                      break;
311                   case 0x3:
312                      n = x86_segreg_gs;
313                      break;
314                   case 0x4:
315                      n = x86_segreg_cs;
316                      break;
317                   case 0x5:
318                      n = x86_segreg_ss;
319                      break;
320                   default:
321                      n = 0;
322                      break;
323                }
324                break;
325             case x86::FLAG:
326                c = x86_regclass_flags;
327                n = 0;
328                break;
329             case x86::MISC:
330                c = x86_regclass_unknown;
331                break;
332             case x86::XMM:
333                c = x86_regclass_xmm;
334                n = baseID;
335                break;
336             case x86::MMX:
337                c = x86_regclass_mm;
338                n = baseID;
339                break;
340             case x86::CTL:
341                c = x86_regclass_cr;
342                n = baseID;
343                break;
344             case x86::DBG:
345                c = x86_regclass_dr;
346                n = baseID;
347                break;
348             case x86::TST:
349                c = x86_regclass_unknown;
350                break;
351             case 0:
352                switch (baseID) {
353                   case 0x10:
354                      c = x86_regclass_ip;
355                      n = 0;
356                      break;
357                   default:
358                      c = x86_regclass_unknown;
359                      break;
360                }
361                break;
362          }
363          break;
364       default:
365          c = x86_regclass_unknown;
366          n = 0;
367          break;
368    }
369
370    switch (getArchitecture()) {
371       case Arch_x86:
372       case Arch_x86_64:
373          switch (subrange) {
374             case x86::FULL:
375             case x86::OCT:
376             case x86::FPDBL:
377                p = x86_regpos_all;
378                break;
379             case x86::H_REG:
380                p = x86_regpos_high_byte;
381                break;
382             case x86::L_REG:
383                p = x86_regpos_low_byte;
384                break;
385             case x86::W_REG:
386                p = x86_regpos_word;
387                break;
388             case x86_64::D_REG:
389                p = x86_regpos_dword;
390                break;
391          }
392          break;
393       default:
394         p = x86_regpos_unknown;
395    }
396 }
397
398 }