]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/valgrind/src/valgrind-3.6.0-svn/VEX/priv/guest_amd64_defs.h
40ed37f1434cd679a8ae9fe0c8ad84012aa025ec
[l4.git] / l4 / pkg / valgrind / src / valgrind-3.6.0-svn / VEX / priv / guest_amd64_defs.h
1
2 /*---------------------------------------------------------------*/
3 /*--- begin                                guest_amd64_defs.h ---*/
4 /*---------------------------------------------------------------*/
5
6 /*
7    This file is part of Valgrind, a dynamic binary instrumentation
8    framework.
9
10    Copyright (C) 2004-2010 OpenWorks LLP
11       info@open-works.net
12
13    This program is free software; you can redistribute it and/or
14    modify it under the terms of the GNU General Public License as
15    published by the Free Software Foundation; either version 2 of the
16    License, or (at your option) any later version.
17
18    This program is distributed in the hope that it will be useful, but
19    WITHOUT ANY WARRANTY; without even the implied warranty of
20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21    General Public License for more details.
22
23    You should have received a copy of the GNU General Public License
24    along with this program; if not, write to the Free Software
25    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26    02110-1301, USA.
27
28    The GNU General Public License is contained in the file COPYING.
29
30    Neither the names of the U.S. Department of Energy nor the
31    University of California nor the names of its contributors may be
32    used to endorse or promote products derived from this software
33    without prior written permission.
34 */
35
36 /* Only to be used within the guest-amd64 directory. */
37
38 #ifndef __VEX_GUEST_AMD64_DEFS_H
39 #define __VEX_GUEST_AMD64_DEFS_H
40
41
42 /*---------------------------------------------------------*/
43 /*--- amd64 to IR conversion                            ---*/
44 /*---------------------------------------------------------*/
45
46 /* Convert one amd64 insn to IR.  See the type DisOneInstrFn in
47    bb_to_IR.h. */
48 extern
49 DisResult disInstr_AMD64 ( IRSB*        irbb,
50                            Bool         put_IP,
51                            Bool         (*resteerOkFn) ( void*, Addr64 ),
52                            Bool         resteerCisOk,
53                            void*        callback_opaque,
54                            UChar*       guest_code,
55                            Long         delta,
56                            Addr64       guest_IP,
57                            VexArch      guest_arch,
58                            VexArchInfo* archinfo,
59                            VexAbiInfo*  abiinfo,
60                            Bool         host_bigendian );
61
62 /* Used by the optimiser to specialise calls to helpers. */
63 extern
64 IRExpr* guest_amd64_spechelper ( HChar* function_name,
65                                  IRExpr** args );
66
67 /* Describes to the optimiser which part of the guest state require
68    precise memory exceptions.  This is logically part of the guest
69    state description. */
70 extern 
71 Bool guest_amd64_state_requires_precise_mem_exns ( Int, Int );
72
73 extern
74 VexGuestLayout amd64guest_layout;
75
76
77 /*---------------------------------------------------------*/
78 /*--- amd64 guest helpers                               ---*/
79 /*---------------------------------------------------------*/
80
81 /* --- CLEAN HELPERS --- */
82
83 extern ULong amd64g_calculate_rflags_all ( 
84                 ULong cc_op, 
85                 ULong cc_dep1, ULong cc_dep2, ULong cc_ndep 
86              );
87
88 extern ULong amd64g_calculate_rflags_c ( 
89                 ULong cc_op, 
90                 ULong cc_dep1, ULong cc_dep2, ULong cc_ndep 
91              );
92
93 extern ULong amd64g_calculate_condition ( 
94                 ULong/*AMD64Condcode*/ cond, 
95                 ULong cc_op, 
96                 ULong cc_dep1, ULong cc_dep2, ULong cc_ndep 
97              );
98
99 extern ULong amd64g_calculate_FXAM ( ULong tag, ULong dbl );
100
101 extern ULong amd64g_calculate_RCR  ( 
102                 ULong arg, ULong rot_amt, ULong rflags_in, Long sz 
103              );
104
105 extern ULong amd64g_calculate_RCL  ( 
106                 ULong arg, ULong rot_amt, ULong rflags_in, Long sz 
107              );
108
109 extern ULong amd64g_check_fldcw ( ULong fpucw );
110
111 extern ULong amd64g_create_fpucw ( ULong fpround );
112
113 extern ULong amd64g_check_ldmxcsr ( ULong mxcsr );
114
115 extern ULong amd64g_create_mxcsr ( ULong sseround );
116
117 extern VexEmWarn amd64g_dirtyhelper_FLDENV ( VexGuestAMD64State*, HWord );
118
119 extern void amd64g_dirtyhelper_FSTENV ( VexGuestAMD64State*, HWord );
120
121 /* Translate a guest virtual_addr into a guest linear address by
122    consulting the supplied LDT/GDT structures.  Their representation
123    must be as specified in pub/libvex_guest_amd64.h.  To indicate a
124    translation failure, 1<<32 is returned.  On success, the lower 32
125    bits of the returned result indicate the linear address.  
126 */
127 //extern 
128 //ULong amd64g_use_seg_selector ( HWord ldt, HWord gdt, 
129 //                              UInt seg_selector, UInt virtual_addr );
130
131 extern ULong amd64g_calculate_mmx_pmaddwd  ( ULong, ULong );
132 extern ULong amd64g_calculate_mmx_psadbw   ( ULong, ULong );
133 extern ULong amd64g_calculate_mmx_pmovmskb ( ULong );
134 extern ULong amd64g_calculate_sse_pmovmskb ( ULong w64hi, ULong w64lo );
135
136
137 /* --- DIRTY HELPERS --- */
138
139 extern ULong amd64g_dirtyhelper_loadF80le  ( ULong/*addr*/ );
140
141 extern void  amd64g_dirtyhelper_storeF80le ( ULong/*addr*/, ULong/*data*/ );
142
143 extern void  amd64g_dirtyhelper_CPUID_baseline ( VexGuestAMD64State* st );
144 extern void  amd64g_dirtyhelper_CPUID_sse3_and_cx16 ( VexGuestAMD64State* st );
145
146 extern void  amd64g_dirtyhelper_FINIT ( VexGuestAMD64State* );
147
148 extern void  amd64g_dirtyhelper_FXSAVE ( VexGuestAMD64State*, HWord );
149
150 extern ULong amd64g_dirtyhelper_RDTSC ( void );
151
152 extern ULong amd64g_dirtyhelper_IN  ( ULong portno, ULong sz/*1,2 or 4*/ );
153 extern void  amd64g_dirtyhelper_OUT ( ULong portno, ULong data, 
154                                       ULong sz/*1,2 or 4*/ );
155
156 //extern void  amd64g_dirtyhelper_CPUID_sse0 ( VexGuestAMD64State* );
157 //extern void  amd64g_dirtyhelper_CPUID_sse1 ( VexGuestAMD64State* );
158 //extern void  amd64g_dirtyhelper_CPUID_sse2 ( VexGuestAMD64State* );
159
160 //extern void  amd64g_dirtyhelper_FSAVE ( VexGuestAMD64State*, HWord );
161
162 //extern VexEmWarn
163 //            amd64g_dirtyhelper_FRSTOR ( VexGuestAMD64State*, HWord );
164
165 //extern void amd64g_dirtyhelper_FSTENV ( VexGuestAMD64State*, HWord );
166
167 //extern VexEmWarn 
168 //            amd64g_dirtyhelper_FLDENV ( VexGuestAMD64State*, HWord );
169
170
171
172 /*---------------------------------------------------------*/
173 /*--- Condition code stuff                              ---*/
174 /*---------------------------------------------------------*/
175
176 /* rflags masks */
177 #define AMD64G_CC_SHIFT_O   11
178 #define AMD64G_CC_SHIFT_S   7
179 #define AMD64G_CC_SHIFT_Z   6
180 #define AMD64G_CC_SHIFT_A   4
181 #define AMD64G_CC_SHIFT_C   0
182 #define AMD64G_CC_SHIFT_P   2
183
184 #define AMD64G_CC_MASK_O    (1ULL << AMD64G_CC_SHIFT_O)
185 #define AMD64G_CC_MASK_S    (1ULL << AMD64G_CC_SHIFT_S)
186 #define AMD64G_CC_MASK_Z    (1ULL << AMD64G_CC_SHIFT_Z)
187 #define AMD64G_CC_MASK_A    (1ULL << AMD64G_CC_SHIFT_A)
188 #define AMD64G_CC_MASK_C    (1ULL << AMD64G_CC_SHIFT_C)
189 #define AMD64G_CC_MASK_P    (1ULL << AMD64G_CC_SHIFT_P)
190
191 /* FPU flag masks */
192 #define AMD64G_FC_SHIFT_C3   14
193 #define AMD64G_FC_SHIFT_C2   10
194 #define AMD64G_FC_SHIFT_C1   9
195 #define AMD64G_FC_SHIFT_C0   8
196
197 #define AMD64G_FC_MASK_C3    (1ULL << AMD64G_FC_SHIFT_C3)
198 #define AMD64G_FC_MASK_C2    (1ULL << AMD64G_FC_SHIFT_C2)
199 #define AMD64G_FC_MASK_C1    (1ULL << AMD64G_FC_SHIFT_C1)
200 #define AMD64G_FC_MASK_C0    (1ULL << AMD64G_FC_SHIFT_C0)
201
202
203 /* %RFLAGS thunk descriptors.  A four-word thunk is used to record
204    details of the most recent flag-setting operation, so the flags can
205    be computed later if needed.  It is possible to do this a little
206    more efficiently using a 3-word thunk, but that makes it impossible
207    to describe the flag data dependencies sufficiently accurately for
208    Memcheck.  Hence 4 words are used, with minimal loss of efficiency.
209
210    The four words are:
211
212       CC_OP, which describes the operation.
213
214       CC_DEP1 and CC_DEP2.  These are arguments to the operation.
215          We want Memcheck to believe that the resulting flags are
216          data-dependent on both CC_DEP1 and CC_DEP2, hence the 
217          name DEP.
218
219       CC_NDEP.  This is a 3rd argument to the operation which is
220          sometimes needed.  We arrange things so that Memcheck does
221          not believe the resulting flags are data-dependent on CC_NDEP
222          ("not dependent").
223
224    To make Memcheck believe that (the definedness of) the encoded
225    flags depends only on (the definedness of) CC_DEP1 and CC_DEP2
226    requires two things:
227
228    (1) In the guest state layout info (amd64guest_layout), CC_OP and
229        CC_NDEP are marked as always defined.
230
231    (2) When passing the thunk components to an evaluation function
232        (calculate_condition, calculate_eflags, calculate_eflags_c) the
233        IRCallee's mcx_mask must be set so as to exclude from
234        consideration all passed args except CC_DEP1 and CC_DEP2.
235
236    Strictly speaking only (2) is necessary for correctness.  However,
237    (1) helps efficiency in that since (2) means we never ask about the
238    definedness of CC_OP or CC_NDEP, we may as well not even bother to
239    track their definedness.
240
241    When building the thunk, it is always necessary to write words into
242    CC_DEP1 and CC_DEP2, even if those args are not used given the
243    CC_OP field (eg, CC_DEP2 is not used if CC_OP is CC_LOGIC1/2/4).
244    This is important because otherwise Memcheck could give false
245    positives as it does not understand the relationship between the
246    CC_OP field and CC_DEP1 and CC_DEP2, and so believes that the 
247    definedness of the stored flags always depends on both CC_DEP1 and
248    CC_DEP2.
249
250    However, it is only necessary to set CC_NDEP when the CC_OP value
251    requires it, because Memcheck ignores CC_NDEP, and the evaluation
252    functions do understand the CC_OP fields and will only examine
253    CC_NDEP for suitable values of CC_OP.
254
255    A summary of the field usages is:
256
257    Operation          DEP1               DEP2               NDEP
258    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
259
260    add/sub/mul        first arg          second arg         unused
261
262    adc/sbb            first arg          (second arg)
263                                          XOR old_carry      old_carry
264
265    and/or/xor         result             zero               unused
266
267    inc/dec            result             zero               old_carry
268
269    shl/shr/sar        result             subshifted-        unused
270                                          result
271
272    rol/ror            result             zero               old_flags
273
274    copy               old_flags          zero               unused.
275
276
277    Therefore Memcheck will believe the following:
278
279    * add/sub/mul -- definedness of result flags depends on definedness
280      of both args.
281
282    * adc/sbb -- definedness of result flags depends on definedness of
283      both args and definedness of the old C flag.  Because only two
284      DEP fields are available, the old C flag is XOR'd into the second
285      arg so that Memcheck sees the data dependency on it.  That means
286      the NDEP field must contain a second copy of the old C flag
287      so that the evaluation functions can correctly recover the second
288      arg.
289
290    * and/or/xor are straightforward -- definedness of result flags
291      depends on definedness of result value.
292
293    * inc/dec -- definedness of result flags depends only on
294      definedness of result.  This isn't really true -- it also depends
295      on the old C flag.  However, we don't want Memcheck to see that,
296      and so the old C flag must be passed in NDEP and not in DEP2.
297      It's inconceivable that a compiler would generate code that puts
298      the C flag in an undefined state, then does an inc/dec, which
299      leaves C unchanged, and then makes a conditional jump/move based
300      on C.  So our fiction seems a good approximation.
301
302    * shl/shr/sar -- straightforward, again, definedness of result
303      flags depends on definedness of result value.  The subshifted
304      value (value shifted one less) is also needed, but its
305      definedness is the same as the definedness of the shifted value.
306
307    * rol/ror -- these only set O and C, and leave A Z C P alone.
308      However it seems prudent (as per inc/dec) to say the definedness
309      of all resulting flags depends on the definedness of the result,
310      hence the old flags must go in as NDEP and not DEP2.
311
312    * rcl/rcr are too difficult to do in-line, and so are done by a
313      helper function.  They are not part of this scheme.  The helper
314      function takes the value to be rotated, the rotate amount and the
315      old flags, and returns the new flags and the rotated value.
316      Since the helper's mcx_mask does not have any set bits, Memcheck
317      will lazily propagate undefinedness from any of the 3 args into 
318      both results (flags and actual value).
319 */
320 enum {
321     AMD64G_CC_OP_COPY=0,  /* DEP1 = current flags, DEP2 = 0, NDEP = unused */
322                           /* just copy DEP1 to output */
323
324     AMD64G_CC_OP_ADDB,    /* 1 */
325     AMD64G_CC_OP_ADDW,    /* 2 DEP1 = argL, DEP2 = argR, NDEP = unused */
326     AMD64G_CC_OP_ADDL,    /* 3 */
327     AMD64G_CC_OP_ADDQ,    /* 4 */
328
329     AMD64G_CC_OP_SUBB,    /* 5 */
330     AMD64G_CC_OP_SUBW,    /* 6 DEP1 = argL, DEP2 = argR, NDEP = unused */
331     AMD64G_CC_OP_SUBL,    /* 7 */
332     AMD64G_CC_OP_SUBQ,    /* 8 */
333
334     AMD64G_CC_OP_ADCB,    /* 9 */
335     AMD64G_CC_OP_ADCW,    /* 10 DEP1 = argL, DEP2 = argR ^ oldCarry, NDEP = oldCarry */
336     AMD64G_CC_OP_ADCL,    /* 11 */
337     AMD64G_CC_OP_ADCQ,    /* 12 */
338
339     AMD64G_CC_OP_SBBB,    /* 13 */
340     AMD64G_CC_OP_SBBW,    /* 14 DEP1 = argL, DEP2 = argR ^ oldCarry, NDEP = oldCarry */
341     AMD64G_CC_OP_SBBL,    /* 15 */
342     AMD64G_CC_OP_SBBQ,    /* 16 */
343
344     AMD64G_CC_OP_LOGICB,  /* 17 */
345     AMD64G_CC_OP_LOGICW,  /* 18 DEP1 = result, DEP2 = 0, NDEP = unused */
346     AMD64G_CC_OP_LOGICL,  /* 19 */
347     AMD64G_CC_OP_LOGICQ,  /* 20 */
348
349     AMD64G_CC_OP_INCB,    /* 21 */
350     AMD64G_CC_OP_INCW,    /* 22 DEP1 = result, DEP2 = 0, NDEP = oldCarry (0 or 1) */
351     AMD64G_CC_OP_INCL,    /* 23 */
352     AMD64G_CC_OP_INCQ,    /* 24 */
353
354     AMD64G_CC_OP_DECB,    /* 25 */
355     AMD64G_CC_OP_DECW,    /* 26 DEP1 = result, DEP2 = 0, NDEP = oldCarry (0 or 1) */
356     AMD64G_CC_OP_DECL,    /* 27 */
357     AMD64G_CC_OP_DECQ,    /* 28 */
358
359     AMD64G_CC_OP_SHLB,    /* 29 DEP1 = res, DEP2 = res', NDEP = unused */
360     AMD64G_CC_OP_SHLW,    /* 30 where res' is like res but shifted one bit less */
361     AMD64G_CC_OP_SHLL,    /* 31 */
362     AMD64G_CC_OP_SHLQ,    /* 32 */
363
364     AMD64G_CC_OP_SHRB,    /* 33 DEP1 = res, DEP2 = res', NDEP = unused */
365     AMD64G_CC_OP_SHRW,    /* 34 where res' is like res but shifted one bit less */
366     AMD64G_CC_OP_SHRL,    /* 35 */
367     AMD64G_CC_OP_SHRQ,    /* 36 */
368
369     AMD64G_CC_OP_ROLB,    /* 37 */
370     AMD64G_CC_OP_ROLW,    /* 38 DEP1 = res, DEP2 = 0, NDEP = old flags */
371     AMD64G_CC_OP_ROLL,    /* 39 */
372     AMD64G_CC_OP_ROLQ,    /* 40 */
373
374     AMD64G_CC_OP_RORB,    /* 41 */
375     AMD64G_CC_OP_RORW,    /* 42 DEP1 = res, DEP2 = 0, NDEP = old flags */
376     AMD64G_CC_OP_RORL,    /* 43 */
377     AMD64G_CC_OP_RORQ,    /* 44 */
378
379     AMD64G_CC_OP_UMULB,   /* 45 */
380     AMD64G_CC_OP_UMULW,   /* 46 DEP1 = argL, DEP2 = argR, NDEP = unused */
381     AMD64G_CC_OP_UMULL,   /* 47 */
382     AMD64G_CC_OP_UMULQ,   /* 48 */
383
384     AMD64G_CC_OP_SMULB,   /* 49 */
385     AMD64G_CC_OP_SMULW,   /* 50 DEP1 = argL, DEP2 = argR, NDEP = unused */
386     AMD64G_CC_OP_SMULL,   /* 51 */
387     AMD64G_CC_OP_SMULQ,   /* 52 */
388
389     AMD64G_CC_OP_NUMBER
390 };
391
392 typedef
393    enum {
394       AMD64CondO      = 0,  /* overflow           */
395       AMD64CondNO     = 1,  /* no overflow        */
396
397       AMD64CondB      = 2,  /* below              */
398       AMD64CondNB     = 3,  /* not below          */
399
400       AMD64CondZ      = 4,  /* zero               */
401       AMD64CondNZ     = 5,  /* not zero           */
402
403       AMD64CondBE     = 6,  /* below or equal     */
404       AMD64CondNBE    = 7,  /* not below or equal */
405
406       AMD64CondS      = 8,  /* negative           */
407       AMD64CondNS     = 9,  /* not negative       */
408
409       AMD64CondP      = 10, /* parity even        */
410       AMD64CondNP     = 11, /* not parity even    */
411
412       AMD64CondL      = 12, /* jump less          */
413       AMD64CondNL     = 13, /* not less           */
414
415       AMD64CondLE     = 14, /* less or equal      */
416       AMD64CondNLE    = 15, /* not less or equal  */
417
418       AMD64CondAlways = 16  /* HACK */
419    }
420    AMD64Condcode;
421
422 #endif /* ndef __VEX_GUEST_AMD64_DEFS_H */
423
424 /*---------------------------------------------------------------*/
425 /*--- end                                  guest_amd64_defs.h ---*/
426 /*---------------------------------------------------------------*/