2 /*---------------------------------------------------------------*/
3 /*--- begin guest_x86_helpers.c ---*/
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 #include "libvex_basictypes.h"
37 #include "libvex_emwarn.h"
38 #include "libvex_guest_x86.h"
39 #include "libvex_ir.h"
42 #include "main_util.h"
43 #include "guest_generic_bb_to_IR.h"
44 #include "guest_x86_defs.h"
45 #include "guest_generic_x87.h"
48 /* This file contains helper functions for x86 guest code.
49 Calls to these functions are generated by the back end.
50 These calls are of course in the host machine code and
51 this file will be compiled to host machine code, so that
54 Only change the signatures of these helper functions very
55 carefully. If you change the signature here, you'll have to change
56 the parameters passed to it in the IR calls constructed by
59 The convention used is that all functions called from generated
60 code are named x86g_<something>, and any function whose name lacks
61 that prefix is not called from generated code. Note that some
62 LibVEX_* functions can however be called by VEX's client, but that
63 is not the same as calling them from VEX-generated code.
67 /* Set to 1 to get detailed profiling info about use of the flag
69 #define PROFILE_EFLAGS 0
72 /*---------------------------------------------------------------*/
73 /*--- %eflags run-time helpers. ---*/
74 /*---------------------------------------------------------------*/
76 static const UChar parity_table[256] = {
77 X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
78 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
79 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
80 X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
81 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
82 X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
83 X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
84 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
85 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
86 X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
87 X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
88 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
89 X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
90 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
91 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
92 X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
93 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
94 X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
95 X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
96 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
97 X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
98 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
99 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
100 X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
101 X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
102 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
103 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
104 X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
105 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
106 X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
107 X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
108 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
111 /* generalised left-shifter */
112 inline static Int lshift ( Int x, Int n )
120 /* identity on ULong */
121 static inline ULong idULong ( ULong x )
127 #define PREAMBLE(__data_bits) \
128 /* const */ UInt DATA_MASK \
129 = __data_bits==8 ? 0xFF \
130 : (__data_bits==16 ? 0xFFFF \
132 /* const */ UInt SIGN_MASK = 1 << (__data_bits - 1); \
133 /* const */ UInt CC_DEP1 = cc_dep1_formal; \
134 /* const */ UInt CC_DEP2 = cc_dep2_formal; \
135 /* const */ UInt CC_NDEP = cc_ndep_formal; \
136 /* Four bogus assignments, which hopefully gcc can */ \
137 /* optimise away, and which stop it complaining about */ \
138 /* unused variables. */ \
139 SIGN_MASK = SIGN_MASK; \
140 DATA_MASK = DATA_MASK; \
145 /*-------------------------------------------------------------*/
147 #define ACTIONS_ADD(DATA_BITS,DATA_UTYPE) \
149 PREAMBLE(DATA_BITS); \
150 { Int cf, pf, af, zf, sf, of; \
151 Int argL, argR, res; \
155 cf = (DATA_UTYPE)res < (DATA_UTYPE)argL; \
156 pf = parity_table[(UChar)res]; \
157 af = (res ^ argL ^ argR) & 0x10; \
158 zf = ((DATA_UTYPE)res == 0) << 6; \
159 sf = lshift(res, 8 - DATA_BITS) & 0x80; \
160 of = lshift((argL ^ argR ^ -1) & (argL ^ res), \
161 12 - DATA_BITS) & X86G_CC_MASK_O; \
162 return cf | pf | af | zf | sf | of; \
166 /*-------------------------------------------------------------*/
168 #define ACTIONS_SUB(DATA_BITS,DATA_UTYPE) \
170 PREAMBLE(DATA_BITS); \
171 { Int cf, pf, af, zf, sf, of; \
172 Int argL, argR, res; \
176 cf = (DATA_UTYPE)argL < (DATA_UTYPE)argR; \
177 pf = parity_table[(UChar)res]; \
178 af = (res ^ argL ^ argR) & 0x10; \
179 zf = ((DATA_UTYPE)res == 0) << 6; \
180 sf = lshift(res, 8 - DATA_BITS) & 0x80; \
181 of = lshift((argL ^ argR) & (argL ^ res), \
182 12 - DATA_BITS) & X86G_CC_MASK_O; \
183 return cf | pf | af | zf | sf | of; \
187 /*-------------------------------------------------------------*/
189 #define ACTIONS_ADC(DATA_BITS,DATA_UTYPE) \
191 PREAMBLE(DATA_BITS); \
192 { Int cf, pf, af, zf, sf, of; \
193 Int argL, argR, oldC, res; \
194 oldC = CC_NDEP & X86G_CC_MASK_C; \
196 argR = CC_DEP2 ^ oldC; \
197 res = (argL + argR) + oldC; \
199 cf = (DATA_UTYPE)res <= (DATA_UTYPE)argL; \
201 cf = (DATA_UTYPE)res < (DATA_UTYPE)argL; \
202 pf = parity_table[(UChar)res]; \
203 af = (res ^ argL ^ argR) & 0x10; \
204 zf = ((DATA_UTYPE)res == 0) << 6; \
205 sf = lshift(res, 8 - DATA_BITS) & 0x80; \
206 of = lshift((argL ^ argR ^ -1) & (argL ^ res), \
207 12 - DATA_BITS) & X86G_CC_MASK_O; \
208 return cf | pf | af | zf | sf | of; \
212 /*-------------------------------------------------------------*/
214 #define ACTIONS_SBB(DATA_BITS,DATA_UTYPE) \
216 PREAMBLE(DATA_BITS); \
217 { Int cf, pf, af, zf, sf, of; \
218 Int argL, argR, oldC, res; \
219 oldC = CC_NDEP & X86G_CC_MASK_C; \
221 argR = CC_DEP2 ^ oldC; \
222 res = (argL - argR) - oldC; \
224 cf = (DATA_UTYPE)argL <= (DATA_UTYPE)argR; \
226 cf = (DATA_UTYPE)argL < (DATA_UTYPE)argR; \
227 pf = parity_table[(UChar)res]; \
228 af = (res ^ argL ^ argR) & 0x10; \
229 zf = ((DATA_UTYPE)res == 0) << 6; \
230 sf = lshift(res, 8 - DATA_BITS) & 0x80; \
231 of = lshift((argL ^ argR) & (argL ^ res), \
232 12 - DATA_BITS) & X86G_CC_MASK_O; \
233 return cf | pf | af | zf | sf | of; \
237 /*-------------------------------------------------------------*/
239 #define ACTIONS_LOGIC(DATA_BITS,DATA_UTYPE) \
241 PREAMBLE(DATA_BITS); \
242 { Int cf, pf, af, zf, sf, of; \
244 pf = parity_table[(UChar)CC_DEP1]; \
246 zf = ((DATA_UTYPE)CC_DEP1 == 0) << 6; \
247 sf = lshift(CC_DEP1, 8 - DATA_BITS) & 0x80; \
249 return cf | pf | af | zf | sf | of; \
253 /*-------------------------------------------------------------*/
255 #define ACTIONS_INC(DATA_BITS,DATA_UTYPE) \
257 PREAMBLE(DATA_BITS); \
258 { Int cf, pf, af, zf, sf, of; \
259 Int argL, argR, res; \
263 cf = CC_NDEP & X86G_CC_MASK_C; \
264 pf = parity_table[(UChar)res]; \
265 af = (res ^ argL ^ argR) & 0x10; \
266 zf = ((DATA_UTYPE)res == 0) << 6; \
267 sf = lshift(res, 8 - DATA_BITS) & 0x80; \
268 of = ((res & DATA_MASK) == SIGN_MASK) << 11; \
269 return cf | pf | af | zf | sf | of; \
273 /*-------------------------------------------------------------*/
275 #define ACTIONS_DEC(DATA_BITS,DATA_UTYPE) \
277 PREAMBLE(DATA_BITS); \
278 { Int cf, pf, af, zf, sf, of; \
279 Int argL, argR, res; \
283 cf = CC_NDEP & X86G_CC_MASK_C; \
284 pf = parity_table[(UChar)res]; \
285 af = (res ^ argL ^ argR) & 0x10; \
286 zf = ((DATA_UTYPE)res == 0) << 6; \
287 sf = lshift(res, 8 - DATA_BITS) & 0x80; \
288 of = ((res & DATA_MASK) \
289 == ((UInt)SIGN_MASK - 1)) << 11; \
290 return cf | pf | af | zf | sf | of; \
294 /*-------------------------------------------------------------*/
296 #define ACTIONS_SHL(DATA_BITS,DATA_UTYPE) \
298 PREAMBLE(DATA_BITS); \
299 { Int cf, pf, af, zf, sf, of; \
300 cf = (CC_DEP2 >> (DATA_BITS - 1)) & X86G_CC_MASK_C; \
301 pf = parity_table[(UChar)CC_DEP1]; \
302 af = 0; /* undefined */ \
303 zf = ((DATA_UTYPE)CC_DEP1 == 0) << 6; \
304 sf = lshift(CC_DEP1, 8 - DATA_BITS) & 0x80; \
305 /* of is defined if shift count == 1 */ \
306 of = lshift(CC_DEP2 ^ CC_DEP1, 12 - DATA_BITS) \
308 return cf | pf | af | zf | sf | of; \
312 /*-------------------------------------------------------------*/
314 #define ACTIONS_SHR(DATA_BITS,DATA_UTYPE) \
316 PREAMBLE(DATA_BITS); \
317 { Int cf, pf, af, zf, sf, of; \
319 pf = parity_table[(UChar)CC_DEP1]; \
320 af = 0; /* undefined */ \
321 zf = ((DATA_UTYPE)CC_DEP1 == 0) << 6; \
322 sf = lshift(CC_DEP1, 8 - DATA_BITS) & 0x80; \
323 /* of is defined if shift count == 1 */ \
324 of = lshift(CC_DEP2 ^ CC_DEP1, 12 - DATA_BITS) \
326 return cf | pf | af | zf | sf | of; \
330 /*-------------------------------------------------------------*/
332 /* ROL: cf' = lsb(result). of' = msb(result) ^ lsb(result). */
333 /* DEP1 = result, NDEP = old flags */
334 #define ACTIONS_ROL(DATA_BITS,DATA_UTYPE) \
336 PREAMBLE(DATA_BITS); \
338 = (CC_NDEP & ~(X86G_CC_MASK_O | X86G_CC_MASK_C)) \
339 | (X86G_CC_MASK_C & CC_DEP1) \
340 | (X86G_CC_MASK_O & (lshift(CC_DEP1, \
342 ^ lshift(CC_DEP1, 11))); \
347 /*-------------------------------------------------------------*/
349 /* ROR: cf' = msb(result). of' = msb(result) ^ msb-1(result). */
350 /* DEP1 = result, NDEP = old flags */
351 #define ACTIONS_ROR(DATA_BITS,DATA_UTYPE) \
353 PREAMBLE(DATA_BITS); \
355 = (CC_NDEP & ~(X86G_CC_MASK_O | X86G_CC_MASK_C)) \
356 | (X86G_CC_MASK_C & (CC_DEP1 >> (DATA_BITS-1))) \
357 | (X86G_CC_MASK_O & (lshift(CC_DEP1, \
359 ^ lshift(CC_DEP1, 11-(DATA_BITS-1)+1))); \
364 /*-------------------------------------------------------------*/
366 #define ACTIONS_UMUL(DATA_BITS, DATA_UTYPE, NARROWtoU, \
367 DATA_U2TYPE, NARROWto2U) \
369 PREAMBLE(DATA_BITS); \
370 { Int cf, pf, af, zf, sf, of; \
373 = NARROWtoU( ((DATA_UTYPE)CC_DEP1) \
374 * ((DATA_UTYPE)CC_DEP2) ); \
377 ((DATA_U2TYPE)((DATA_UTYPE)CC_DEP1)) \
378 * ((DATA_U2TYPE)((DATA_UTYPE)CC_DEP2)) ); \
379 hi = NARROWtoU(rr >>/*u*/ DATA_BITS); \
381 pf = parity_table[(UChar)lo]; \
382 af = 0; /* undefined */ \
383 zf = (lo == 0) << 6; \
384 sf = lshift(lo, 8 - DATA_BITS) & 0x80; \
386 return cf | pf | af | zf | sf | of; \
390 /*-------------------------------------------------------------*/
392 #define ACTIONS_SMUL(DATA_BITS, DATA_STYPE, NARROWtoS, \
393 DATA_S2TYPE, NARROWto2S) \
395 PREAMBLE(DATA_BITS); \
396 { Int cf, pf, af, zf, sf, of; \
399 = NARROWtoS( ((DATA_STYPE)CC_DEP1) \
400 * ((DATA_STYPE)CC_DEP2) ); \
403 ((DATA_S2TYPE)((DATA_STYPE)CC_DEP1)) \
404 * ((DATA_S2TYPE)((DATA_STYPE)CC_DEP2)) ); \
405 hi = NARROWtoS(rr >>/*s*/ DATA_BITS); \
406 cf = (hi != (lo >>/*s*/ (DATA_BITS-1))); \
407 pf = parity_table[(UChar)lo]; \
408 af = 0; /* undefined */ \
409 zf = (lo == 0) << 6; \
410 sf = lshift(lo, 8 - DATA_BITS) & 0x80; \
412 return cf | pf | af | zf | sf | of; \
419 static Bool initted = False;
421 /* C flag, fast route */
422 static UInt tabc_fast[X86G_CC_OP_NUMBER];
423 /* C flag, slow route */
424 static UInt tabc_slow[X86G_CC_OP_NUMBER];
425 /* table for calculate_cond */
426 static UInt tab_cond[X86G_CC_OP_NUMBER][16];
427 /* total entry counts for calc_all, calc_c, calc_cond. */
428 static UInt n_calc_all = 0;
429 static UInt n_calc_c = 0;
430 static UInt n_calc_cond = 0;
432 #define SHOW_COUNTS_NOW (0 == (0x3FFFFF & (n_calc_all+n_calc_c+n_calc_cond)))
435 static void showCounts ( void )
439 vex_printf("\nTotal calls: calc_all=%u calc_cond=%u calc_c=%u\n",
440 n_calc_all, n_calc_cond, n_calc_c);
442 vex_printf(" cSLOW cFAST O NO B NB Z NZ BE NBE"
443 " S NS P NP L NL LE NLE\n");
444 vex_printf(" -----------------------------------------------------"
445 "----------------------------------------\n");
446 for (op = 0; op < X86G_CC_OP_NUMBER; op++) {
449 if (op > 0 && (op-1) % 3 == 0)
451 if (op > 0 && (op-1) % 3 == 1)
453 if (op > 0 && (op-1) % 3 == 2)
456 vex_printf("%2d%c: ", op, ch);
457 vex_printf("%6u ", tabc_slow[op]);
458 vex_printf("%6u ", tabc_fast[op]);
459 for (co = 0; co < 16; co++) {
460 Int n = tab_cond[op][co];
462 vex_printf(" %3dK", n / 1000);
465 vex_printf(" %3d ", n );
475 static void initCounts ( void )
479 for (op = 0; op < X86G_CC_OP_NUMBER; op++) {
480 tabc_fast[op] = tabc_slow[op] = 0;
481 for (co = 0; co < 16; co++)
482 tab_cond[op][co] = 0;
486 #endif /* PROFILE_EFLAGS */
489 /* CALLED FROM GENERATED CODE: CLEAN HELPER */
490 /* Calculate all the 6 flags from the supplied thunk parameters.
491 Worker function, not directly called from generated code. */
493 UInt x86g_calculate_eflags_all_WRK ( UInt cc_op,
496 UInt cc_ndep_formal )
499 case X86G_CC_OP_COPY:
500 return cc_dep1_formal
501 & (X86G_CC_MASK_O | X86G_CC_MASK_S | X86G_CC_MASK_Z
502 | X86G_CC_MASK_A | X86G_CC_MASK_C | X86G_CC_MASK_P);
504 case X86G_CC_OP_ADDB: ACTIONS_ADD( 8, UChar );
505 case X86G_CC_OP_ADDW: ACTIONS_ADD( 16, UShort );
506 case X86G_CC_OP_ADDL: ACTIONS_ADD( 32, UInt );
508 case X86G_CC_OP_ADCB: ACTIONS_ADC( 8, UChar );
509 case X86G_CC_OP_ADCW: ACTIONS_ADC( 16, UShort );
510 case X86G_CC_OP_ADCL: ACTIONS_ADC( 32, UInt );
512 case X86G_CC_OP_SUBB: ACTIONS_SUB( 8, UChar );
513 case X86G_CC_OP_SUBW: ACTIONS_SUB( 16, UShort );
514 case X86G_CC_OP_SUBL: ACTIONS_SUB( 32, UInt );
516 case X86G_CC_OP_SBBB: ACTIONS_SBB( 8, UChar );
517 case X86G_CC_OP_SBBW: ACTIONS_SBB( 16, UShort );
518 case X86G_CC_OP_SBBL: ACTIONS_SBB( 32, UInt );
520 case X86G_CC_OP_LOGICB: ACTIONS_LOGIC( 8, UChar );
521 case X86G_CC_OP_LOGICW: ACTIONS_LOGIC( 16, UShort );
522 case X86G_CC_OP_LOGICL: ACTIONS_LOGIC( 32, UInt );
524 case X86G_CC_OP_INCB: ACTIONS_INC( 8, UChar );
525 case X86G_CC_OP_INCW: ACTIONS_INC( 16, UShort );
526 case X86G_CC_OP_INCL: ACTIONS_INC( 32, UInt );
528 case X86G_CC_OP_DECB: ACTIONS_DEC( 8, UChar );
529 case X86G_CC_OP_DECW: ACTIONS_DEC( 16, UShort );
530 case X86G_CC_OP_DECL: ACTIONS_DEC( 32, UInt );
532 case X86G_CC_OP_SHLB: ACTIONS_SHL( 8, UChar );
533 case X86G_CC_OP_SHLW: ACTIONS_SHL( 16, UShort );
534 case X86G_CC_OP_SHLL: ACTIONS_SHL( 32, UInt );
536 case X86G_CC_OP_SHRB: ACTIONS_SHR( 8, UChar );
537 case X86G_CC_OP_SHRW: ACTIONS_SHR( 16, UShort );
538 case X86G_CC_OP_SHRL: ACTIONS_SHR( 32, UInt );
540 case X86G_CC_OP_ROLB: ACTIONS_ROL( 8, UChar );
541 case X86G_CC_OP_ROLW: ACTIONS_ROL( 16, UShort );
542 case X86G_CC_OP_ROLL: ACTIONS_ROL( 32, UInt );
544 case X86G_CC_OP_RORB: ACTIONS_ROR( 8, UChar );
545 case X86G_CC_OP_RORW: ACTIONS_ROR( 16, UShort );
546 case X86G_CC_OP_RORL: ACTIONS_ROR( 32, UInt );
548 case X86G_CC_OP_UMULB: ACTIONS_UMUL( 8, UChar, toUChar,
550 case X86G_CC_OP_UMULW: ACTIONS_UMUL( 16, UShort, toUShort,
552 case X86G_CC_OP_UMULL: ACTIONS_UMUL( 32, UInt, toUInt,
555 case X86G_CC_OP_SMULB: ACTIONS_SMUL( 8, Char, toUChar,
557 case X86G_CC_OP_SMULW: ACTIONS_SMUL( 16, Short, toUShort,
559 case X86G_CC_OP_SMULL: ACTIONS_SMUL( 32, Int, toUInt,
563 /* shouldn't really make these calls from generated code */
564 vex_printf("x86g_calculate_eflags_all_WRK(X86)"
565 "( %u, 0x%x, 0x%x, 0x%x )\n",
566 cc_op, cc_dep1_formal, cc_dep2_formal, cc_ndep_formal );
567 vpanic("x86g_calculate_eflags_all_WRK(X86)");
572 /* CALLED FROM GENERATED CODE: CLEAN HELPER */
573 /* Calculate all the 6 flags from the supplied thunk parameters. */
574 UInt x86g_calculate_eflags_all ( UInt cc_op,
580 if (!initted) initCounts();
582 if (SHOW_COUNTS_NOW) showCounts();
585 x86g_calculate_eflags_all_WRK ( cc_op, cc_dep1, cc_dep2, cc_ndep );
589 /* CALLED FROM GENERATED CODE: CLEAN HELPER */
590 /* Calculate just the carry flag from the supplied thunk parameters. */
591 __attribute((regparm(3)))
592 UInt x86g_calculate_eflags_c ( UInt cc_op,
598 if (!initted) initCounts();
601 if (SHOW_COUNTS_NOW) showCounts();
604 /* Fast-case some common ones. */
606 case X86G_CC_OP_LOGICL:
607 case X86G_CC_OP_LOGICW:
608 case X86G_CC_OP_LOGICB:
610 case X86G_CC_OP_SUBL:
611 return ((UInt)cc_dep1) < ((UInt)cc_dep2)
612 ? X86G_CC_MASK_C : 0;
613 case X86G_CC_OP_SUBW:
614 return ((UInt)(cc_dep1 & 0xFFFF)) < ((UInt)(cc_dep2 & 0xFFFF))
615 ? X86G_CC_MASK_C : 0;
616 case X86G_CC_OP_SUBB:
617 return ((UInt)(cc_dep1 & 0xFF)) < ((UInt)(cc_dep2 & 0xFF))
618 ? X86G_CC_MASK_C : 0;
619 case X86G_CC_OP_INCL:
620 case X86G_CC_OP_DECL:
621 return cc_ndep & X86G_CC_MASK_C;
631 return x86g_calculate_eflags_all_WRK(cc_op,cc_dep1,cc_dep2,cc_ndep)
636 /* CALLED FROM GENERATED CODE: CLEAN HELPER */
638 UInt x86g_calculate_condition ( UInt/*X86Condcode*/ cond,
644 UInt eflags = x86g_calculate_eflags_all_WRK(cc_op, cc_dep1,
650 if (!initted) initCounts();
651 tab_cond[cc_op][cond]++;
653 if (SHOW_COUNTS_NOW) showCounts();
658 case X86CondO: /* OF == 1 */
659 of = eflags >> X86G_CC_SHIFT_O;
660 return 1 & (inv ^ of);
663 case X86CondZ: /* ZF == 1 */
664 zf = eflags >> X86G_CC_SHIFT_Z;
665 return 1 & (inv ^ zf);
668 case X86CondB: /* CF == 1 */
669 cf = eflags >> X86G_CC_SHIFT_C;
670 return 1 & (inv ^ cf);
674 case X86CondBE: /* (CF or ZF) == 1 */
675 cf = eflags >> X86G_CC_SHIFT_C;
676 zf = eflags >> X86G_CC_SHIFT_Z;
677 return 1 & (inv ^ (cf | zf));
681 case X86CondS: /* SF == 1 */
682 sf = eflags >> X86G_CC_SHIFT_S;
683 return 1 & (inv ^ sf);
686 case X86CondP: /* PF == 1 */
687 pf = eflags >> X86G_CC_SHIFT_P;
688 return 1 & (inv ^ pf);
691 case X86CondL: /* (SF xor OF) == 1 */
692 sf = eflags >> X86G_CC_SHIFT_S;
693 of = eflags >> X86G_CC_SHIFT_O;
694 return 1 & (inv ^ (sf ^ of));
698 case X86CondLE: /* ((SF xor OF) or ZF) == 1 */
699 sf = eflags >> X86G_CC_SHIFT_S;
700 of = eflags >> X86G_CC_SHIFT_O;
701 zf = eflags >> X86G_CC_SHIFT_Z;
702 return 1 & (inv ^ ((sf ^ of) | zf));
706 /* shouldn't really make these calls from generated code */
707 vex_printf("x86g_calculate_condition( %u, %u, 0x%x, 0x%x, 0x%x )\n",
708 cond, cc_op, cc_dep1, cc_dep2, cc_ndep );
709 vpanic("x86g_calculate_condition");
714 /* VISIBLE TO LIBVEX CLIENT */
715 UInt LibVEX_GuestX86_get_eflags ( /*IN*/VexGuestX86State* vex_state )
717 UInt eflags = x86g_calculate_eflags_all_WRK(
718 vex_state->guest_CC_OP,
719 vex_state->guest_CC_DEP1,
720 vex_state->guest_CC_DEP2,
721 vex_state->guest_CC_NDEP
723 UInt dflag = vex_state->guest_DFLAG;
724 vassert(dflag == 1 || dflag == 0xFFFFFFFF);
725 if (dflag == 0xFFFFFFFF)
727 if (vex_state->guest_IDFLAG == 1)
729 if (vex_state->guest_ACFLAG == 1)
735 /* VISIBLE TO LIBVEX CLIENT */
737 LibVEX_GuestX86_put_eflag_c ( UInt new_carry_flag,
738 /*MOD*/VexGuestX86State* vex_state )
740 UInt oszacp = x86g_calculate_eflags_all_WRK(
741 vex_state->guest_CC_OP,
742 vex_state->guest_CC_DEP1,
743 vex_state->guest_CC_DEP2,
744 vex_state->guest_CC_NDEP
746 if (new_carry_flag & 1) {
747 oszacp |= X86G_CC_MASK_C;
749 oszacp &= ~X86G_CC_MASK_C;
751 vex_state->guest_CC_OP = X86G_CC_OP_COPY;
752 vex_state->guest_CC_DEP1 = oszacp;
753 vex_state->guest_CC_DEP2 = 0;
754 vex_state->guest_CC_NDEP = 0;
758 /*---------------------------------------------------------------*/
759 /*--- %eflags translation-time function specialisers. ---*/
760 /*--- These help iropt specialise calls the above run-time ---*/
761 /*--- %eflags functions. ---*/
762 /*---------------------------------------------------------------*/
764 /* Used by the optimiser to try specialisations. Returns an
765 equivalent expression, or NULL if none. */
767 static inline Bool isU32 ( IRExpr* e, UInt n )
770 toBool( e->tag == Iex_Const
771 && e->Iex.Const.con->tag == Ico_U32
772 && e->Iex.Const.con->Ico.U32 == n );
775 IRExpr* guest_x86_spechelper ( HChar* function_name,
778 # define unop(_op,_a1) IRExpr_Unop((_op),(_a1))
779 # define binop(_op,_a1,_a2) IRExpr_Binop((_op),(_a1),(_a2))
780 # define mkU32(_n) IRExpr_Const(IRConst_U32(_n))
781 # define mkU8(_n) IRExpr_Const(IRConst_U8(_n))
784 for (i = 0; args[i]; i++)
787 vex_printf("spec request:\n");
788 vex_printf(" %s ", function_name);
789 for (i = 0; i < arity; i++) {
796 /* --------- specialising "x86g_calculate_condition" --------- */
798 if (vex_streq(function_name, "x86g_calculate_condition")) {
799 /* specialise calls to above "calculate condition" function */
800 IRExpr *cond, *cc_op, *cc_dep1, *cc_dep2;
807 /*---------------- ADDL ----------------*/
809 if (isU32(cc_op, X86G_CC_OP_ADDL) && isU32(cond, X86CondZ)) {
810 /* long add, then Z --> test (dst+src == 0) */
811 return unop(Iop_1Uto32,
813 binop(Iop_Add32, cc_dep1, cc_dep2),
817 /*---------------- SUBL ----------------*/
819 if (isU32(cc_op, X86G_CC_OP_SUBL) && isU32(cond, X86CondZ)) {
820 /* long sub/cmp, then Z --> test dst==src */
821 return unop(Iop_1Uto32,
822 binop(Iop_CmpEQ32, cc_dep1, cc_dep2));
824 if (isU32(cc_op, X86G_CC_OP_SUBL) && isU32(cond, X86CondNZ)) {
825 /* long sub/cmp, then NZ --> test dst!=src */
826 return unop(Iop_1Uto32,
827 binop(Iop_CmpNE32, cc_dep1, cc_dep2));
830 if (isU32(cc_op, X86G_CC_OP_SUBL) && isU32(cond, X86CondL)) {
831 /* long sub/cmp, then L (signed less than)
832 --> test dst <s src */
833 return unop(Iop_1Uto32,
834 binop(Iop_CmpLT32S, cc_dep1, cc_dep2));
836 if (isU32(cc_op, X86G_CC_OP_SUBL) && isU32(cond, X86CondNL)) {
837 /* long sub/cmp, then NL (signed greater than or equal)
838 --> test !(dst <s src) */
839 return binop(Iop_Xor32,
841 binop(Iop_CmpLT32S, cc_dep1, cc_dep2)),
845 if (isU32(cc_op, X86G_CC_OP_SUBL) && isU32(cond, X86CondLE)) {
846 /* long sub/cmp, then LE (signed less than or equal)
847 --> test dst <=s src */
848 return unop(Iop_1Uto32,
849 binop(Iop_CmpLE32S, cc_dep1, cc_dep2));
851 if (isU32(cc_op, X86G_CC_OP_SUBL) && isU32(cond, X86CondNLE)) {
852 /* long sub/cmp, then NLE (signed not less than or equal)
854 --> test !(dst <=s src) */
855 return binop(Iop_Xor32,
857 binop(Iop_CmpLE32S, cc_dep1, cc_dep2)),
861 if (isU32(cc_op, X86G_CC_OP_SUBL) && isU32(cond, X86CondBE)) {
862 /* long sub/cmp, then BE (unsigned less than or equal)
863 --> test dst <=u src */
864 return unop(Iop_1Uto32,
865 binop(Iop_CmpLE32U, cc_dep1, cc_dep2));
867 if (isU32(cc_op, X86G_CC_OP_SUBL) && isU32(cond, X86CondNBE)) {
868 /* long sub/cmp, then BE (unsigned greater than)
869 --> test !(dst <=u src) */
870 return binop(Iop_Xor32,
872 binop(Iop_CmpLE32U, cc_dep1, cc_dep2)),
876 if (isU32(cc_op, X86G_CC_OP_SUBL) && isU32(cond, X86CondB)) {
877 /* long sub/cmp, then B (unsigned less than)
878 --> test dst <u src */
879 return unop(Iop_1Uto32,
880 binop(Iop_CmpLT32U, cc_dep1, cc_dep2));
882 if (isU32(cc_op, X86G_CC_OP_SUBL) && isU32(cond, X86CondNB)) {
883 /* long sub/cmp, then NB (unsigned greater than or equal)
884 --> test !(dst <u src) */
885 return binop(Iop_Xor32,
887 binop(Iop_CmpLT32U, cc_dep1, cc_dep2)),
891 if (isU32(cc_op, X86G_CC_OP_SUBL) && isU32(cond, X86CondS)) {
892 /* long sub/cmp, then S (negative) --> test (dst-src <s 0) */
893 return unop(Iop_1Uto32,
895 binop(Iop_Sub32, cc_dep1, cc_dep2),
898 if (isU32(cc_op, X86G_CC_OP_SUBL) && isU32(cond, X86CondNS)) {
899 /* long sub/cmp, then NS (not negative) --> test !(dst-src <s 0) */
900 return binop(Iop_Xor32,
903 binop(Iop_Sub32, cc_dep1, cc_dep2),
908 /*---------------- SUBW ----------------*/
910 if (isU32(cc_op, X86G_CC_OP_SUBW) && isU32(cond, X86CondZ)) {
911 /* word sub/cmp, then Z --> test dst==src */
912 return unop(Iop_1Uto32,
914 unop(Iop_32to16,cc_dep1),
915 unop(Iop_32to16,cc_dep2)));
917 if (isU32(cc_op, X86G_CC_OP_SUBW) && isU32(cond, X86CondNZ)) {
918 /* word sub/cmp, then NZ --> test dst!=src */
919 return unop(Iop_1Uto32,
921 unop(Iop_32to16,cc_dep1),
922 unop(Iop_32to16,cc_dep2)));
925 /*---------------- SUBB ----------------*/
927 if (isU32(cc_op, X86G_CC_OP_SUBB) && isU32(cond, X86CondZ)) {
928 /* byte sub/cmp, then Z --> test dst==src */
929 return unop(Iop_1Uto32,
931 unop(Iop_32to8,cc_dep1),
932 unop(Iop_32to8,cc_dep2)));
934 if (isU32(cc_op, X86G_CC_OP_SUBB) && isU32(cond, X86CondNZ)) {
935 /* byte sub/cmp, then NZ --> test dst!=src */
936 return unop(Iop_1Uto32,
938 unop(Iop_32to8,cc_dep1),
939 unop(Iop_32to8,cc_dep2)));
942 if (isU32(cc_op, X86G_CC_OP_SUBB) && isU32(cond, X86CondNBE)) {
943 /* byte sub/cmp, then NBE (unsigned greater than)
944 --> test src <u dst */
945 /* Note, args are opposite way round from the usual */
946 return unop(Iop_1Uto32,
948 binop(Iop_And32,cc_dep2,mkU32(0xFF)),
949 binop(Iop_And32,cc_dep1,mkU32(0xFF))));
952 if (isU32(cc_op, X86G_CC_OP_SUBB) && isU32(cond, X86CondS)
953 && isU32(cc_dep2, 0)) {
954 /* byte sub/cmp of zero, then S --> test (dst-0 <s 0)
957 This is yet another scheme by which gcc figures out if the
958 top bit of a byte is 1 or 0. See also LOGICB/CondS below. */
959 /* Note: isU32(cc_dep2, 0) is correct, even though this is
960 for an 8-bit comparison, since the args to the helper
961 function are always U32s. */
962 return binop(Iop_And32,
963 binop(Iop_Shr32,cc_dep1,mkU8(7)),
966 if (isU32(cc_op, X86G_CC_OP_SUBB) && isU32(cond, X86CondNS)
967 && isU32(cc_dep2, 0)) {
968 /* byte sub/cmp of zero, then NS --> test !(dst-0 <s 0)
972 return binop(Iop_Xor32,
974 binop(Iop_Shr32,cc_dep1,mkU8(7)),
979 /*---------------- LOGICL ----------------*/
981 if (isU32(cc_op, X86G_CC_OP_LOGICL) && isU32(cond, X86CondZ)) {
982 /* long and/or/xor, then Z --> test dst==0 */
983 return unop(Iop_1Uto32,binop(Iop_CmpEQ32, cc_dep1, mkU32(0)));
985 if (isU32(cc_op, X86G_CC_OP_LOGICL) && isU32(cond, X86CondNZ)) {
986 /* long and/or/xor, then NZ --> test dst!=0 */
987 return unop(Iop_1Uto32,binop(Iop_CmpNE32, cc_dep1, mkU32(0)));
990 if (isU32(cc_op, X86G_CC_OP_LOGICL) && isU32(cond, X86CondLE)) {
991 /* long and/or/xor, then LE
992 This is pretty subtle. LOGIC sets SF and ZF according to the
993 result and makes OF be zero. LE computes (SZ ^ OF) | ZF, but
994 OF is zero, so this reduces to SZ | ZF -- which will be 1 iff
995 the result is <=signed 0. Hence ...
997 return unop(Iop_1Uto32,binop(Iop_CmpLE32S, cc_dep1, mkU32(0)));
1000 if (isU32(cc_op, X86G_CC_OP_LOGICL) && isU32(cond, X86CondBE)) {
1001 /* long and/or/xor, then BE
1002 LOGIC sets ZF according to the result and makes CF be zero.
1003 BE computes (CF | ZF), but CF is zero, so this reduces ZF
1004 -- which will be 1 iff the result is zero. Hence ...
1006 return unop(Iop_1Uto32,binop(Iop_CmpEQ32, cc_dep1, mkU32(0)));
1009 if (isU32(cc_op, X86G_CC_OP_LOGICL) && isU32(cond, X86CondS)) {
1010 /* see comment below for (LOGICB, CondS) */
1011 /* long and/or/xor, then S --> (UInt)result[31] */
1012 return binop(Iop_And32,
1013 binop(Iop_Shr32,cc_dep1,mkU8(31)),
1016 if (isU32(cc_op, X86G_CC_OP_LOGICL) && isU32(cond, X86CondNS)) {
1017 /* see comment below for (LOGICB, CondNS) */
1018 /* long and/or/xor, then S --> (UInt) ~ result[31] */
1019 return binop(Iop_Xor32,
1021 binop(Iop_Shr32,cc_dep1,mkU8(31)),
1026 /*---------------- LOGICW ----------------*/
1028 if (isU32(cc_op, X86G_CC_OP_LOGICW) && isU32(cond, X86CondZ)) {
1029 /* word and/or/xor, then Z --> test dst==0 */
1030 return unop(Iop_1Uto32,
1031 binop(Iop_CmpEQ32, binop(Iop_And32,cc_dep1,mkU32(0xFFFF)),
1035 if (isU32(cc_op, X86G_CC_OP_LOGICW) && isU32(cond, X86CondS)) {
1036 /* see comment below for (LOGICB, CondS) */
1037 /* word and/or/xor, then S --> (UInt)result[15] */
1038 return binop(Iop_And32,
1039 binop(Iop_Shr32,cc_dep1,mkU8(15)),
1043 /*---------------- LOGICB ----------------*/
1045 if (isU32(cc_op, X86G_CC_OP_LOGICB) && isU32(cond, X86CondZ)) {
1046 /* byte and/or/xor, then Z --> test dst==0 */
1047 return unop(Iop_1Uto32,
1048 binop(Iop_CmpEQ32, binop(Iop_And32,cc_dep1,mkU32(255)),
1051 if (isU32(cc_op, X86G_CC_OP_LOGICB) && isU32(cond, X86CondNZ)) {
1052 /* byte and/or/xor, then Z --> test dst!=0 */
1053 /* b9ac9: 84 c0 test %al,%al
1054 b9acb: 75 0d jne b9ada */
1055 return unop(Iop_1Uto32,
1056 binop(Iop_CmpNE32, binop(Iop_And32,cc_dep1,mkU32(255)),
1060 if (isU32(cc_op, X86G_CC_OP_LOGICB) && isU32(cond, X86CondS)) {
1061 /* this is an idiom gcc sometimes uses to find out if the top
1062 bit of a byte register is set: eg testb %al,%al; js ..
1063 Since it just depends on the top bit of the byte, extract
1064 that bit and explicitly get rid of all the rest. This
1065 helps memcheck avoid false positives in the case where any
1066 of the other bits in the byte are undefined. */
1067 /* byte and/or/xor, then S --> (UInt)result[7] */
1068 return binop(Iop_And32,
1069 binop(Iop_Shr32,cc_dep1,mkU8(7)),
1072 if (isU32(cc_op, X86G_CC_OP_LOGICB) && isU32(cond, X86CondNS)) {
1073 /* ditto, for negation-of-S. */
1074 /* byte and/or/xor, then S --> (UInt) ~ result[7] */
1075 return binop(Iop_Xor32,
1077 binop(Iop_Shr32,cc_dep1,mkU8(7)),
1082 /*---------------- DECL ----------------*/
1084 if (isU32(cc_op, X86G_CC_OP_DECL) && isU32(cond, X86CondZ)) {
1085 /* dec L, then Z --> test dst == 0 */
1086 return unop(Iop_1Uto32,binop(Iop_CmpEQ32, cc_dep1, mkU32(0)));
1089 if (isU32(cc_op, X86G_CC_OP_DECL) && isU32(cond, X86CondS)) {
1090 /* dec L, then S --> compare DST <s 0 */
1091 return unop(Iop_1Uto32,binop(Iop_CmpLT32S, cc_dep1, mkU32(0)));
1094 /*---------------- DECW ----------------*/
1096 if (isU32(cc_op, X86G_CC_OP_DECW) && isU32(cond, X86CondZ)) {
1097 /* dec W, then Z --> test dst == 0 */
1098 return unop(Iop_1Uto32,
1100 binop(Iop_Shl32,cc_dep1,mkU8(16)),
1104 /*---------------- INCW ----------------*/
1106 if (isU32(cc_op, X86G_CC_OP_INCW) && isU32(cond, X86CondZ)) {
1107 /* This rewrite helps memcheck on 'incw %ax ; je ...'. */
1108 /* inc W, then Z --> test dst == 0 */
1109 return unop(Iop_1Uto32,
1111 binop(Iop_Shl32,cc_dep1,mkU8(16)),
1115 /*---------------- SHRL ----------------*/
1117 if (isU32(cc_op, X86G_CC_OP_SHRL) && isU32(cond, X86CondZ)) {
1118 /* SHRL, then Z --> test dep1 == 0 */
1119 return unop(Iop_1Uto32,binop(Iop_CmpEQ32, cc_dep1, mkU32(0)));
1122 /*---------------- COPY ----------------*/
1123 /* This can happen, as a result of x87 FP compares: "fcom ... ;
1124 fnstsw %ax ; sahf ; jbe" for example. */
1126 if (isU32(cc_op, X86G_CC_OP_COPY) &&
1127 (isU32(cond, X86CondBE) || isU32(cond, X86CondNBE))) {
1128 /* COPY, then BE --> extract C and Z from dep1, and test
1130 /* COPY, then NBE --> extract C and Z from dep1, and test
1132 UInt nnn = isU32(cond, X86CondBE) ? 1 : 0;
1142 binop(Iop_Shr32, cc_dep1, mkU8(X86G_CC_SHIFT_C)),
1143 binop(Iop_Shr32, cc_dep1, mkU8(X86G_CC_SHIFT_Z))
1152 if (isU32(cc_op, X86G_CC_OP_COPY)
1153 && (isU32(cond, X86CondB) || isU32(cond, X86CondNB))) {
1154 /* COPY, then B --> extract C from dep1, and test (C == 1). */
1155 /* COPY, then NB --> extract C from dep1, and test (C == 0). */
1156 UInt nnn = isU32(cond, X86CondB) ? 1 : 0;
1164 binop(Iop_Shr32, cc_dep1, mkU8(X86G_CC_SHIFT_C)),
1172 if (isU32(cc_op, X86G_CC_OP_COPY)
1173 && (isU32(cond, X86CondZ) || isU32(cond, X86CondNZ))) {
1174 /* COPY, then Z --> extract Z from dep1, and test (Z == 1). */
1175 /* COPY, then NZ --> extract Z from dep1, and test (Z == 0). */
1176 UInt nnn = isU32(cond, X86CondZ) ? 1 : 0;
1184 binop(Iop_Shr32, cc_dep1, mkU8(X86G_CC_SHIFT_Z)),
1192 if (isU32(cc_op, X86G_CC_OP_COPY)
1193 && (isU32(cond, X86CondP) || isU32(cond, X86CondNP))) {
1194 /* COPY, then P --> extract P from dep1, and test (P == 1). */
1195 /* COPY, then NP --> extract P from dep1, and test (P == 0). */
1196 UInt nnn = isU32(cond, X86CondP) ? 1 : 0;
1204 binop(Iop_Shr32, cc_dep1, mkU8(X86G_CC_SHIFT_P)),
1215 /* --------- specialising "x86g_calculate_eflags_c" --------- */
1217 if (vex_streq(function_name, "x86g_calculate_eflags_c")) {
1218 /* specialise calls to above "calculate_eflags_c" function */
1219 IRExpr *cc_op, *cc_dep1, *cc_dep2, *cc_ndep;
1220 vassert(arity == 4);
1226 if (isU32(cc_op, X86G_CC_OP_SUBL)) {
1227 /* C after sub denotes unsigned less than */
1228 return unop(Iop_1Uto32,
1229 binop(Iop_CmpLT32U, cc_dep1, cc_dep2));
1231 if (isU32(cc_op, X86G_CC_OP_SUBB)) {
1232 /* C after sub denotes unsigned less than */
1233 return unop(Iop_1Uto32,
1235 binop(Iop_And32,cc_dep1,mkU32(0xFF)),
1236 binop(Iop_And32,cc_dep2,mkU32(0xFF))));
1238 if (isU32(cc_op, X86G_CC_OP_LOGICL)
1239 || isU32(cc_op, X86G_CC_OP_LOGICW)
1240 || isU32(cc_op, X86G_CC_OP_LOGICB)) {
1241 /* cflag after logic is zero */
1244 if (isU32(cc_op, X86G_CC_OP_DECL) || isU32(cc_op, X86G_CC_OP_INCL)) {
1245 /* If the thunk is dec or inc, the cflag is supplied as CC_NDEP. */
1248 if (isU32(cc_op, X86G_CC_OP_COPY)) {
1249 /* cflag after COPY is stored in DEP1. */
1253 binop(Iop_Shr32, cc_dep1, mkU8(X86G_CC_SHIFT_C)),
1257 if (isU32(cc_op, X86G_CC_OP_ADDL)) {
1258 /* C after add denotes sum <u either arg */
1259 return unop(Iop_1Uto32,
1261 binop(Iop_Add32, cc_dep1, cc_dep2),
1264 // ATC, requires verification, no test case known
1265 //if (isU32(cc_op, X86G_CC_OP_SMULL)) {
1266 // /* C after signed widening multiply denotes the case where
1267 // the top half of the result isn't simply the sign extension
1268 // of the bottom half (iow the result doesn't fit completely
1269 // in the bottom half). Hence:
1270 // C = hi-half(dep1 x dep2) != lo-half(dep1 x dep2) >>s 31
1271 // where 'x' denotes signed widening multiply.*/
1274 // binop(Iop_CmpNE32,
1275 // unop(Iop_64HIto32,
1276 // binop(Iop_MullS32, cc_dep1, cc_dep2)),
1278 // binop(Iop_Mul32, cc_dep1, cc_dep2), mkU8(31)) ));
1281 if (cc_op->tag == Iex_Const) {
1282 vex_printf("CFLAG "); ppIRExpr(cc_op); vex_printf("\n");
1289 /* --------- specialising "x86g_calculate_eflags_all" --------- */
1291 if (vex_streq(function_name, "x86g_calculate_eflags_all")) {
1292 /* specialise calls to above "calculate_eflags_all" function */
1293 IRExpr *cc_op, *cc_dep1; /*, *cc_dep2, *cc_ndep; */
1294 vassert(arity == 4);
1297 /* cc_dep2 = args[2]; */
1298 /* cc_ndep = args[3]; */
1300 if (isU32(cc_op, X86G_CC_OP_COPY)) {
1301 /* eflags after COPY are stored in DEP1. */
1306 mkU32(X86G_CC_MASK_O | X86G_CC_MASK_S | X86G_CC_MASK_Z
1307 | X86G_CC_MASK_A | X86G_CC_MASK_C | X86G_CC_MASK_P)
1322 /*---------------------------------------------------------------*/
1323 /*--- Supporting functions for x87 FPU activities. ---*/
1324 /*---------------------------------------------------------------*/
1326 static inline Bool host_is_little_endian ( void )
1328 UInt x = 0x76543210;
1329 UChar* p = (UChar*)(&x);
1330 return toBool(*p == 0x10);
1333 /* 80 and 64-bit floating point formats:
1338 S 0 0X------X denormals
1339 S 1-7FFE 1X------X normals (all normals have leading 1)
1340 S 7FFF 10------0 infinity
1341 S 7FFF 10X-----X snan
1342 S 7FFF 11X-----X qnan
1344 S is the sign bit. For runs X----X, at least one of the Xs must be
1345 nonzero. Exponent is 15 bits, fractional part is 63 bits, and
1346 there is an explicitly represented leading 1, and a sign bit,
1349 64-bit avoids the confusion of an explicitly represented leading 1
1353 S 0 X------X denormals
1355 S 7FF 0------0 infinity
1359 Exponent is 11 bits, fractional part is 52 bits, and there is a
1360 sign bit, giving 64 in total.
1363 /* Inspect a value and its tag, as per the x87 'FXAM' instruction. */
1364 /* CALLED FROM GENERATED CODE: CLEAN HELPER */
1365 UInt x86g_calculate_FXAM ( UInt tag, ULong dbl )
1367 Bool mantissaIsZero;
1372 vassert(host_is_little_endian());
1374 /* vex_printf("calculate_FXAM ( %d, %llx ) .. ", tag, dbl ); */
1376 f64 = (UChar*)(&dbl);
1377 sign = toUChar( (f64[7] >> 7) & 1 );
1379 /* First off, if the tag indicates the register was empty,
1380 return 1,0,sign,1 */
1382 /* vex_printf("Empty\n"); */
1383 return X86G_FC_MASK_C3 | 0 | (sign << X86G_FC_SHIFT_C1)
1387 bexp = (f64[7] << 4) | ((f64[6] >> 4) & 0x0F);
1392 (f64[6] & 0x0F) == 0
1393 && (f64[5] | f64[4] | f64[3] | f64[2] | f64[1] | f64[0]) == 0
1396 /* If both exponent and mantissa are zero, the value is zero.
1397 Return 1,0,sign,0. */
1398 if (bexp == 0 && mantissaIsZero) {
1399 /* vex_printf("Zero\n"); */
1400 return X86G_FC_MASK_C3 | 0
1401 | (sign << X86G_FC_SHIFT_C1) | 0;
1404 /* If exponent is zero but mantissa isn't, it's a denormal.
1405 Return 1,1,sign,0. */
1406 if (bexp == 0 && !mantissaIsZero) {
1407 /* vex_printf("Denormal\n"); */
1408 return X86G_FC_MASK_C3 | X86G_FC_MASK_C2
1409 | (sign << X86G_FC_SHIFT_C1) | 0;
1412 /* If the exponent is 7FF and the mantissa is zero, this is an infinity.
1413 Return 0,1,sign,1. */
1414 if (bexp == 0x7FF && mantissaIsZero) {
1415 /* vex_printf("Inf\n"); */
1416 return 0 | X86G_FC_MASK_C2 | (sign << X86G_FC_SHIFT_C1)
1420 /* If the exponent is 7FF and the mantissa isn't zero, this is a NaN.
1421 Return 0,0,sign,1. */
1422 if (bexp == 0x7FF && !mantissaIsZero) {
1423 /* vex_printf("NaN\n"); */
1424 return 0 | 0 | (sign << X86G_FC_SHIFT_C1) | X86G_FC_MASK_C0;
1427 /* Uh, ok, we give up. It must be a normal finite number.
1430 /* vex_printf("normal\n"); */
1431 return 0 | X86G_FC_MASK_C2 | (sign << X86G_FC_SHIFT_C1) | 0;
1435 /* CALLED FROM GENERATED CODE */
1436 /* DIRTY HELPER (reads guest memory) */
1437 ULong x86g_dirtyhelper_loadF80le ( UInt addrU )
1440 convert_f80le_to_f64le ( (UChar*)ULong_to_Ptr(addrU), (UChar*)&f64 );
1444 /* CALLED FROM GENERATED CODE */
1445 /* DIRTY HELPER (writes guest memory) */
1446 void x86g_dirtyhelper_storeF80le ( UInt addrU, ULong f64 )
1448 convert_f64le_to_f80le( (UChar*)&f64, (UChar*)ULong_to_Ptr(addrU) );
1452 /*----------------------------------------------*/
1453 /*--- The exported fns .. ---*/
1454 /*----------------------------------------------*/
1456 /* Layout of the real x87 state. */
1457 /* 13 June 05: Fpu_State and auxiliary constants was moved to
1462 /* fpucw[15:0] contains a x87 native format FPU control word.
1463 Extract from it the required FPROUND value and any resulting
1464 emulation warning, and return (warn << 32) | fpround value.
1466 ULong x86g_check_fldcw ( UInt fpucw )
1468 /* Decide on a rounding mode. fpucw[11:10] holds it. */
1469 /* NOTE, encoded exactly as per enum IRRoundingMode. */
1470 UInt rmode = (fpucw >> 10) & 3;
1472 /* Detect any required emulation warnings. */
1473 VexEmWarn ew = EmWarn_NONE;
1475 if ((fpucw & 0x3F) != 0x3F) {
1476 /* unmasked exceptions! */
1477 ew = EmWarn_X86_x87exns;
1480 if (((fpucw >> 8) & 3) != 3) {
1481 /* unsupported precision */
1482 ew = EmWarn_X86_x87precision;
1485 return (((ULong)ew) << 32) | ((ULong)rmode);
1489 /* Given fpround as an IRRoundingMode value, create a suitable x87
1490 native format FPU control word. */
1491 UInt x86g_create_fpucw ( UInt fpround )
1494 return 0x037F | (fpround << 10);
1499 /* mxcsr[15:0] contains a SSE native format MXCSR value.
1500 Extract from it the required SSEROUND value and any resulting
1501 emulation warning, and return (warn << 32) | sseround value.
1503 ULong x86g_check_ldmxcsr ( UInt mxcsr )
1505 /* Decide on a rounding mode. mxcsr[14:13] holds it. */
1506 /* NOTE, encoded exactly as per enum IRRoundingMode. */
1507 UInt rmode = (mxcsr >> 13) & 3;
1509 /* Detect any required emulation warnings. */
1510 VexEmWarn ew = EmWarn_NONE;
1512 if ((mxcsr & 0x1F80) != 0x1F80) {
1513 /* unmasked exceptions! */
1514 ew = EmWarn_X86_sseExns;
1517 if (mxcsr & (1<<15)) {
1522 if (mxcsr & (1<<6)) {
1524 ew = EmWarn_X86_daz;
1527 return (((ULong)ew) << 32) | ((ULong)rmode);
1532 /* Given sseround as an IRRoundingMode value, create a suitable SSE
1533 native format MXCSR value. */
1534 UInt x86g_create_mxcsr ( UInt sseround )
1537 return 0x1F80 | (sseround << 13);
1541 /* CALLED FROM GENERATED CODE */
1542 /* DIRTY HELPER (writes guest state) */
1543 /* Initialise the x87 FPU state as per 'finit'. */
1544 void x86g_dirtyhelper_FINIT ( VexGuestX86State* gst )
1547 gst->guest_FTOP = 0;
1548 for (i = 0; i < 8; i++) {
1549 gst->guest_FPTAG[i] = 0; /* empty */
1550 gst->guest_FPREG[i] = 0; /* IEEE754 64-bit zero */
1552 gst->guest_FPROUND = (UInt)Irrm_NEAREST;
1553 gst->guest_FC3210 = 0;
1557 /* This is used to implement both 'frstor' and 'fldenv'. The latter
1558 appears to differ from the former only in that the 8 FP registers
1559 themselves are not transferred into the guest state. */
1561 VexEmWarn do_put_x87 ( Bool moveRegs,
1562 /*IN*/UChar* x87_state,
1563 /*OUT*/VexGuestX86State* vex_state )
1567 ULong* vexRegs = (ULong*)(&vex_state->guest_FPREG[0]);
1568 UChar* vexTags = (UChar*)(&vex_state->guest_FPTAG[0]);
1569 Fpu_State* x87 = (Fpu_State*)x87_state;
1570 UInt ftop = (x87->env[FP_ENV_STAT] >> 11) & 7;
1571 UInt tagw = x87->env[FP_ENV_TAG];
1572 UInt fpucw = x87->env[FP_ENV_CTRL];
1573 UInt c3210 = x87->env[FP_ENV_STAT] & 0x4700;
1578 /* Copy registers and tags */
1579 for (stno = 0; stno < 8; stno++) {
1580 preg = (stno + ftop) & 7;
1581 tag = (tagw >> (2*preg)) & 3;
1583 /* register is empty */
1584 /* hmm, if it's empty, does it still get written? Probably
1585 safer to say it does. If we don't, memcheck could get out
1586 of sync, in that it thinks all FP registers are defined by
1587 this helper, but in reality some have not been updated. */
1589 vexRegs[preg] = 0; /* IEEE754 64-bit zero */
1592 /* register is non-empty */
1594 convert_f80le_to_f64le( &x87->reg[10*stno],
1595 (UChar*)&vexRegs[preg] );
1601 vex_state->guest_FTOP = ftop;
1604 vex_state->guest_FC3210 = c3210;
1606 /* handle the control word, setting FPROUND and detecting any
1607 emulation warnings. */
1608 pair = x86g_check_fldcw ( (UInt)fpucw );
1609 fpround = (UInt)pair;
1610 ew = (VexEmWarn)(pair >> 32);
1612 vex_state->guest_FPROUND = fpround & 3;
1614 /* emulation warnings --> caller */
1619 /* Create an x87 FPU state from the guest state, as close as
1620 we can approximate it. */
1622 void do_get_x87 ( /*IN*/VexGuestX86State* vex_state,
1623 /*OUT*/UChar* x87_state )
1627 ULong* vexRegs = (ULong*)(&vex_state->guest_FPREG[0]);
1628 UChar* vexTags = (UChar*)(&vex_state->guest_FPTAG[0]);
1629 Fpu_State* x87 = (Fpu_State*)x87_state;
1630 UInt ftop = vex_state->guest_FTOP;
1631 UInt c3210 = vex_state->guest_FC3210;
1633 for (i = 0; i < 14; i++)
1636 x87->env[1] = x87->env[3] = x87->env[5] = x87->env[13] = 0xFFFF;
1637 x87->env[FP_ENV_STAT]
1638 = toUShort(((ftop & 7) << 11) | (c3210 & 0x4700));
1639 x87->env[FP_ENV_CTRL]
1640 = toUShort(x86g_create_fpucw( vex_state->guest_FPROUND ));
1642 /* Dump the register stack in ST order. */
1644 for (stno = 0; stno < 8; stno++) {
1645 preg = (stno + ftop) & 7;
1646 if (vexTags[preg] == 0) {
1647 /* register is empty */
1648 tagw |= (3 << (2*preg));
1649 convert_f64le_to_f80le( (UChar*)&vexRegs[preg],
1650 &x87->reg[10*stno] );
1652 /* register is full. */
1653 tagw |= (0 << (2*preg));
1654 convert_f64le_to_f80le( (UChar*)&vexRegs[preg],
1655 &x87->reg[10*stno] );
1658 x87->env[FP_ENV_TAG] = toUShort(tagw);
1662 /* CALLED FROM GENERATED CODE */
1663 /* DIRTY HELPER (reads guest state, writes guest mem) */
1664 void x86g_dirtyhelper_FXSAVE ( VexGuestX86State* gst, HWord addr )
1666 /* Somewhat roundabout, but at least it's simple. */
1668 UShort* addrS = (UShort*)addr;
1669 UChar* addrC = (UChar*)addr;
1670 U128* xmm = (U128*)(addr + 160);
1675 UShort *srcS, *dstS;
1677 do_get_x87( gst, (UChar*)&tmp );
1678 mxcsr = x86g_create_mxcsr( gst->guest_SSEROUND );
1680 /* Now build the proper fxsave image from the x87 image we just
1683 addrS[0] = tmp.env[FP_ENV_CTRL]; /* FCW: fpu control word */
1684 addrS[1] = tmp.env[FP_ENV_STAT]; /* FCW: fpu status word */
1686 /* set addrS[2] in an endian-independent way */
1688 fp_tags = tmp.env[FP_ENV_TAG];
1689 for (r = 0; r < 8; r++) {
1690 if ( ((fp_tags >> (2*r)) & 3) != 3 )
1691 summary_tags |= (1 << r);
1693 addrC[4] = toUChar(summary_tags); /* FTW: tag summary byte */
1694 addrC[5] = 0; /* pad */
1696 addrS[3] = 0; /* FOP: fpu opcode (bogus) */
1698 addrS[5] = 0; /* FPU IP (bogus) */
1699 addrS[6] = 0; /* FPU IP's segment selector (bogus) (although we
1700 could conceivably dump %CS here) */
1702 addrS[7] = 0; /* Intel reserved */
1704 addrS[8] = 0; /* FPU DP (operand pointer) (bogus) */
1705 addrS[9] = 0; /* FPU DP (operand pointer) (bogus) */
1706 addrS[10] = 0; /* segment selector for above operand pointer; %DS
1708 addrS[11] = 0; /* Intel reserved */
1710 addrS[12] = toUShort(mxcsr); /* MXCSR */
1711 addrS[13] = toUShort(mxcsr >> 16);
1713 addrS[14] = 0xFFFF; /* MXCSR mask (lo16); who knows what for */
1714 addrS[15] = 0xFFFF; /* MXCSR mask (hi16); who knows what for */
1716 /* Copy in the FP registers, in ST order. */
1717 for (stno = 0; stno < 8; stno++) {
1718 srcS = (UShort*)(&tmp.reg[10*stno]);
1719 dstS = (UShort*)(&addrS[16 + 8*stno]);
1730 /* That's the first 160 bytes of the image done. Now only %xmm0
1731 .. %xmm7 remain to be copied. If the host is big-endian, these
1732 need to be byte-swapped. */
1733 vassert(host_is_little_endian());
1735 # define COPY_U128(_dst,_src) \
1736 do { _dst[0] = _src[0]; _dst[1] = _src[1]; \
1737 _dst[2] = _src[2]; _dst[3] = _src[3]; } \
1740 COPY_U128( xmm[0], gst->guest_XMM0 );
1741 COPY_U128( xmm[1], gst->guest_XMM1 );
1742 COPY_U128( xmm[2], gst->guest_XMM2 );
1743 COPY_U128( xmm[3], gst->guest_XMM3 );
1744 COPY_U128( xmm[4], gst->guest_XMM4 );
1745 COPY_U128( xmm[5], gst->guest_XMM5 );
1746 COPY_U128( xmm[6], gst->guest_XMM6 );
1747 COPY_U128( xmm[7], gst->guest_XMM7 );
1753 /* CALLED FROM GENERATED CODE */
1754 /* DIRTY HELPER (writes guest state, reads guest mem) */
1755 VexEmWarn x86g_dirtyhelper_FXRSTOR ( VexGuestX86State* gst, HWord addr )
1758 VexEmWarn warnX87 = EmWarn_NONE;
1759 VexEmWarn warnXMM = EmWarn_NONE;
1760 UShort* addrS = (UShort*)addr;
1761 UChar* addrC = (UChar*)addr;
1762 U128* xmm = (U128*)(addr + 160);
1766 /* Restore %xmm0 .. %xmm7. If the host is big-endian, these need
1767 to be byte-swapped. */
1768 vassert(host_is_little_endian());
1770 # define COPY_U128(_dst,_src) \
1771 do { _dst[0] = _src[0]; _dst[1] = _src[1]; \
1772 _dst[2] = _src[2]; _dst[3] = _src[3]; } \
1775 COPY_U128( gst->guest_XMM0, xmm[0] );
1776 COPY_U128( gst->guest_XMM1, xmm[1] );
1777 COPY_U128( gst->guest_XMM2, xmm[2] );
1778 COPY_U128( gst->guest_XMM3, xmm[3] );
1779 COPY_U128( gst->guest_XMM4, xmm[4] );
1780 COPY_U128( gst->guest_XMM5, xmm[5] );
1781 COPY_U128( gst->guest_XMM6, xmm[6] );
1782 COPY_U128( gst->guest_XMM7, xmm[7] );
1786 /* Copy the x87 registers out of the image, into a temporary
1787 Fpu_State struct. */
1788 for (i = 0; i < 14; i++) tmp.env[i] = 0;
1789 for (i = 0; i < 80; i++) tmp.reg[i] = 0;
1790 /* fill in tmp.reg[0..7] */
1791 for (stno = 0; stno < 8; stno++) {
1792 UShort* dstS = (UShort*)(&tmp.reg[10*stno]);
1793 UShort* srcS = (UShort*)(&addrS[16 + 8*stno]);
1800 /* fill in tmp.env[0..13] */
1801 tmp.env[FP_ENV_CTRL] = addrS[0]; /* FCW: fpu control word */
1802 tmp.env[FP_ENV_STAT] = addrS[1]; /* FCW: fpu status word */
1805 for (r = 0; r < 8; r++) {
1806 if (addrC[4] & (1<<r))
1807 fp_tags |= (0 << (2*r)); /* EMPTY */
1809 fp_tags |= (3 << (2*r)); /* VALID -- not really precise enough. */
1811 tmp.env[FP_ENV_TAG] = fp_tags;
1813 /* Now write 'tmp' into the guest state. */
1814 warnX87 = do_put_x87( True/*moveRegs*/, (UChar*)&tmp, gst );
1816 { UInt w32 = (((UInt)addrS[12]) & 0xFFFF)
1817 | ((((UInt)addrS[13]) & 0xFFFF) << 16);
1818 ULong w64 = x86g_check_ldmxcsr( w32 );
1820 warnXMM = (VexEmWarn)(w64 >> 32);
1822 gst->guest_SSEROUND = (UInt)w64;
1825 /* Prefer an X87 emwarn over an XMM one, if both exist. */
1826 if (warnX87 != EmWarn_NONE)
1833 /* CALLED FROM GENERATED CODE */
1834 /* DIRTY HELPER (reads guest state, writes guest mem) */
1835 void x86g_dirtyhelper_FSAVE ( VexGuestX86State* gst, HWord addr )
1837 do_get_x87( gst, (UChar*)addr );
1840 /* CALLED FROM GENERATED CODE */
1841 /* DIRTY HELPER (writes guest state, reads guest mem) */
1842 VexEmWarn x86g_dirtyhelper_FRSTOR ( VexGuestX86State* gst, HWord addr )
1844 return do_put_x87( True/*regs too*/, (UChar*)addr, gst );
1847 /* CALLED FROM GENERATED CODE */
1848 /* DIRTY HELPER (reads guest state, writes guest mem) */
1849 void x86g_dirtyhelper_FSTENV ( VexGuestX86State* gst, HWord addr )
1851 /* Somewhat roundabout, but at least it's simple. */
1853 UShort* addrP = (UShort*)addr;
1855 do_get_x87( gst, (UChar*)&tmp );
1856 for (i = 0; i < 14; i++)
1857 addrP[i] = tmp.env[i];
1860 /* CALLED FROM GENERATED CODE */
1861 /* DIRTY HELPER (writes guest state, reads guest mem) */
1862 VexEmWarn x86g_dirtyhelper_FLDENV ( VexGuestX86State* gst, HWord addr )
1864 return do_put_x87( False/*don't move regs*/, (UChar*)addr, gst);
1868 /*---------------------------------------------------------------*/
1869 /*--- Misc integer helpers, including rotates and CPUID. ---*/
1870 /*---------------------------------------------------------------*/
1872 /* CALLED FROM GENERATED CODE: CLEAN HELPER */
1873 /* Calculate both flags and value result for rotate right
1874 through the carry bit. Result in low 32 bits,
1875 new flags (OSZACP) in high 32 bits.
1877 ULong x86g_calculate_RCR ( UInt arg, UInt rot_amt, UInt eflags_in, UInt sz )
1879 UInt tempCOUNT = rot_amt & 0x1F, cf=0, of=0, tempcf;
1883 cf = (eflags_in >> X86G_CC_SHIFT_C) & 1;
1884 of = ((arg >> 31) ^ cf) & 1;
1885 while (tempCOUNT > 0) {
1887 arg = (arg >> 1) | (cf << 31);
1893 while (tempCOUNT >= 17) tempCOUNT -= 17;
1894 cf = (eflags_in >> X86G_CC_SHIFT_C) & 1;
1895 of = ((arg >> 15) ^ cf) & 1;
1896 while (tempCOUNT > 0) {
1898 arg = ((arg >> 1) & 0x7FFF) | (cf << 15);
1904 while (tempCOUNT >= 9) tempCOUNT -= 9;
1905 cf = (eflags_in >> X86G_CC_SHIFT_C) & 1;
1906 of = ((arg >> 7) ^ cf) & 1;
1907 while (tempCOUNT > 0) {
1909 arg = ((arg >> 1) & 0x7F) | (cf << 7);
1915 vpanic("calculate_RCR: invalid size");
1920 eflags_in &= ~(X86G_CC_MASK_C | X86G_CC_MASK_O);
1921 eflags_in |= (cf << X86G_CC_SHIFT_C) | (of << X86G_CC_SHIFT_O);
1923 return (((ULong)eflags_in) << 32) | ((ULong)arg);
1927 /* CALLED FROM GENERATED CODE: CLEAN HELPER */
1928 /* Calculate both flags and value result for rotate left
1929 through the carry bit. Result in low 32 bits,
1930 new flags (OSZACP) in high 32 bits.
1932 ULong x86g_calculate_RCL ( UInt arg, UInt rot_amt, UInt eflags_in, UInt sz )
1934 UInt tempCOUNT = rot_amt & 0x1F, cf=0, of=0, tempcf;
1938 cf = (eflags_in >> X86G_CC_SHIFT_C) & 1;
1939 while (tempCOUNT > 0) {
1940 tempcf = (arg >> 31) & 1;
1941 arg = (arg << 1) | (cf & 1);
1945 of = ((arg >> 31) ^ cf) & 1;
1948 while (tempCOUNT >= 17) tempCOUNT -= 17;
1949 cf = (eflags_in >> X86G_CC_SHIFT_C) & 1;
1950 while (tempCOUNT > 0) {
1951 tempcf = (arg >> 15) & 1;
1952 arg = 0xFFFF & ((arg << 1) | (cf & 1));
1956 of = ((arg >> 15) ^ cf) & 1;
1959 while (tempCOUNT >= 9) tempCOUNT -= 9;
1960 cf = (eflags_in >> X86G_CC_SHIFT_C) & 1;
1961 while (tempCOUNT > 0) {
1962 tempcf = (arg >> 7) & 1;
1963 arg = 0xFF & ((arg << 1) | (cf & 1));
1967 of = ((arg >> 7) ^ cf) & 1;
1970 vpanic("calculate_RCL: invalid size");
1975 eflags_in &= ~(X86G_CC_MASK_C | X86G_CC_MASK_O);
1976 eflags_in |= (cf << X86G_CC_SHIFT_C) | (of << X86G_CC_SHIFT_O);
1978 return (((ULong)eflags_in) << 32) | ((ULong)arg);
1982 /* CALLED FROM GENERATED CODE: CLEAN HELPER */
1983 /* Calculate both flags and value result for DAA/DAS/AAA/AAS.
1984 AX value in low half of arg, OSZACP in upper half.
1985 See guest-x86/toIR.c usage point for details.
1987 static UInt calc_parity_8bit ( UInt w32 ) {
1990 for (i = 0; i < 8; i++)
1991 p ^= (1 & (w32 >> i));
1994 UInt x86g_calculate_daa_das_aaa_aas ( UInt flags_and_AX, UInt opcode )
1996 UInt r_AL = (flags_and_AX >> 0) & 0xFF;
1997 UInt r_AH = (flags_and_AX >> 8) & 0xFF;
1998 UInt r_O = (flags_and_AX >> (16 + X86G_CC_SHIFT_O)) & 1;
1999 UInt r_S = (flags_and_AX >> (16 + X86G_CC_SHIFT_S)) & 1;
2000 UInt r_Z = (flags_and_AX >> (16 + X86G_CC_SHIFT_Z)) & 1;
2001 UInt r_A = (flags_and_AX >> (16 + X86G_CC_SHIFT_A)) & 1;
2002 UInt r_C = (flags_and_AX >> (16 + X86G_CC_SHIFT_C)) & 1;
2003 UInt r_P = (flags_and_AX >> (16 + X86G_CC_SHIFT_P)) & 1;
2007 case 0x27: { /* DAA */
2011 if ((r_AL & 0xF) > 9 || r_A == 1) {
2014 if (r_AL >= 0x100) r_C = 1;
2019 if (old_AL > 0x99 || old_C == 1) {
2025 /* O is undefined. S Z and P are set according to the
2028 r_O = 0; /* let's say */
2029 r_S = (r_AL & 0x80) ? 1 : 0;
2030 r_Z = (r_AL == 0) ? 1 : 0;
2031 r_P = calc_parity_8bit( r_AL );
2034 case 0x2F: { /* DAS */
2038 if ((r_AL & 0xF) > 9 || r_A == 1) {
2039 Bool borrow = r_AL < 6;
2042 if (borrow) r_C = 1;
2047 if (old_AL > 0x99 || old_C == 1) {
2051 /* Intel docs are wrong: r_C = 0; */
2053 /* O is undefined. S Z and P are set according to the
2056 r_O = 0; /* let's say */
2057 r_S = (r_AL & 0x80) ? 1 : 0;
2058 r_Z = (r_AL == 0) ? 1 : 0;
2059 r_P = calc_parity_8bit( r_AL );
2062 case 0x37: { /* AAA */
2063 Bool nudge = r_AL > 0xF9;
2064 if ((r_AL & 0xF) > 9 || r_A == 1) {
2066 r_AH = r_AH + 1 + (nudge ? 1 : 0);
2075 /* O S Z and P are undefined. */
2076 r_O = r_S = r_Z = r_P = 0; /* let's say */
2079 case 0x3F: { /* AAS */
2080 Bool nudge = r_AL < 0x06;
2081 if ((r_AL & 0xF) > 9 || r_A == 1) {
2083 r_AH = r_AH - 1 - (nudge ? 1 : 0);
2092 /* O S Z and P are undefined. */
2093 r_O = r_S = r_Z = r_P = 0; /* let's say */
2099 result = ( (r_O & 1) << (16 + X86G_CC_SHIFT_O) )
2100 | ( (r_S & 1) << (16 + X86G_CC_SHIFT_S) )
2101 | ( (r_Z & 1) << (16 + X86G_CC_SHIFT_Z) )
2102 | ( (r_A & 1) << (16 + X86G_CC_SHIFT_A) )
2103 | ( (r_C & 1) << (16 + X86G_CC_SHIFT_C) )
2104 | ( (r_P & 1) << (16 + X86G_CC_SHIFT_P) )
2105 | ( (r_AH & 0xFF) << 8 )
2106 | ( (r_AL & 0xFF) << 0 );
2111 /* CALLED FROM GENERATED CODE */
2112 /* DIRTY HELPER (non-referentially-transparent) */
2113 /* Horrible hack. On non-x86 platforms, return 1. */
2114 ULong x86g_dirtyhelper_RDTSC ( void )
2116 # if defined(__i386__)
2118 __asm__ __volatile__("rdtsc" : "=A" (res));
2126 /* CALLED FROM GENERATED CODE */
2127 /* DIRTY HELPER (modifies guest state) */
2128 /* Claim to be a P55C (Intel Pentium/MMX) */
2129 void x86g_dirtyhelper_CPUID_sse0 ( VexGuestX86State* st )
2131 switch (st->guest_EAX) {
2133 st->guest_EAX = 0x1;
2134 st->guest_EBX = 0x756e6547;
2135 st->guest_ECX = 0x6c65746e;
2136 st->guest_EDX = 0x49656e69;
2139 st->guest_EAX = 0x543;
2140 st->guest_EBX = 0x0;
2141 st->guest_ECX = 0x0;
2142 st->guest_EDX = 0x8001bf;
2147 /* CALLED FROM GENERATED CODE */
2148 /* DIRTY HELPER (modifies guest state) */
2149 /* Claim to be the following SSE1-capable CPU:
2150 vendor_id : GenuineIntel
2153 model name : Intel(R) Pentium(R) III CPU family 1133MHz
2158 void x86g_dirtyhelper_CPUID_sse1 ( VexGuestX86State* st )
2160 switch (st->guest_EAX) {
2162 st->guest_EAX = 0x00000002;
2163 st->guest_EBX = 0x756e6547;
2164 st->guest_ECX = 0x6c65746e;
2165 st->guest_EDX = 0x49656e69;
2168 st->guest_EAX = 0x000006b1;
2169 st->guest_EBX = 0x00000004;
2170 st->guest_ECX = 0x00000000;
2171 st->guest_EDX = 0x0383fbff;
2174 st->guest_EAX = 0x03020101;
2175 st->guest_EBX = 0x00000000;
2176 st->guest_ECX = 0x00000000;
2177 st->guest_EDX = 0x0c040883;
2182 /* Claim to be the following SSSE3-capable CPU (2 x ...):
2183 vendor_id : GenuineIntel
2186 model name : Intel(R) Core(TM)2 CPU 6600 @ 2.40GHz
2189 cache size : 4096 KB
2198 flags : fpu vme de pse tsc msr pae mce cx8 apic sep
2199 mtrr pge mca cmov pat pse36 clflush dts acpi
2200 mmx fxsr sse sse2 ss ht tm syscall nx lm
2201 constant_tsc pni monitor ds_cpl vmx est tm2
2205 cache_alignment : 64
2206 address sizes : 36 bits physical, 48 bits virtual
2209 void x86g_dirtyhelper_CPUID_sse2 ( VexGuestX86State* st )
2211 # define SET_ABCD(_a,_b,_c,_d) \
2212 do { st->guest_EAX = (UInt)(_a); \
2213 st->guest_EBX = (UInt)(_b); \
2214 st->guest_ECX = (UInt)(_c); \
2215 st->guest_EDX = (UInt)(_d); \
2218 switch (st->guest_EAX) {
2220 SET_ABCD(0x0000000a, 0x756e6547, 0x6c65746e, 0x49656e69);
2223 SET_ABCD(0x000006f6, 0x00020800, 0x0000e3bd, 0xbfebfbff);
2226 SET_ABCD(0x05b0b101, 0x005657f0, 0x00000000, 0x2cb43049);
2229 SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2232 switch (st->guest_ECX) {
2233 case 0x00000000: SET_ABCD(0x04000121, 0x01c0003f,
2234 0x0000003f, 0x00000001); break;
2235 case 0x00000001: SET_ABCD(0x04000122, 0x01c0003f,
2236 0x0000003f, 0x00000001); break;
2237 case 0x00000002: SET_ABCD(0x04004143, 0x03c0003f,
2238 0x00000fff, 0x00000001); break;
2239 default: SET_ABCD(0x00000000, 0x00000000,
2240 0x00000000, 0x00000000); break;
2245 SET_ABCD(0x00000040, 0x00000040, 0x00000003, 0x00000020);
2248 SET_ABCD(0x00000001, 0x00000002, 0x00000001, 0x00000000);
2251 SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2254 SET_ABCD(0x00000400, 0x00000000, 0x00000000, 0x00000000);
2257 SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2260 unhandled_eax_value:
2261 SET_ABCD(0x07280202, 0x00000000, 0x00000000, 0x00000000);
2264 SET_ABCD(0x80000008, 0x00000000, 0x00000000, 0x00000000);
2267 SET_ABCD(0x00000000, 0x00000000, 0x00000001, 0x20100000);
2270 SET_ABCD(0x65746e49, 0x2952286c, 0x726f4320, 0x4d542865);
2273 SET_ABCD(0x43203229, 0x20205550, 0x20202020, 0x20202020);
2276 SET_ABCD(0x30303636, 0x20402020, 0x30342e32, 0x007a4847);
2279 SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2282 SET_ABCD(0x00000000, 0x00000000, 0x10008040, 0x00000000);
2285 SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2288 SET_ABCD(0x00003024, 0x00000000, 0x00000000, 0x00000000);
2291 goto unhandled_eax_value;
2297 /* CALLED FROM GENERATED CODE */
2298 /* DIRTY HELPER (non-referentially-transparent) */
2299 /* Horrible hack. On non-x86 platforms, return 0. */
2300 UInt x86g_dirtyhelper_IN ( UInt portno, UInt sz/*1,2 or 4*/ )
2302 # if defined(__i386__)
2307 __asm__ __volatile__("movl $0,%%eax; inl %w1,%0"
2308 : "=a" (r) : "Nd" (portno));
2311 __asm__ __volatile__("movl $0,%%eax; inw %w1,%w0"
2312 : "=a" (r) : "Nd" (portno));
2315 __asm__ __volatile__("movl $0,%%eax; inb %w1,%b0"
2316 : "=a" (r) : "Nd" (portno));
2328 /* CALLED FROM GENERATED CODE */
2329 /* DIRTY HELPER (non-referentially-transparent) */
2330 /* Horrible hack. On non-x86 platforms, do nothing. */
2331 void x86g_dirtyhelper_OUT ( UInt portno, UInt data, UInt sz/*1,2 or 4*/ )
2333 # if defined(__i386__)
2337 __asm__ __volatile__("outl %0, %w1"
2338 : : "a" (data), "Nd" (portno));
2341 __asm__ __volatile__("outw %w0, %w1"
2342 : : "a" (data), "Nd" (portno));
2345 __asm__ __volatile__("outb %b0, %w1"
2346 : : "a" (data), "Nd" (portno));
2357 /*---------------------------------------------------------------*/
2358 /*--- Helpers for MMX/SSE/SSE2. ---*/
2359 /*---------------------------------------------------------------*/
2361 static inline UChar abdU8 ( UChar xx, UChar yy ) {
2362 return toUChar(xx>yy ? xx-yy : yy-xx);
2365 static inline ULong mk32x2 ( UInt w1, UInt w0 ) {
2366 return (((ULong)w1) << 32) | ((ULong)w0);
2369 static inline UShort sel16x4_3 ( ULong w64 ) {
2370 UInt hi32 = toUInt(w64 >> 32);
2371 return toUShort(hi32 >> 16);
2373 static inline UShort sel16x4_2 ( ULong w64 ) {
2374 UInt hi32 = toUInt(w64 >> 32);
2375 return toUShort(hi32);
2377 static inline UShort sel16x4_1 ( ULong w64 ) {
2378 UInt lo32 = toUInt(w64);
2379 return toUShort(lo32 >> 16);
2381 static inline UShort sel16x4_0 ( ULong w64 ) {
2382 UInt lo32 = toUInt(w64);
2383 return toUShort(lo32);
2386 static inline UChar sel8x8_7 ( ULong w64 ) {
2387 UInt hi32 = toUInt(w64 >> 32);
2388 return toUChar(hi32 >> 24);
2390 static inline UChar sel8x8_6 ( ULong w64 ) {
2391 UInt hi32 = toUInt(w64 >> 32);
2392 return toUChar(hi32 >> 16);
2394 static inline UChar sel8x8_5 ( ULong w64 ) {
2395 UInt hi32 = toUInt(w64 >> 32);
2396 return toUChar(hi32 >> 8);
2398 static inline UChar sel8x8_4 ( ULong w64 ) {
2399 UInt hi32 = toUInt(w64 >> 32);
2400 return toUChar(hi32 >> 0);
2402 static inline UChar sel8x8_3 ( ULong w64 ) {
2403 UInt lo32 = toUInt(w64);
2404 return toUChar(lo32 >> 24);
2406 static inline UChar sel8x8_2 ( ULong w64 ) {
2407 UInt lo32 = toUInt(w64);
2408 return toUChar(lo32 >> 16);
2410 static inline UChar sel8x8_1 ( ULong w64 ) {
2411 UInt lo32 = toUInt(w64);
2412 return toUChar(lo32 >> 8);
2414 static inline UChar sel8x8_0 ( ULong w64 ) {
2415 UInt lo32 = toUInt(w64);
2416 return toUChar(lo32 >> 0);
2419 /* CALLED FROM GENERATED CODE: CLEAN HELPER */
2420 ULong x86g_calculate_mmx_pmaddwd ( ULong xx, ULong yy )
2424 (((Int)(Short)sel16x4_3(xx)) * ((Int)(Short)sel16x4_3(yy)))
2425 + (((Int)(Short)sel16x4_2(xx)) * ((Int)(Short)sel16x4_2(yy))),
2426 (((Int)(Short)sel16x4_1(xx)) * ((Int)(Short)sel16x4_1(yy)))
2427 + (((Int)(Short)sel16x4_0(xx)) * ((Int)(Short)sel16x4_0(yy)))
2431 /* CALLED FROM GENERATED CODE: CLEAN HELPER */
2432 UInt x86g_calculate_mmx_pmovmskb ( ULong xx )
2435 if (xx & (1ULL << (64-1))) r |= (1<<7);
2436 if (xx & (1ULL << (56-1))) r |= (1<<6);
2437 if (xx & (1ULL << (48-1))) r |= (1<<5);
2438 if (xx & (1ULL << (40-1))) r |= (1<<4);
2439 if (xx & (1ULL << (32-1))) r |= (1<<3);
2440 if (xx & (1ULL << (24-1))) r |= (1<<2);
2441 if (xx & (1ULL << (16-1))) r |= (1<<1);
2442 if (xx & (1ULL << ( 8-1))) r |= (1<<0);
2446 /* CALLED FROM GENERATED CODE: CLEAN HELPER */
2447 ULong x86g_calculate_mmx_psadbw ( ULong xx, ULong yy )
2450 t += (UInt)abdU8( sel8x8_7(xx), sel8x8_7(yy) );
2451 t += (UInt)abdU8( sel8x8_6(xx), sel8x8_6(yy) );
2452 t += (UInt)abdU8( sel8x8_5(xx), sel8x8_5(yy) );
2453 t += (UInt)abdU8( sel8x8_4(xx), sel8x8_4(yy) );
2454 t += (UInt)abdU8( sel8x8_3(xx), sel8x8_3(yy) );
2455 t += (UInt)abdU8( sel8x8_2(xx), sel8x8_2(yy) );
2456 t += (UInt)abdU8( sel8x8_1(xx), sel8x8_1(yy) );
2457 t += (UInt)abdU8( sel8x8_0(xx), sel8x8_0(yy) );
2462 /* CALLED FROM GENERATED CODE: CLEAN HELPER */
2463 UInt x86g_calculate_sse_pmovmskb ( ULong w64hi, ULong w64lo )
2465 UInt rHi8 = x86g_calculate_mmx_pmovmskb ( w64hi );
2466 UInt rLo8 = x86g_calculate_mmx_pmovmskb ( w64lo );
2467 return ((rHi8 & 0xFF) << 8) | (rLo8 & 0xFF);
2471 /*---------------------------------------------------------------*/
2472 /*--- Helpers for dealing with segment overrides. ---*/
2473 /*---------------------------------------------------------------*/
2476 UInt get_segdescr_base ( VexGuestX86SegDescr* ent )
2478 UInt lo = 0xFFFF & (UInt)ent->LdtEnt.Bits.BaseLow;
2479 UInt mid = 0xFF & (UInt)ent->LdtEnt.Bits.BaseMid;
2480 UInt hi = 0xFF & (UInt)ent->LdtEnt.Bits.BaseHi;
2481 return (hi << 24) | (mid << 16) | lo;
2485 UInt get_segdescr_limit ( VexGuestX86SegDescr* ent )
2487 UInt lo = 0xFFFF & (UInt)ent->LdtEnt.Bits.LimitLow;
2488 UInt hi = 0xF & (UInt)ent->LdtEnt.Bits.LimitHi;
2489 UInt limit = (hi << 16) | lo;
2490 if (ent->LdtEnt.Bits.Granularity)
2491 limit = (limit << 12) | 0xFFF;
2495 /* CALLED FROM GENERATED CODE: CLEAN HELPER */
2496 ULong x86g_use_seg_selector ( HWord ldt, HWord gdt,
2497 UInt seg_selector, UInt virtual_addr )
2499 UInt tiBit, base, limit;
2500 VexGuestX86SegDescr* the_descrs;
2502 Bool verboze = False;
2504 /* If this isn't true, we're in Big Trouble. */
2505 vassert(8 == sizeof(VexGuestX86SegDescr));
2508 vex_printf("x86h_use_seg_selector: "
2509 "seg_selector = 0x%x, vaddr = 0x%x\n",
2510 seg_selector, virtual_addr);
2512 /* Check for wildly invalid selector. */
2513 if (seg_selector & ~0xFFFF)
2516 seg_selector &= 0x0000FFFF;
2518 /* Sanity check the segment selector. Ensure that RPL=11b (least
2519 privilege). This forms the bottom 2 bits of the selector. */
2520 if ((seg_selector & 3) != 3)
2523 /* Extract the TI bit (0 means GDT, 1 means LDT) */
2524 tiBit = (seg_selector >> 2) & 1;
2526 /* Convert the segment selector onto a table index */
2528 vassert(seg_selector >= 0 && seg_selector < 8192);
2533 /* Do we actually have a GDT to look at? */
2537 /* Check for access to non-existent entry. */
2538 if (seg_selector >= VEX_GUEST_X86_GDT_NENT)
2541 the_descrs = (VexGuestX86SegDescr*)gdt;
2542 base = get_segdescr_base (&the_descrs[seg_selector]);
2543 limit = get_segdescr_limit(&the_descrs[seg_selector]);
2547 /* All the same stuff, except for the LDT. */
2551 if (seg_selector >= VEX_GUEST_X86_LDT_NENT)
2554 the_descrs = (VexGuestX86SegDescr*)ldt;
2555 base = get_segdescr_base (&the_descrs[seg_selector]);
2556 limit = get_segdescr_limit(&the_descrs[seg_selector]);
2560 /* Do the limit check. Note, this check is just slightly too
2561 slack. Really it should be "if (virtual_addr + size - 1 >=
2562 limit)," but we don't have the size info to hand. Getting it
2563 could be significantly complex. */
2564 if (virtual_addr >= limit)
2568 vex_printf("x86h_use_seg_selector: "
2569 "base = 0x%x, addr = 0x%x\n",
2570 base, base + virtual_addr);
2572 /* High 32 bits are zero, indicating success. */
2573 return (ULong)( ((UInt)virtual_addr) + base );
2580 /*---------------------------------------------------------------*/
2581 /*--- Helpers for dealing with, and describing, ---*/
2582 /*--- guest state as a whole. ---*/
2583 /*---------------------------------------------------------------*/
2585 /* Initialise the entire x86 guest state. */
2586 /* VISIBLE TO LIBVEX CLIENT */
2587 void LibVEX_GuestX86_initialise ( /*OUT*/VexGuestX86State* vex_state )
2589 vex_state->guest_EAX = 0;
2590 vex_state->guest_ECX = 0;
2591 vex_state->guest_EDX = 0;
2592 vex_state->guest_EBX = 0;
2593 vex_state->guest_ESP = 0;
2594 vex_state->guest_EBP = 0;
2595 vex_state->guest_ESI = 0;
2596 vex_state->guest_EDI = 0;
2598 vex_state->guest_CC_OP = X86G_CC_OP_COPY;
2599 vex_state->guest_CC_DEP1 = 0;
2600 vex_state->guest_CC_DEP2 = 0;
2601 vex_state->guest_CC_NDEP = 0;
2602 vex_state->guest_DFLAG = 1; /* forwards */
2603 vex_state->guest_IDFLAG = 0;
2604 vex_state->guest_ACFLAG = 0;
2606 vex_state->guest_EIP = 0;
2608 /* Initialise the simulated FPU */
2609 x86g_dirtyhelper_FINIT( vex_state );
2611 /* Initialse the SSE state. */
2612 # define SSEZERO(_xmm) _xmm[0]=_xmm[1]=_xmm[2]=_xmm[3] = 0;
2614 vex_state->guest_SSEROUND = (UInt)Irrm_NEAREST;
2615 SSEZERO(vex_state->guest_XMM0);
2616 SSEZERO(vex_state->guest_XMM1);
2617 SSEZERO(vex_state->guest_XMM2);
2618 SSEZERO(vex_state->guest_XMM3);
2619 SSEZERO(vex_state->guest_XMM4);
2620 SSEZERO(vex_state->guest_XMM5);
2621 SSEZERO(vex_state->guest_XMM6);
2622 SSEZERO(vex_state->guest_XMM7);
2626 vex_state->guest_CS = 0;
2627 vex_state->guest_DS = 0;
2628 vex_state->guest_ES = 0;
2629 vex_state->guest_FS = 0;
2630 vex_state->guest_GS = 0;
2631 vex_state->guest_SS = 0;
2632 vex_state->guest_LDT = 0;
2633 vex_state->guest_GDT = 0;
2635 vex_state->guest_EMWARN = EmWarn_NONE;
2637 /* SSE2 has a 'clflush' cache-line-invalidator which uses these. */
2638 vex_state->guest_TISTART = 0;
2639 vex_state->guest_TILEN = 0;
2641 vex_state->guest_NRADDR = 0;
2642 vex_state->guest_SC_CLASS = 0;
2643 vex_state->guest_IP_AT_SYSCALL = 0;
2645 vex_state->padding1 = 0;
2646 vex_state->padding2 = 0;
2647 vex_state->padding3 = 0;
2651 /* Figure out if any part of the guest state contained in minoff
2652 .. maxoff requires precise memory exceptions. If in doubt return
2653 True (but this is generates significantly slower code).
2655 By default we enforce precise exns for guest %ESP, %EBP and %EIP
2656 only. These are the minimum needed to extract correct stack
2657 backtraces from x86 code.
2659 Bool guest_x86_state_requires_precise_mem_exns ( Int minoff,
2662 Int ebp_min = offsetof(VexGuestX86State, guest_EBP);
2663 Int ebp_max = ebp_min + 4 - 1;
2664 Int esp_min = offsetof(VexGuestX86State, guest_ESP);
2665 Int esp_max = esp_min + 4 - 1;
2666 Int eip_min = offsetof(VexGuestX86State, guest_EIP);
2667 Int eip_max = eip_min + 4 - 1;
2669 if (maxoff < ebp_min || minoff > ebp_max) {
2670 /* no overlap with ebp */
2675 if (maxoff < esp_min || minoff > esp_max) {
2676 /* no overlap with esp */
2681 if (maxoff < eip_min || minoff > eip_max) {
2682 /* no overlap with eip */
2691 #define ALWAYSDEFD(field) \
2692 { offsetof(VexGuestX86State, field), \
2693 (sizeof ((VexGuestX86State*)0)->field) }
2698 /* Total size of the guest state, in bytes. */
2699 .total_sizeB = sizeof(VexGuestX86State),
2701 /* Describe the stack pointer. */
2702 .offset_SP = offsetof(VexGuestX86State,guest_ESP),
2705 /* Describe the frame pointer. */
2706 .offset_FP = offsetof(VexGuestX86State,guest_EBP),
2709 /* Describe the instruction pointer. */
2710 .offset_IP = offsetof(VexGuestX86State,guest_EIP),
2713 /* Describe any sections to be regarded by Memcheck as
2714 'always-defined'. */
2717 /* flags thunk: OP and NDEP are always defd, whereas DEP1
2718 and DEP2 have to be tracked. See detailed comment in
2719 gdefs.h on meaning of thunk fields. */
2721 = { /* 0 */ ALWAYSDEFD(guest_CC_OP),
2722 /* 1 */ ALWAYSDEFD(guest_CC_NDEP),
2723 /* 2 */ ALWAYSDEFD(guest_DFLAG),
2724 /* 3 */ ALWAYSDEFD(guest_IDFLAG),
2725 /* 4 */ ALWAYSDEFD(guest_ACFLAG),
2726 /* 5 */ ALWAYSDEFD(guest_EIP),
2727 /* 6 */ ALWAYSDEFD(guest_FTOP),
2728 /* 7 */ ALWAYSDEFD(guest_FPTAG),
2729 /* 8 */ ALWAYSDEFD(guest_FPROUND),
2730 /* 9 */ ALWAYSDEFD(guest_FC3210),
2731 /* 10 */ ALWAYSDEFD(guest_CS),
2732 /* 11 */ ALWAYSDEFD(guest_DS),
2733 /* 12 */ ALWAYSDEFD(guest_ES),
2734 /* 13 */ ALWAYSDEFD(guest_FS),
2735 /* 14 */ ALWAYSDEFD(guest_GS),
2736 /* 15 */ ALWAYSDEFD(guest_SS),
2737 /* 16 */ ALWAYSDEFD(guest_LDT),
2738 /* 17 */ ALWAYSDEFD(guest_GDT),
2739 /* 18 */ ALWAYSDEFD(guest_EMWARN),
2740 /* 19 */ ALWAYSDEFD(guest_SSEROUND),
2741 /* 20 */ ALWAYSDEFD(guest_TISTART),
2742 /* 21 */ ALWAYSDEFD(guest_TILEN),
2743 /* 22 */ ALWAYSDEFD(guest_SC_CLASS),
2744 /* 23 */ ALWAYSDEFD(guest_IP_AT_SYSCALL)
2749 /*---------------------------------------------------------------*/
2750 /*--- end guest_x86_helpers.c ---*/
2751 /*---------------------------------------------------------------*/