This commit enables arbitrary instrumentation points at the last instruction
[dyninst.git] / dyninstAPI / h / BPatch_memoryAccess_NP.h
1 /* $Id: BPatch_memoryAccess_NP.h,v 1.11 2002/09/23 21:47:10 gaburici Exp $ */
2
3 #ifndef _MemoryAccess_h_
4 #define _MemoryAccess_h_
5
6 #include <stdlib.h>
7 #include <BPatch_point.h>
8
9 /* Pseudoregisters definitions */
10 #define POWER_XER2531   9999
11
12 #define IA32_EMULATE    1000
13 #define IA32_ESCAS      1000
14 #define IA32_NESCAS     1001
15 #define IA32_ECMPS      1002
16 #define IA32_NECMPS     1003
17
18 #define IA32prefetchNTA  0
19 #define IA32prefetchT0   1
20 #define IA32prefetchT1   2
21 #define IA32prefetchT2   3
22 #define IA32AMDprefetch  100
23 #define IA32AMDprefetchw 101
24
25
26 /* This is believed to be machine independent, modulo register numbers of course */
27 struct BPATCH_DLL_EXPORT BPatch_addrSpec_NP
28 {
29   // the formula is regs[0] + 2 ^ scale * regs[1] + imm
30   int imm;      // immediate
31   unsigned int scale;
32   int regs[2];  // registers: -1 means none, 0 is 1st, 1 is 2nd and so on
33                 // some pseudoregisters may be used, see the documentation
34
35 public:
36   BPatch_addrSpec_NP(int _imm, int _ra = -1, int _rb = -1, int _scale = 0)
37     :  imm(_imm), scale(_scale)
38   {
39     regs[0] = _ra;
40     regs[1] = _rb;
41   }
42
43   BPatch_addrSpec_NP() : imm(0), scale(0)
44   {
45     regs[0] = 0;
46     regs[1] = 0;
47   }
48
49   int getImm() const { return imm; }
50   int getScale() const { return scale; }
51   int getReg(unsigned i) const { return regs[i]; }
52
53   bool equals(const BPatch_addrSpec_NP& ar) const
54   {
55     return
56       (imm == ar.imm) &&
57       (scale == ar.scale) &&
58       (regs[0] == ar.regs[0]) &&
59       (regs[1] == ar.regs[1]);
60   }
61 };
62
63 #define BPatch_countSpec_NP BPatch_addrSpec_NP // right now it has the same form
64
65 class BPatch_memoryAccess;
66 extern void initOpCodeInfo();
67
68
69 class BPATCH_DLL_EXPORT BPatch_memoryAccess
70 {
71   friend class BPatch_function;
72   friend class AstNode;
73   friend class InstrucIter;
74
75  public:
76   // maximum number of memory accesses per instruction; platform dependent
77 #if defined(i386_unknown_nt4_0)
78   // Translation from C++ to VC++ 6.0
79 #define nmaxacc_NP 2
80 #else
81 #if defined(i386_unknown_linux2_0)
82   static const unsigned int nmaxacc_NP = 2;
83 #else
84   static const unsigned int nmaxacc_NP = 1;
85 #endif
86 #endif
87
88   // Utility function to filter out the points that don't have a 2nd memory access on x86
89   static BPatch_Vector<BPatch_point*>* filterPoints(const BPatch_Vector<BPatch_point*> &points,
90                                                     unsigned int numMAs);
91   
92  private:
93   unsigned int nacc;
94   bool isLoad[nmaxacc_NP];
95   bool isStore[nmaxacc_NP];
96   // VG(8/13/02): removed redundant isPrefetch fields; preFcn>=0 is the same thing
97
98   BPatch_addrSpec_NP start[nmaxacc_NP];
99   BPatch_countSpec_NP count[nmaxacc_NP];
100   int  preFcn[nmaxacc_NP];      // prefetch function (-1 = none)
101   int  condition[nmaxacc_NP];   // -1 means no condition, all other values are machine specific
102                                 // conditions, currently (8/13/02) the tttn field on x86
103   bool nonTemporal[nmaxacc_NP]; // non-temporal (cache non-polluting) write on x86
104
105  protected:
106   bool hasALoad() const { return nacc == 1 ? isLoad[0] : (isLoad[0] || isLoad[1]); }
107   bool hasAStore() const { return nacc == 1 ? isStore[0] : (isStore[0] || isStore[1]); }
108   bool hasAPrefetch() const { return preFcn[0] >= 0; }
109   int  prefetchType(int which = 0) { return preFcn[which]; }
110
111   BPatch_addrSpec_NP getStartAddr(int which = 0) const { return start[which]; }
112   BPatch_countSpec_NP getByteCount(int which = 0) const { return count[which]; }
113
114
115   // initializes only the first access - general case
116   void set1st(bool _isLoad, bool _isStore,
117               int _imm_s, int _ra_s, int _rb_s, unsigned int _scale_s,
118               int _imm_c, int _ra_c, int _rb_c, unsigned int _scale_c,
119               int _preFcn, int _cond, bool _nt)
120   {
121     nacc = 1;
122     isLoad[0] = _isLoad;
123     isStore[0] = _isStore;
124     start[0] = BPatch_addrSpec_NP(_imm_s, _ra_s, _rb_s, _scale_s);
125     count[0] = BPatch_countSpec_NP(_imm_c, _ra_c, _rb_c, _scale_c);
126     preFcn[0] = _preFcn;
127     condition[0] = _cond;
128     nonTemporal[0] = _nt;
129   }
130
131   // initializes only the first access - no scale for count
132   void set1st(bool _isLoad, bool _isStore,
133               int _imm_s, int _ra_s, int _rb_s,
134               int _imm_c, int _ra_c = -1, int _rb_c = -1,
135               unsigned int _scale_s = 0, int _preFcn = -1,
136               int _cond = -1, bool _nt = false)
137   {
138     nacc = 1;
139     isLoad[0] = _isLoad;
140     isStore[0] = _isStore;
141     start[0] = BPatch_addrSpec_NP(_imm_s, _ra_s, _rb_s, _scale_s);
142     count[0] = BPatch_countSpec_NP(_imm_c, _ra_c, _rb_c);
143     preFcn[0] = _preFcn;
144     condition[0] = _cond;
145     nonTemporal[0] = _nt;
146   }
147
148  public:
149   static BPatch_memoryAccess* const none;
150
151   static BPatch_memoryAccess* init_tables()
152   {
153     initOpCodeInfo();
154     return NULL;
155   }
156
157   // initializes only the first access; #bytes is a constant
158   BPatch_memoryAccess(bool _isLoad, bool _isStore, unsigned int _bytes,
159                       int _imm, int _ra, int _rb, unsigned int _scale = 0,
160                       int _cond = -1, bool _nt = false)
161   {
162     set1st(_isLoad, _isStore, _imm, _ra, _rb, _bytes, -1, -1, _scale, -1, _cond, _nt);
163   }
164
165   // initializes only the first access; #bytes is an expression w/scale
166   BPatch_memoryAccess(bool _isLoad, bool _isStore,
167                       int _imm_s, int _ra_s, int _rb_s, unsigned int _scale_s,
168                       int _imm_c, int _ra_c, int _rb_c, unsigned int _scale_c,
169                       int _cond, bool _nt, int _preFcn = -1)
170   {
171     set1st(_isLoad, _isStore,
172            _imm_s, _ra_s, _rb_s, _scale_s,
173            _imm_c, _ra_c, _rb_c, _scale_c,
174            _preFcn, _cond, _nt);
175   }
176
177   // initializes only the first access; #bytes is an expression
178   BPatch_memoryAccess(bool _isLoad, bool _isStore, bool _isPrefetch,
179                       int _imm_s, int _ra_s, int _rb_s,
180                       int _imm_c, int _ra_c, int _rb_c,
181                       unsigned short _preFcn)
182   {
183     assert(_isPrefetch); // VG(8/13/02): historical reasons...
184     set1st(_isLoad, _isStore, _imm_s, _ra_s, _rb_s, _imm_c, _ra_c, _rb_c, 0, _preFcn);
185   }
186
187   // initializes only the first access; #bytes is an expression & not a prefetch
188   BPatch_memoryAccess(bool _isLoad, bool _isStore,
189                int _imm_s, int _ra_s, int _rb_s,
190                int _imm_c, int _ra_c, int _rb_c)
191   {
192     set1st(_isLoad, _isStore, _imm_s, _ra_s, _rb_s, _imm_c, _ra_c, _rb_c);
193   }
194
195   // sets 2nd access; #bytes is constant
196   void set2nd(bool _isLoad, bool _isStore, unsigned int _bytes,
197               int _imm, int _ra, int _rb, unsigned int _scale = 0)
198   {
199     if(nacc >= 2)
200       return;
201     nacc = 2;
202     isLoad[1] = _isLoad;
203     isStore[1] = _isStore;
204     start[1] = BPatch_addrSpec_NP(_imm, _ra, _rb, _scale);
205     count[1] = BPatch_countSpec_NP(_bytes);
206     preFcn[1] = -1;
207     condition[1] = -1;
208     nonTemporal[1] = false;
209   }
210
211   // sets 2nd access; #bytes is an expression w/scale
212   void set2nd(bool _isLoad, bool _isStore,
213               int _imm_s, int _ra_s, int _rb_s, unsigned int _scale_s,
214               int _imm_c, int _ra_c, int _rb_c, unsigned int _scale_c,
215               int _cond, bool _nt)
216   {
217     if(nacc >= 2)
218       return;
219     nacc = 2;
220     isLoad[1] = _isLoad;
221     isStore[1] = _isStore;
222     start[1] = BPatch_addrSpec_NP(_imm_s, _ra_s, _rb_s, _scale_s);
223     count[1] = BPatch_countSpec_NP(_imm_c, _ra_c, _rb_c, _scale_c);
224     preFcn[1] = -1;
225     condition[1] = _cond;
226     nonTemporal[1] = _nt;
227   }
228
229
230   // initializes both accesses; #bytes is a constant
231   BPatch_memoryAccess(bool _isLoad, bool _isStore, unsigned int _bytes,
232                       int _imm, int _ra, int _rb, unsigned int _scale,
233                       bool _isLoad2, bool _isStore2, unsigned int _bytes2,
234                       int _imm2, int _ra2, int _rb2, unsigned int _scale2)
235   {
236     set1st(_isLoad, _isStore, _imm, _ra, _rb, _bytes, -1, -1, _scale);
237     set2nd(_isLoad2, _isStore2, _bytes2, _imm2, _ra2, _rb2, _scale2);
238   }
239
240   // initializes both accesses; #bytes is an expression & not a prefetch
241   BPatch_memoryAccess(bool _isLoad, bool _isStore,
242                       int _imm_s, int _ra_s, int _rb_s, unsigned int _scale_s,
243                       int _imm_c, int _ra_c, int _rb_c, unsigned int _scale_c,
244                       bool _isLoad2, bool _isStore2,
245                       int _imm2_s, int _ra2_s, int _rb2_s, unsigned int _scale2_s,
246                       int _imm2_c, int _ra2_c, int _rb2_c, unsigned int _scale2_c)
247   {
248     set1st(_isLoad, _isStore, 
249            _imm_s, _ra_s, _rb_s, _scale_s,
250            _imm_c, _ra_c, _rb_c, _scale_c,
251            -1, -1, false);
252     set2nd(_isLoad2, _isStore2,
253            _imm2_s, _ra2_s, _rb2_s, _scale2_s,
254            _imm2_c, _ra2_c, _rb2_c, _scale2_c,
255            -1, false);
256   }
257
258
259   bool equals(const BPatch_memoryAccess* mp) const { return mp ? equals(*mp) : false; }
260
261   bool equals(const BPatch_memoryAccess& rp) const
262   {
263     bool res = nacc == rp.nacc;
264
265     if(!res)
266       return res;
267
268     for(unsigned int i=0; i<nacc; ++i) {
269       res = res &&
270         (isLoad[i] == rp.isLoad[i]) &&
271         (isStore[i] == rp.isStore[i]) &&
272         (start[i].equals(rp.start[i])) &&
273         (count[i].equals(rp.count[i])) &&
274         (preFcn[i] == rp.preFcn[i]) &&
275         (condition[i] == rp.condition[i]) && 
276         (nonTemporal[i] == rp.nonTemporal[i]);
277       if(!res)
278         break;
279     }
280
281     return res;
282   }
283
284   unsigned int getNumberOfAccesses() const { return nacc; }
285   BPatch_addrSpec_NP getStartAddr_NP(int which = 0) const { return start[which]; }
286   BPatch_countSpec_NP getByteCount_NP(int which = 0) const { return count[which]; }
287   bool isALoad_NP(int which = 0) const { return isLoad[which]; }
288   bool isAStore_NP(int which = 0) const { return isStore[which]; }
289   bool isAPrefetch_NP(int which = 0) const { return preFcn[which] >= 0; }
290   bool isConditional_NP(int which = 0) const { return condition[which] >= 0; }
291   bool isNonTemporal_NP(int which = 0) const { return nonTemporal[which]; }
292   int  prefetchType_NP(int which = 0) const { return preFcn[which]; }
293   int  conditionCode_NP(int which = 0) const { return condition[which]; }
294
295 };
296
297 #endif