2 /*---------------------------------------------------------------*/
3 /*--- begin guest_amd64_defs.h ---*/
4 /*---------------------------------------------------------------*/
7 This file is part of Valgrind, a dynamic binary instrumentation
10 Copyright (C) 2004-2010 OpenWorks LLP
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.
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.
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
28 The GNU General Public License is contained in the file COPYING.
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.
36 /* Only to be used within the guest-amd64 directory. */
38 #ifndef __VEX_GUEST_AMD64_DEFS_H
39 #define __VEX_GUEST_AMD64_DEFS_H
42 /*---------------------------------------------------------*/
43 /*--- amd64 to IR conversion ---*/
44 /*---------------------------------------------------------*/
46 /* Convert one amd64 insn to IR. See the type DisOneInstrFn in
49 DisResult disInstr_AMD64 ( IRSB* irbb,
51 Bool (*resteerOkFn) ( void*, Addr64 ),
53 void* callback_opaque,
58 VexArchInfo* archinfo,
60 Bool host_bigendian );
62 /* Used by the optimiser to specialise calls to helpers. */
64 IRExpr* guest_amd64_spechelper ( HChar* function_name,
67 /* Describes to the optimiser which part of the guest state require
68 precise memory exceptions. This is logically part of the guest
71 Bool guest_amd64_state_requires_precise_mem_exns ( Int, Int );
74 VexGuestLayout amd64guest_layout;
77 /*---------------------------------------------------------*/
78 /*--- amd64 guest helpers ---*/
79 /*---------------------------------------------------------*/
81 /* --- CLEAN HELPERS --- */
83 extern ULong amd64g_calculate_rflags_all (
85 ULong cc_dep1, ULong cc_dep2, ULong cc_ndep
88 extern ULong amd64g_calculate_rflags_c (
90 ULong cc_dep1, ULong cc_dep2, ULong cc_ndep
93 extern ULong amd64g_calculate_condition (
94 ULong/*AMD64Condcode*/ cond,
96 ULong cc_dep1, ULong cc_dep2, ULong cc_ndep
99 extern ULong amd64g_calculate_FXAM ( ULong tag, ULong dbl );
101 extern ULong amd64g_calculate_RCR (
102 ULong arg, ULong rot_amt, ULong rflags_in, Long sz
105 extern ULong amd64g_calculate_RCL (
106 ULong arg, ULong rot_amt, ULong rflags_in, Long sz
109 extern ULong amd64g_check_fldcw ( ULong fpucw );
111 extern ULong amd64g_create_fpucw ( ULong fpround );
113 extern ULong amd64g_check_ldmxcsr ( ULong mxcsr );
115 extern ULong amd64g_create_mxcsr ( ULong sseround );
117 extern VexEmWarn amd64g_dirtyhelper_FLDENV ( VexGuestAMD64State*, HWord );
119 extern void amd64g_dirtyhelper_FSTENV ( VexGuestAMD64State*, HWord );
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.
128 //ULong amd64g_use_seg_selector ( HWord ldt, HWord gdt,
129 // UInt seg_selector, UInt virtual_addr );
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 );
137 /* --- DIRTY HELPERS --- */
139 extern ULong amd64g_dirtyhelper_loadF80le ( ULong/*addr*/ );
141 extern void amd64g_dirtyhelper_storeF80le ( ULong/*addr*/, ULong/*data*/ );
143 extern void amd64g_dirtyhelper_CPUID_baseline ( VexGuestAMD64State* st );
144 extern void amd64g_dirtyhelper_CPUID_sse3_and_cx16 ( VexGuestAMD64State* st );
146 extern void amd64g_dirtyhelper_FINIT ( VexGuestAMD64State* );
148 extern void amd64g_dirtyhelper_FXSAVE ( VexGuestAMD64State*, HWord );
150 extern ULong amd64g_dirtyhelper_RDTSC ( void );
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*/ );
156 //extern void amd64g_dirtyhelper_CPUID_sse0 ( VexGuestAMD64State* );
157 //extern void amd64g_dirtyhelper_CPUID_sse1 ( VexGuestAMD64State* );
158 //extern void amd64g_dirtyhelper_CPUID_sse2 ( VexGuestAMD64State* );
160 //extern void amd64g_dirtyhelper_FSAVE ( VexGuestAMD64State*, HWord );
163 // amd64g_dirtyhelper_FRSTOR ( VexGuestAMD64State*, HWord );
165 //extern void amd64g_dirtyhelper_FSTENV ( VexGuestAMD64State*, HWord );
168 // amd64g_dirtyhelper_FLDENV ( VexGuestAMD64State*, HWord );
172 /*---------------------------------------------------------*/
173 /*--- Condition code stuff ---*/
174 /*---------------------------------------------------------*/
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
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)
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
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)
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.
212 CC_OP, which describes the operation.
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
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
224 To make Memcheck believe that (the definedness of) the encoded
225 flags depends only on (the definedness of) CC_DEP1 and CC_DEP2
228 (1) In the guest state layout info (amd64guest_layout), CC_OP and
229 CC_NDEP are marked as always defined.
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.
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.
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
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.
255 A summary of the field usages is:
257 Operation DEP1 DEP2 NDEP
258 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
260 add/sub/mul first arg second arg unused
262 adc/sbb first arg (second arg)
263 XOR old_carry old_carry
265 and/or/xor result zero unused
267 inc/dec result zero old_carry
269 shl/shr/sar result subshifted- unused
272 rol/ror result zero old_flags
274 copy old_flags zero unused.
277 Therefore Memcheck will believe the following:
279 * add/sub/mul -- definedness of result flags depends on definedness
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
290 * and/or/xor are straightforward -- definedness of result flags
291 depends on definedness of result value.
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.
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.
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.
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).
321 AMD64G_CC_OP_COPY=0, /* DEP1 = current flags, DEP2 = 0, NDEP = unused */
322 /* just copy DEP1 to output */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
394 AMD64CondO = 0, /* overflow */
395 AMD64CondNO = 1, /* no overflow */
397 AMD64CondB = 2, /* below */
398 AMD64CondNB = 3, /* not below */
400 AMD64CondZ = 4, /* zero */
401 AMD64CondNZ = 5, /* not zero */
403 AMD64CondBE = 6, /* below or equal */
404 AMD64CondNBE = 7, /* not below or equal */
406 AMD64CondS = 8, /* negative */
407 AMD64CondNS = 9, /* not negative */
409 AMD64CondP = 10, /* parity even */
410 AMD64CondNP = 11, /* not parity even */
412 AMD64CondL = 12, /* jump less */
413 AMD64CondNL = 13, /* not less */
415 AMD64CondLE = 14, /* less or equal */
416 AMD64CondNLE = 15, /* not less or equal */
418 AMD64CondAlways = 16 /* HACK */
422 #endif /* ndef __VEX_GUEST_AMD64_DEFS_H */
424 /*---------------------------------------------------------------*/
425 /*--- end guest_amd64_defs.h ---*/
426 /*---------------------------------------------------------------*/