Update copyright to LGPL on all files
[dyninst.git] / instructionAPI / src / Register.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 #include "Register.h"
33 #include "../../common/h/Singleton.h"
34 #include <vector>
35 #include <set>
36 #include <sstream>
37 #include "Visitor.h"
38 #include "../../common/h/singleton_object_pool.h"
39
40 using namespace std;
41 using namespace dyn_detail::boost;
42
43 extern bool ia32_is_mode_64();
44
45
46 namespace Dyninst
47 {
48   namespace InstructionAPI
49   {
50     RegisterAST::RegisterAST(int id) : 
51       Expression(Singleton<IA32RegTable>::getInstance().getSize(id)), registerID(id) 
52     {
53     }
54     RegisterAST::~RegisterAST()
55     {
56     }
57     void RegisterAST::getChildren(vector<InstructionAST::Ptr>& /*children*/) const
58     {
59       return;
60     }
61     void RegisterAST::getUses(set<InstructionAST::Ptr>& uses)
62     {
63       if(registerID == r_ALLGPRS)
64       {
65         uses.insert(InstructionAST::Ptr(new RegisterAST(r_EAX)));
66         uses.insert(InstructionAST::Ptr(new RegisterAST(r_ECX)));
67         uses.insert(InstructionAST::Ptr(new RegisterAST(r_EDX)));
68         uses.insert(InstructionAST::Ptr(new RegisterAST(r_EBX)));
69         uses.insert(InstructionAST::Ptr(new RegisterAST(r_ESP)));
70         uses.insert(InstructionAST::Ptr(new RegisterAST(r_EBP)));
71         uses.insert(InstructionAST::Ptr(new RegisterAST(r_ESI)));
72         uses.insert(InstructionAST::Ptr(new RegisterAST(r_EDI)));
73       }
74       else
75       {
76         uses.insert(shared_from_this());
77       }
78       return;
79     }
80     bool RegisterAST::isUsed(InstructionAST::Ptr findMe) const
81     {
82                 RegisterAST::Ptr promotedThis = RegisterAST::promote(this);
83       if(*findMe == *this)
84       {
85                 return true;
86       }
87           return findMe->checkRegID(promotedThis->getID());
88     }
89     unsigned int RegisterAST::getID() const
90     {
91       return registerID;
92     }
93     
94     std::string RegisterAST::format() const
95     {
96       std::stringstream retVal;
97           RegTable::iterator foundName = Singleton<IA32RegTable>::getInstance().IA32_register_names.find(IA32Regs(registerID));
98       if(foundName != Singleton<IA32RegTable>::getInstance().IA32_register_names.end())
99       {
100                 retVal << (*foundName).second.regName;
101       }
102       else
103       {
104                 retVal << "R" << registerID;
105       }
106       return retVal.str();
107     }
108     RegisterAST RegisterAST::makePC()
109     {
110       // Make this platform independent
111       return RegisterAST(r_EIP);
112     }
113     
114     bool RegisterAST::operator<(const RegisterAST& rhs) const
115     {
116       return registerID < rhs.registerID;
117     }
118     bool RegisterAST::isStrictEqual(const InstructionAST& rhs) const
119     {
120       return rhs.checkRegID(registerID);
121     }
122     RegisterAST::Ptr RegisterAST::promote(const InstructionAST::Ptr regPtr) {
123         const RegisterAST::Ptr r = dyn_detail::boost::dynamic_pointer_cast<RegisterAST>(regPtr);
124         return RegisterAST::promote(r);
125     }
126     int RegisterAST::getPromotedID() const
127     {
128         unsigned int convertedID = 0;
129         if (/*(registerID >= r_AH) && */(registerID <= r_DH)) {
130             convertedID = registerID + (r_EAX-r_AH);
131         }
132         else if ((registerID >= r_AL) && (registerID <= r_DL)) {
133             convertedID = registerID + (r_EAX-r_AL);
134         }
135         else if ((registerID >= r_AX) && (registerID <= r_DI)) {
136             convertedID = registerID + (r_EAX - r_AX);
137         }
138         else if ((registerID >= r_eAX) && (registerID <= r_eDI)) {
139             convertedID = registerID + (r_EAX - r_eAX);
140         }
141         else if ((registerID >= r_eSP) && (registerID <= r_eBP)) {
142             convertedID = registerID + (r_ESP - r_eSP);
143         }
144         else if ((registerID >= r_rAX) && (registerID <= r_rDI)) {
145             convertedID = registerID + (r_RAX - r_rAX);
146         }
147         else if ((registerID >= r_rSP) && (registerID <= r_rBP)) {
148             convertedID = registerID + (r_RSP - r_rSP);
149         }
150         else {
151             convertedID = registerID;
152         }
153
154         if (ia32_is_mode_64()) {
155             // Take a 32-bit register and turn it into a 64-bit
156             if ((convertedID >= r_EAX) && (convertedID <= r_EDI)) {
157                 convertedID = convertedID + (r_RAX - r_EAX);
158             }
159             else if ((convertedID >= r_ESP) && (convertedID <= r_EBP)) {
160                 convertedID = convertedID + (r_RSP - r_ESP);
161             }
162         }
163         else {
164             // Take 64-bit regs and turn them into 32-bit
165             if ((convertedID >= r_RAX) && (convertedID <= r_RDI)) {
166                 convertedID = convertedID - r_RAX + r_EAX;
167             }
168             else if ((convertedID >= r_RSP) && (convertedID <= r_RBP)) {
169                 convertedID = convertedID - r_RSP + r_ESP;
170             }
171         }
172         return convertedID;
173     }
174
175     RegisterAST::Ptr RegisterAST::promote(const RegisterAST* regPtr) {
176         if (!regPtr) return RegisterAST::Ptr();
177
178         unsigned convertedID = regPtr->getPromotedID();
179
180         // We want to upconvert the register ID to the maximal containing
181         // register for the platform - either EAX or RAX as appropriate.
182
183         return make_shared(singleton_object_pool<RegisterAST>::construct(convertedID));
184     }
185     bool RegisterAST::isFlag() const
186     {
187       return registerID >= r_OF && registerID <= r_RF;
188     }
189     bool RegisterAST::checkRegID(unsigned int id) const
190     {
191         if(registerID == r_ALLGPRS)
192         {
193             if(id == r_EAX ||
194                id == r_EDX ||
195                id == r_ECX ||
196                id == r_EBX ||
197                id == r_ESP ||
198                id == r_EBP ||
199                id == r_ESI ||
200                id == r_EDI ||
201                id == r_RAX ||
202                id == r_RDX ||
203                id == r_RCX ||
204                id == r_RBX ||
205                id == r_RSP ||
206                id == r_RBP ||
207                id == r_RSI ||
208                id == r_RDI)
209             {
210                 return true;
211             }
212         }
213         if(id == r_ALLGPRS)
214         {
215             if(registerID == r_EAX ||
216                registerID == r_EDX ||
217                registerID == r_ECX ||
218                registerID == r_EBX ||
219                registerID == r_ESP ||
220                registerID == r_EBP ||
221                registerID == r_ESI ||
222                registerID == r_EDI ||
223                registerID == r_RAX ||
224                registerID == r_RDX ||
225                registerID == r_RCX ||
226                registerID == r_RBX ||
227                registerID == r_RSP ||
228                registerID == r_RBP ||
229                registerID == r_RSI ||
230                registerID == r_RDI)
231             {
232                 return true;
233             }
234         }
235         return (id == registerID) || (id == getPromotedID());
236     }
237     void RegisterAST::apply(Visitor* v)
238     {
239         v->visit(this);
240     }
241   };
242 };