Update copyright to LGPL on all files
[dyninst.git] / dyninstAPI / src / MemoryAccess.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 /* $Id: MemoryAccess.C,v 1.13 2006/10/16 20:17:14 bernat Exp $ */
33
34 #include <stdlib.h>
35 #include <string.h>
36
37 #include "BPatch_memoryAccess_NP.h"
38 #include "BPatch_point.h"
39 #include "BPatch_Vector.h"
40 #include "../../common/h/Types.h"
41 #if !defined(cap_instruction_api)
42 extern void initOpCodeInfo();
43 #endif
44
45
46 BPatch_addrSpec_NP::BPatch_addrSpec_NP(long _imm, int _ra, int _rb, int _scale) :
47    imm(_imm), 
48    scale(_scale)
49 {
50    regs[0] = _ra;
51    regs[1] = _rb;
52 }
53
54 BPatch_addrSpec_NP::BPatch_addrSpec_NP() : 
55    imm(0), 
56    scale(0)
57 {
58    regs[0] = 0;
59    regs[1] = 0;
60 }
61
62 long BPatch_addrSpec_NP::getImm() const 
63
64    return imm; 
65 }
66
67 int BPatch_addrSpec_NP::getScale() const 
68
69    return scale; 
70 }
71
72 int BPatch_addrSpec_NP::getReg(unsigned i) const 
73
74    return regs[i]; 
75 }
76
77 bool BPatch_addrSpec_NP::equals(const BPatch_addrSpec_NP& ar) const
78 {
79    return ((imm == ar.imm) && (scale == ar.scale) &&
80            (regs[0] == ar.regs[0]) && (regs[1] == ar.regs[1]));
81 }
82
83 BPatch_Vector<BPatch_point*>* BPatch_memoryAccess::filterPoints(
84                 const BPatch_Vector<BPatch_point *> &points,
85                 unsigned int numMAs)
86 {
87   BPatch_Vector<BPatch_point*> *result = new BPatch_Vector<BPatch_point *>;
88
89   for(unsigned int i = 0; i < points.size(); ++i) {
90     const BPatch_memoryAccess *ma = points[i]->getMemoryAccess();
91     if(ma)
92       if(ma->getNumberOfAccesses() >= numMAs)
93         result->push_back(points[i]);
94   }
95   return result;
96 }
97  
98 const BPatch_addrSpec_NP *BPatch_memoryAccess::getStartAddr(int which) const
99
100    return &(start[which]);
101 }
102
103 const BPatch_countSpec_NP *BPatch_memoryAccess::getByteCount(int which) const
104
105    return &(count[which]);
106 }
107
108 // initializes only the first access - general case
109 void BPatch_memoryAccess::set1st(bool _isLoad, bool _isStore,
110             long _imm_s, int _ra_s, int _rb_s, unsigned int _scale_s,
111             long _imm_c, int _ra_c, int _rb_c, unsigned int _scale_c,
112             int _preFcn, int _cond, bool _nt)
113 {
114    nacc = 1;
115    isLoad[0] = _isLoad;
116    isStore[0] = _isStore;
117    start[0] = BPatch_addrSpec_NP(_imm_s, _ra_s, _rb_s, _scale_s);
118    count[0] = BPatch_countSpec_NP(_imm_c, _ra_c, _rb_c, _scale_c);
119    preFcn[0] = _preFcn;
120    condition[0] = _cond;
121    nonTemporal[0] = _nt;
122 }
123
124   // initializes only the first access - no scale for count
125 void BPatch_memoryAccess::set1st(bool _isLoad, bool _isStore,
126               long _imm_s, int _ra_s, int _rb_s, long _imm_c, int _ra_c, 
127               int _rb_c, unsigned int _scale_s, int _preFcn, int _cond, 
128               bool _nt)
129 {
130    nacc = 1;
131    isLoad[0] = _isLoad;
132    isStore[0] = _isStore;
133    start[0] = BPatch_addrSpec_NP(_imm_s, _ra_s, _rb_s, _scale_s);
134    count[0] = BPatch_countSpec_NP(_imm_c, _ra_c, _rb_c);
135    preFcn[0] = _preFcn;
136    condition[0] = _cond;
137    nonTemporal[0] = _nt;
138 }
139
140 BPatch_memoryAccess* BPatch_memoryAccess::init_tables()
141 {
142 #if !defined(cap_instruction_api)
143    initOpCodeInfo();
144 #endif   
145     return NULL;
146 }
147
148 // initializes only the first access; #bytes is a constant
149 BPatch_memoryAccess::BPatch_memoryAccess(instruction *insn, Address _addr,
150                                          bool _isLoad, bool _isStore, unsigned int _bytes,
151                                          long _imm, int _ra, int _rb, unsigned int _scale,
152                                          int _cond, bool _nt) : 
153     BPatch_instruction(insn, _addr)
154 {
155     start = new BPatch_addrSpec_NP[nmaxacc_NP];
156     count = new BPatch_countSpec_NP[nmaxacc_NP];
157     set1st(_isLoad, _isStore, _imm, _ra, _rb, _bytes, -1, -1, _scale, -1, _cond,
158            _nt);
159 }
160
161 // initializes only the first access; #bytes is an expression w/scale
162 BPatch_memoryAccess::BPatch_memoryAccess(instruction *insn, Address _addr,
163                     bool _isLoad, bool _isStore, long _imm_s, int _ra_s, int _rb_s,
164                     unsigned int _scale_s, long _imm_c, int _ra_c, int _rb_c, 
165                     unsigned int _scale_c, int _cond, bool _nt, int _preFcn) : 
166    BPatch_instruction(insn, _addr)
167 {
168    start = new BPatch_addrSpec_NP[nmaxacc_NP];
169    count = new BPatch_countSpec_NP[nmaxacc_NP];
170    set1st(_isLoad, _isStore, _imm_s, _ra_s, _rb_s, _scale_s, _imm_c, _ra_c, 
171           _rb_c, _scale_c, _preFcn, _cond, _nt);
172 }
173
174 // initializes only the first access; #bytes is an expression
175 BPatch_memoryAccess::BPatch_memoryAccess(instruction *insn, Address _addr,
176                     bool _isLoad, bool _isStore, bool _isPrefetch, long _imm_s, 
177                     int _ra_s, int _rb_s, long _imm_c, int _ra_c, int _rb_c,
178                     unsigned short _preFcn) : 
179    BPatch_instruction(insn, _addr)
180 {
181    start = new BPatch_addrSpec_NP[nmaxacc_NP];
182    count = new BPatch_countSpec_NP[nmaxacc_NP];
183    assert(_isPrefetch);
184    set1st(_isLoad, _isStore, _imm_s, _ra_s, _rb_s, _imm_c, _ra_c, _rb_c, 
185           0, _preFcn);
186 }
187
188   // initializes only the first access; #bytes is an expression & not a prefetch
189 BPatch_memoryAccess::BPatch_memoryAccess(instruction *insn, Address _addr,
190                bool _isLoad, bool _isStore, long _imm_s, int _ra_s, int _rb_s,
191                long _imm_c, int _ra_c, int _rb_c) : 
192    BPatch_instruction(insn, _addr)
193 {
194    start = new BPatch_addrSpec_NP[nmaxacc_NP];
195    count = new BPatch_countSpec_NP[nmaxacc_NP];
196    set1st(_isLoad, _isStore, _imm_s, _ra_s, _rb_s, _imm_c, _ra_c, _rb_c);
197 }
198
199   // sets 2nd access; #bytes is constant
200 void BPatch_memoryAccess::set2nd(bool _isLoad, bool _isStore, 
201             unsigned int _bytes, long _imm, int _ra, int _rb, 
202             unsigned int _scale)
203 {
204    if(nacc >= 2)
205       return;
206    nacc = 2;
207    isLoad[1] = _isLoad;
208    isStore[1] = _isStore;
209    start[1] = BPatch_addrSpec_NP(_imm, _ra, _rb, _scale);
210    count[1] = BPatch_countSpec_NP(_bytes);
211    preFcn[1] = -1;
212    condition[1] = -1;
213    nonTemporal[1] = false;
214 }
215
216   // sets 2nd access; #bytes is an expression w/scale
217 void BPatch_memoryAccess::set2nd(bool _isLoad, bool _isStore,
218             long _imm_s, int _ra_s, int _rb_s, unsigned int _scale_s,
219               long _imm_c, int _ra_c, int _rb_c, unsigned int _scale_c,
220               int _cond, bool _nt)
221 {
222    if(nacc >= 2)
223       return;
224    nacc = 2;
225    isLoad[1] = _isLoad;
226    isStore[1] = _isStore;
227    start[1] = BPatch_addrSpec_NP(_imm_s, _ra_s, _rb_s, _scale_s);
228    count[1] = BPatch_countSpec_NP(_imm_c, _ra_c, _rb_c, _scale_c);
229    preFcn[1] = -1;
230    condition[1] = _cond;
231    nonTemporal[1] = _nt;
232 }
233
234 // initializes both accesses; #bytes is a constant
235 BPatch_memoryAccess::BPatch_memoryAccess(instruction *insn, Address _addr,
236                       bool _isLoad, bool _isStore, unsigned int _bytes,
237             long _imm, int _ra, int _rb, unsigned int _scale,
238             bool _isLoad2, bool _isStore2, unsigned int _bytes2,
239             long _imm2, int _ra2, int _rb2, unsigned int _scale2) : 
240    BPatch_instruction(insn, _addr)
241 {
242    start = new BPatch_addrSpec_NP[nmaxacc_NP];
243    count = new BPatch_countSpec_NP[nmaxacc_NP];
244    set1st(_isLoad, _isStore, _imm, _ra, _rb, _bytes, -1, -1, _scale);
245    set2nd(_isLoad2, _isStore2, _bytes2, _imm2, _ra2, _rb2, _scale2);
246 }
247
248   // initializes both accesses; #bytes is an expression & not a prefetch
249 BPatch_memoryAccess::BPatch_memoryAccess(instruction *insn, Address _addr,
250          bool _isLoad, bool _isStore, long _imm_s, int _ra_s, int _rb_s, 
251          unsigned int _scale_s, long _imm_c, int _ra_c, int _rb_c, 
252          unsigned int _scale_c, bool _isLoad2, bool _isStore2, long _imm2_s, 
253          int _ra2_s, int _rb2_s, unsigned int _scale2_s, long _imm2_c, 
254          int _ra2_c, int _rb2_c, unsigned int _scale2_c) : 
255    BPatch_instruction(insn, _addr)
256 {
257    start = new BPatch_addrSpec_NP[nmaxacc_NP];
258    count = new BPatch_countSpec_NP[nmaxacc_NP];
259    set1st(_isLoad, _isStore, 
260           _imm_s, _ra_s, _rb_s, _scale_s,
261           _imm_c, _ra_c, _rb_c, _scale_c,
262           -1, -1, false);
263    set2nd(_isLoad2, _isStore2,
264           _imm2_s, _ra2_s, _rb2_s, _scale2_s,
265           _imm2_c, _ra2_c, _rb2_c, _scale2_c,
266           -1, false);
267 }
268
269
270 bool BPatch_memoryAccess::equals(const BPatch_memoryAccess* mp) const 
271
272    return mp ? equals(*mp) : false; 
273 }
274
275 bool BPatch_memoryAccess::equals(const BPatch_memoryAccess& rp) const
276 {
277    bool res = nacc == rp.nacc;
278    
279    if(!res)
280       return res;
281    
282    for(unsigned int i=0; i<nacc; ++i) {
283       res = res &&
284          (isLoad[i] == rp.isLoad[i]) &&
285          (isStore[i] == rp.isStore[i]) &&
286          (start[i].equals(rp.start[i])) &&
287          (count[i].equals(rp.count[i])) &&
288          (preFcn[i] == rp.preFcn[i]) &&
289          (condition[i] == rp.condition[i]) && 
290          (nonTemporal[i] == rp.nonTemporal[i]);
291       if(!res)
292          break;
293    }
294
295    return res;
296 }
297
298 BPatch_addrSpec_NP BPatch_memoryAccess::getStartAddr_NP(int which) const 
299
300    return start[which]; 
301 }
302
303 BPatch_countSpec_NP BPatch_memoryAccess::getByteCount_NP(int which) const 
304
305    return count[which]; 
306 }
307
308 BPatch_memoryAccess::~BPatch_memoryAccess() {
309    delete[] start;
310    delete[] count;
311 }
312
313 BPatch_memoryAccess* const BPatch_memoryAccess::none = init_tables();