blob: 8f6814d57992bc5bf1da4057a34e7364c5c0e3b1 [file] [log] [blame]
sewardjd20c8852005-01-20 20:04:07 +00001
2/*---------------------------------------------------------------*/
3/*--- ---*/
4/*--- This file (guest-amd64/gdefs.h) is ---*/
sewardjdbcfae72005-08-02 11:14:04 +00005/*--- Copyright (C) OpenWorks LLP. All rights reserved. ---*/
sewardjd20c8852005-01-20 20:04:07 +00006/*--- ---*/
7/*---------------------------------------------------------------*/
8
9/*
10 This file is part of LibVEX, a library for dynamic binary
11 instrumentation and translation.
12
sewardj7bd6ffe2005-08-03 16:07:36 +000013 Copyright (C) 2004-2005 OpenWorks LLP. All rights reserved.
sewardjd20c8852005-01-20 20:04:07 +000014
sewardj7bd6ffe2005-08-03 16:07:36 +000015 This library is made available under a dual licensing scheme.
sewardjd20c8852005-01-20 20:04:07 +000016
sewardj7bd6ffe2005-08-03 16:07:36 +000017 If you link LibVEX against other code all of which is itself
18 licensed under the GNU General Public License, version 2 dated June
19 1991 ("GPL v2"), then you may use LibVEX under the terms of the GPL
20 v2, as appearing in the file LICENSE.GPL. If the file LICENSE.GPL
21 is missing, you can obtain a copy of the GPL v2 from the Free
22 Software Foundation Inc., 51 Franklin St, Fifth Floor, Boston, MA
23 02110-1301, USA.
24
25 For any other uses of LibVEX, you must first obtain a commercial
26 license from OpenWorks LLP. Please contact info@open-works.co.uk
27 for information about commercial licensing.
28
29 This software is provided by OpenWorks LLP "as is" and any express
30 or implied warranties, including, but not limited to, the implied
31 warranties of merchantability and fitness for a particular purpose
32 are disclaimed. In no event shall OpenWorks LLP be liable for any
33 direct, indirect, incidental, special, exemplary, or consequential
34 damages (including, but not limited to, procurement of substitute
35 goods or services; loss of use, data, or profits; or business
36 interruption) however caused and on any theory of liability,
37 whether in contract, strict liability, or tort (including
38 negligence or otherwise) arising in any way out of the use of this
39 software, even if advised of the possibility of such damage.
sewardjd20c8852005-01-20 20:04:07 +000040
41 Neither the names of the U.S. Department of Energy nor the
42 University of California nor the names of its contributors may be
43 used to endorse or promote products derived from this software
44 without prior written permission.
sewardjd20c8852005-01-20 20:04:07 +000045*/
46
47/* Only to be used within the guest-amd64 directory. */
48
49#ifndef __LIBVEX_GUEST_AMD64_DEFS_H
50#define __LIBVEX_GUEST_AMD64_DEFS_H
51
52
53/*---------------------------------------------------------*/
54/*--- amd64 to IR conversion ---*/
55/*---------------------------------------------------------*/
56
sewardj9e6491a2005-07-02 19:24:10 +000057/* Convert one amd64 insn to IR. See the type DisOneInstrFn in
58 bb_to_IR.h. */
sewardjd20c8852005-01-20 20:04:07 +000059extern
sewardj9e6491a2005-07-02 19:24:10 +000060DisResult disInstr_AMD64 ( IRBB* irbb,
61 Bool put_IP,
62 Bool (*resteerOkFn) ( Addr64 ),
63 UChar* guest_code,
64 Long delta,
65 Addr64 guest_IP,
66 VexArchInfo* archinfo,
67 Bool host_bigendian );
sewardjd20c8852005-01-20 20:04:07 +000068
69/* Used by the optimiser to specialise calls to helpers. */
70extern
sewardj58277842005-02-07 03:11:17 +000071IRExpr* guest_amd64_spechelper ( HChar* function_name,
sewardjd20c8852005-01-20 20:04:07 +000072 IRExpr** args );
73
74/* Describes to the optimiser which part of the guest state require
75 precise memory exceptions. This is logically part of the guest
76 state description. */
77extern
78Bool guest_amd64_state_requires_precise_mem_exns ( Int, Int );
79
80extern
81VexGuestLayout amd64guest_layout;
82
83
84/*---------------------------------------------------------*/
85/*--- amd64 guest helpers ---*/
86/*---------------------------------------------------------*/
87
88/* --- CLEAN HELPERS --- */
89
90extern ULong amd64g_calculate_rflags_all (
91 ULong cc_op,
92 ULong cc_dep1, ULong cc_dep2, ULong cc_ndep
93 );
94
sewardjdf0e0022005-01-25 15:48:43 +000095extern ULong amd64g_calculate_rflags_c (
sewardjd20c8852005-01-20 20:04:07 +000096 ULong cc_op,
97 ULong cc_dep1, ULong cc_dep2, ULong cc_ndep
98 );
99
100extern ULong amd64g_calculate_condition (
101 ULong/*AMD64Condcode*/ cond,
102 ULong cc_op,
103 ULong cc_dep1, ULong cc_dep2, ULong cc_ndep
104 );
105
sewardj4f9847d2005-07-25 11:58:34 +0000106extern ULong amd64g_calculate_FXAM ( ULong tag, ULong dbl );
sewardjd20c8852005-01-20 20:04:07 +0000107
sewardj112b0992005-07-23 13:19:32 +0000108extern ULong amd64g_calculate_RCR (
109 ULong arg, ULong rot_amt, ULong rflags_in, Long sz
110 );
sewardjd20c8852005-01-20 20:04:07 +0000111
sewardj5e205372005-05-09 02:57:08 +0000112extern ULong amd64g_check_fldcw ( ULong fpucw );
sewardjd20c8852005-01-20 20:04:07 +0000113
sewardj5e205372005-05-09 02:57:08 +0000114extern ULong amd64g_create_fpucw ( ULong fpround );
sewardjd20c8852005-01-20 20:04:07 +0000115
sewardjbcbb9de2005-03-27 02:22:32 +0000116extern ULong amd64g_check_ldmxcsr ( ULong mxcsr );
sewardjd20c8852005-01-20 20:04:07 +0000117
sewardjbcbb9de2005-03-27 02:22:32 +0000118extern ULong amd64g_create_mxcsr ( ULong sseround );
sewardjd20c8852005-01-20 20:04:07 +0000119
sewardj4017a3b2005-06-13 12:17:27 +0000120extern VexEmWarn amd64g_dirtyhelper_FLDENV ( VexGuestAMD64State*, HWord );
121
122extern void amd64g_dirtyhelper_FSTENV ( VexGuestAMD64State*, HWord );
123
sewardjd20c8852005-01-20 20:04:07 +0000124/* Translate a guest virtual_addr into a guest linear address by
125 consulting the supplied LDT/GDT structures. Their representation
126 must be as specified in pub/libvex_guest_amd64.h. To indicate a
127 translation failure, 1<<32 is returned. On success, the lower 32
128 bits of the returned result indicate the linear address.
129*/
130//extern
131//ULong amd64g_use_seg_selector ( HWord ldt, HWord gdt,
132// UInt seg_selector, UInt virtual_addr );
133
134extern ULong amd64g_calculate_mmx_pmaddwd ( ULong, ULong );
135extern ULong amd64g_calculate_mmx_psadbw ( ULong, ULong );
sewardja7ba8c42005-05-10 20:08:34 +0000136extern ULong amd64g_calculate_mmx_pmovmskb ( ULong );
137extern ULong amd64g_calculate_sse_pmovmskb ( ULong w64hi, ULong w64lo );
sewardjd20c8852005-01-20 20:04:07 +0000138
139
140/* --- DIRTY HELPERS --- */
141
sewardj924215b2005-03-26 21:50:31 +0000142extern ULong amd64g_loadF80le ( ULong/*addr*/ );
sewardjd20c8852005-01-20 20:04:07 +0000143
sewardj924215b2005-03-26 21:50:31 +0000144extern void amd64g_storeF80le ( ULong/*addr*/, ULong/*data*/ );
sewardjd20c8852005-01-20 20:04:07 +0000145
sewardjd0a12df2005-02-10 02:07:43 +0000146extern void amd64g_dirtyhelper_CPUID ( VexGuestAMD64State* st );
147
sewardjd20c8852005-01-20 20:04:07 +0000148//extern void amd64g_dirtyhelper_CPUID_sse0 ( VexGuestAMD64State* );
149//extern void amd64g_dirtyhelper_CPUID_sse1 ( VexGuestAMD64State* );
150//extern void amd64g_dirtyhelper_CPUID_sse2 ( VexGuestAMD64State* );
151
152//extern void amd64g_dirtyhelper_FSAVE ( VexGuestAMD64State*, HWord );
153
154//extern void amd64g_dirtyhelper_FINIT ( VexGuestAMD64State* );
155
156//extern VexEmWarn
157// amd64g_dirtyhelper_FRSTOR ( VexGuestAMD64State*, HWord );
158
159//extern void amd64g_dirtyhelper_FSTENV ( VexGuestAMD64State*, HWord );
160
161//extern VexEmWarn
162// amd64g_dirtyhelper_FLDENV ( VexGuestAMD64State*, HWord );
163
164//extern void amd64g_dirtyhelper_FXSAVE ( VexGuestAMD64State*, HWord );
165
166
167/*---------------------------------------------------------*/
168/*--- Condition code stuff ---*/
169/*---------------------------------------------------------*/
170
171/* rflags masks */
172#define AMD64G_CC_SHIFT_O 11
173#define AMD64G_CC_SHIFT_S 7
174#define AMD64G_CC_SHIFT_Z 6
175#define AMD64G_CC_SHIFT_A 4
176#define AMD64G_CC_SHIFT_C 0
177#define AMD64G_CC_SHIFT_P 2
178
179#define AMD64G_CC_MASK_O (1 << AMD64G_CC_SHIFT_O)
180#define AMD64G_CC_MASK_S (1 << AMD64G_CC_SHIFT_S)
181#define AMD64G_CC_MASK_Z (1 << AMD64G_CC_SHIFT_Z)
182#define AMD64G_CC_MASK_A (1 << AMD64G_CC_SHIFT_A)
183#define AMD64G_CC_MASK_C (1 << AMD64G_CC_SHIFT_C)
184#define AMD64G_CC_MASK_P (1 << AMD64G_CC_SHIFT_P)
185
186/* FPU flag masks */
sewardj4f9847d2005-07-25 11:58:34 +0000187#define AMD64G_FC_SHIFT_C3 14
188#define AMD64G_FC_SHIFT_C2 10
189#define AMD64G_FC_SHIFT_C1 9
190#define AMD64G_FC_SHIFT_C0 8
191
192#define AMD64G_FC_MASK_C3 (1 << AMD64G_FC_SHIFT_C3)
193#define AMD64G_FC_MASK_C2 (1 << AMD64G_FC_SHIFT_C2)
194#define AMD64G_FC_MASK_C1 (1 << AMD64G_FC_SHIFT_C1)
195#define AMD64G_FC_MASK_C0 (1 << AMD64G_FC_SHIFT_C0)
196
sewardjd20c8852005-01-20 20:04:07 +0000197
198/* %RFLAGS thunk descriptors. A four-word thunk is used to record
199 details of the most recent flag-setting operation, so the flags can
200 be computed later if needed. It is possible to do this a little
201 more efficiently using a 3-word thunk, but that makes it impossible
202 to describe the flag data dependencies sufficiently accurately for
203 Memcheck. Hence 4 words are used, with minimal loss of efficiency.
204
205 The four words are:
206
207 CC_OP, which describes the operation.
208
209 CC_DEP1 and CC_DEP2. These are arguments to the operation.
210 We want Memcheck to believe that the resulting flags are
211 data-dependent on both CC_DEP1 and CC_DEP2, hence the
212 name DEP.
213
214 CC_NDEP. This is a 3rd argument to the operation which is
215 sometimes needed. We arrange things so that Memcheck does
216 not believe the resulting flags are data-dependent on CC_NDEP
217 ("not dependent").
218
219 To make Memcheck believe that (the definedness of) the encoded
220 flags depends only on (the definedness of) CC_DEP1 and CC_DEP2
221 requires two things:
222
223 (1) In the guest state layout info (amd64guest_layout), CC_OP and
224 CC_NDEP are marked as always defined.
225
226 (2) When passing the thunk components to an evaluation function
227 (calculate_condition, calculate_eflags, calculate_eflags_c) the
228 IRCallee's mcx_mask must be set so as to exclude from
229 consideration all passed args except CC_DEP1 and CC_DEP2.
230
231 Strictly speaking only (2) is necessary for correctness. However,
232 (1) helps efficiency in that since (2) means we never ask about the
233 definedness of CC_OP or CC_NDEP, we may as well not even bother to
234 track their definedness.
235
236 When building the thunk, it is always necessary to write words into
237 CC_DEP1 and CC_DEP2, even if those args are not used given the
238 CC_OP field (eg, CC_DEP2 is not used if CC_OP is CC_LOGIC1/2/4).
239 This is important because otherwise Memcheck could give false
240 positives as it does not understand the relationship between the
241 CC_OP field and CC_DEP1 and CC_DEP2, and so believes that the
242 definedness of the stored flags always depends on both CC_DEP1 and
243 CC_DEP2.
244
245 However, it is only necessary to set CC_NDEP when the CC_OP value
246 requires it, because Memcheck ignores CC_NDEP, and the evaluation
247 functions do understand the CC_OP fields and will only examine
248 CC_NDEP for suitable values of CC_OP.
249
250 A summary of the field usages is:
251
252 Operation DEP1 DEP2 NDEP
253 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
254
255 add/sub/mul first arg second arg unused
256
257 adc/sbb first arg (second arg)
258 XOR old_carry old_carry
259
260 and/or/xor result zero unused
261
262 inc/dec result zero old_carry
263
264 shl/shr/sar result subshifted- unused
265 result
266
267 rol/ror result zero old_flags
268
269 copy old_flags zero unused.
270
271
272 Therefore Memcheck will believe the following:
273
274 * add/sub/mul -- definedness of result flags depends on definedness
275 of both args.
276
277 * adc/sbb -- definedness of result flags depends on definedness of
278 both args and definedness of the old C flag. Because only two
279 DEP fields are available, the old C flag is XOR'd into the second
280 arg so that Memcheck sees the data dependency on it. That means
281 the NDEP field must contain a second copy of the old C flag
282 so that the evaluation functions can correctly recover the second
283 arg.
284
285 * and/or/xor are straightforward -- definedness of result flags
286 depends on definedness of result value.
287
288 * inc/dec -- definedness of result flags depends only on
289 definedness of result. This isn't really true -- it also depends
290 on the old C flag. However, we don't want Memcheck to see that,
291 and so the old C flag must be passed in NDEP and not in DEP2.
292 It's inconceivable that a compiler would generate code that puts
293 the C flag in an undefined state, then does an inc/dec, which
294 leaves C unchanged, and then makes a conditional jump/move based
295 on C. So our fiction seems a good approximation.
296
297 * shl/shr/sar -- straightforward, again, definedness of result
298 flags depends on definedness of result value. The subshifted
299 value (value shifted one less) is also needed, but its
300 definedness is the same as the definedness of the shifted value.
301
302 * rol/ror -- these only set O and C, and leave A Z C P alone.
303 However it seems prudent (as per inc/dec) to say the definedness
304 of all resulting flags depends on the definedness of the result,
305 hence the old flags must go in as NDEP and not DEP2.
306
307 * rcl/rcr are too difficult to do in-line, and so are done by a
308 helper function. They are not part of this scheme. The helper
309 function takes the value to be rotated, the rotate amount and the
310 old flags, and returns the new flags and the rotated value.
311 Since the helper's mcx_mask does not have any set bits, Memcheck
312 will lazily propagate undefinedness from any of the 3 args into
313 both results (flags and actual value).
314*/
315enum {
sewardjdf0e0022005-01-25 15:48:43 +0000316 AMD64G_CC_OP_COPY=0, /* DEP1 = current flags, DEP2 = 0, NDEP = unused */
sewardjd20c8852005-01-20 20:04:07 +0000317 /* just copy DEP1 to output */
318
319 AMD64G_CC_OP_ADDB, /* 1 */
320 AMD64G_CC_OP_ADDW, /* 2 DEP1 = argL, DEP2 = argR, NDEP = unused */
321 AMD64G_CC_OP_ADDL, /* 3 */
sewardjdf0e0022005-01-25 15:48:43 +0000322 AMD64G_CC_OP_ADDQ, /* 4 */
sewardjd20c8852005-01-20 20:04:07 +0000323
sewardjdf0e0022005-01-25 15:48:43 +0000324 AMD64G_CC_OP_SUBB, /* 5 */
325 AMD64G_CC_OP_SUBW, /* 6 DEP1 = argL, DEP2 = argR, NDEP = unused */
326 AMD64G_CC_OP_SUBL, /* 7 */
327 AMD64G_CC_OP_SUBQ, /* 8 */
sewardjd20c8852005-01-20 20:04:07 +0000328
sewardjdf0e0022005-01-25 15:48:43 +0000329 AMD64G_CC_OP_ADCB, /* 9 */
330 AMD64G_CC_OP_ADCW, /* 10 DEP1 = argL, DEP2 = argR ^ oldCarry, NDEP = oldCarry */
331 AMD64G_CC_OP_ADCL, /* 11 */
332 AMD64G_CC_OP_ADCQ, /* 12 */
sewardjd20c8852005-01-20 20:04:07 +0000333
sewardjdf0e0022005-01-25 15:48:43 +0000334 AMD64G_CC_OP_SBBB, /* 13 */
335 AMD64G_CC_OP_SBBW, /* 14 DEP1 = argL, DEP2 = argR ^ oldCarry, NDEP = oldCarry */
336 AMD64G_CC_OP_SBBL, /* 15 */
337 AMD64G_CC_OP_SBBQ, /* 16 */
sewardjd20c8852005-01-20 20:04:07 +0000338
sewardjdf0e0022005-01-25 15:48:43 +0000339 AMD64G_CC_OP_LOGICB, /* 17 */
340 AMD64G_CC_OP_LOGICW, /* 18 DEP1 = result, DEP2 = 0, NDEP = unused */
341 AMD64G_CC_OP_LOGICL, /* 19 */
342 AMD64G_CC_OP_LOGICQ, /* 20 */
sewardjd20c8852005-01-20 20:04:07 +0000343
sewardjdf0e0022005-01-25 15:48:43 +0000344 AMD64G_CC_OP_INCB, /* 21 */
345 AMD64G_CC_OP_INCW, /* 22 DEP1 = result, DEP2 = 0, NDEP = oldCarry (0 or 1) */
346 AMD64G_CC_OP_INCL, /* 23 */
347 AMD64G_CC_OP_INCQ, /* 24 */
sewardjd20c8852005-01-20 20:04:07 +0000348
sewardjdf0e0022005-01-25 15:48:43 +0000349 AMD64G_CC_OP_DECB, /* 25 */
350 AMD64G_CC_OP_DECW, /* 26 DEP1 = result, DEP2 = 0, NDEP = oldCarry (0 or 1) */
351 AMD64G_CC_OP_DECL, /* 27 */
352 AMD64G_CC_OP_DECQ, /* 28 */
sewardjd20c8852005-01-20 20:04:07 +0000353
sewardjdf0e0022005-01-25 15:48:43 +0000354 AMD64G_CC_OP_SHLB, /* 29 DEP1 = res, DEP2 = res', NDEP = unused */
355 AMD64G_CC_OP_SHLW, /* 30 where res' is like res but shifted one bit less */
356 AMD64G_CC_OP_SHLL, /* 31 */
357 AMD64G_CC_OP_SHLQ, /* 32 */
sewardjd20c8852005-01-20 20:04:07 +0000358
sewardjdf0e0022005-01-25 15:48:43 +0000359 AMD64G_CC_OP_SHRB, /* 33 DEP1 = res, DEP2 = res', NDEP = unused */
360 AMD64G_CC_OP_SHRW, /* 34 where res' is like res but shifted one bit less */
361 AMD64G_CC_OP_SHRL, /* 35 */
362 AMD64G_CC_OP_SHRQ, /* 36 */
sewardjd20c8852005-01-20 20:04:07 +0000363
sewardjdf0e0022005-01-25 15:48:43 +0000364 AMD64G_CC_OP_ROLB, /* 37 */
365 AMD64G_CC_OP_ROLW, /* 38 DEP1 = res, DEP2 = 0, NDEP = old flags */
366 AMD64G_CC_OP_ROLL, /* 39 */
367 AMD64G_CC_OP_ROLQ, /* 40 */
sewardjd20c8852005-01-20 20:04:07 +0000368
sewardjdf0e0022005-01-25 15:48:43 +0000369 AMD64G_CC_OP_RORB, /* 41 */
370 AMD64G_CC_OP_RORW, /* 42 DEP1 = res, DEP2 = 0, NDEP = old flags */
371 AMD64G_CC_OP_RORL, /* 43 */
372 AMD64G_CC_OP_RORQ, /* 44 */
sewardjd20c8852005-01-20 20:04:07 +0000373
sewardjdf0e0022005-01-25 15:48:43 +0000374 AMD64G_CC_OP_UMULB, /* 45 */
375 AMD64G_CC_OP_UMULW, /* 46 DEP1 = argL, DEP2 = argR, NDEP = unused */
376 AMD64G_CC_OP_UMULL, /* 47 */
sewardj32b2bbe2005-01-28 00:50:10 +0000377 AMD64G_CC_OP_UMULQ, /* 48 */
sewardjd20c8852005-01-20 20:04:07 +0000378
sewardj32b2bbe2005-01-28 00:50:10 +0000379 AMD64G_CC_OP_SMULB, /* 49 */
380 AMD64G_CC_OP_SMULW, /* 50 DEP1 = argL, DEP2 = argR, NDEP = unused */
381 AMD64G_CC_OP_SMULL, /* 51 */
382 AMD64G_CC_OP_SMULQ, /* 52 */
sewardjd20c8852005-01-20 20:04:07 +0000383
384 AMD64G_CC_OP_NUMBER
385};
386
387typedef
388 enum {
389 AMD64CondO = 0, /* overflow */
390 AMD64CondNO = 1, /* no overflow */
391
392 AMD64CondB = 2, /* below */
393 AMD64CondNB = 3, /* not below */
394
395 AMD64CondZ = 4, /* zero */
396 AMD64CondNZ = 5, /* not zero */
397
398 AMD64CondBE = 6, /* below or equal */
399 AMD64CondNBE = 7, /* not below or equal */
400
401 AMD64CondS = 8, /* negative */
402 AMD64CondNS = 9, /* not negative */
403
404 AMD64CondP = 10, /* parity even */
405 AMD64CondNP = 11, /* not parity even */
406
407 AMD64CondL = 12, /* jump less */
408 AMD64CondNL = 13, /* not less */
409
410 AMD64CondLE = 14, /* less or equal */
411 AMD64CondNLE = 15, /* not less or equal */
412
413 AMD64CondAlways = 16 /* HACK */
414 }
415 AMD64Condcode;
416
417#endif /* ndef __LIBVEX_GUEST_AMD64_DEFS_H */
418
419/*---------------------------------------------------------------*/
420/*--- end guest-amd64/gdefs.h ---*/
421/*---------------------------------------------------------------*/