]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/valgrind/src/valgrind-3.6.0-svn/VEX/priv/guest_x86_helpers.c
8178842ad792052830079fd08940a39f62483a91
[l4.git] / l4 / pkg / valgrind / src / valgrind-3.6.0-svn / VEX / priv / guest_x86_helpers.c
1
2 /*---------------------------------------------------------------*/
3 /*--- begin                               guest_x86_helpers.c ---*/
4 /*---------------------------------------------------------------*/
5
6 /*
7    This file is part of Valgrind, a dynamic binary instrumentation
8    framework.
9
10    Copyright (C) 2004-2010 OpenWorks LLP
11       info@open-works.net
12
13    This program is free software; you can redistribute it and/or
14    modify it under the terms of the GNU General Public License as
15    published by the Free Software Foundation; either version 2 of the
16    License, or (at your option) any later version.
17
18    This program is distributed in the hope that it will be useful, but
19    WITHOUT ANY WARRANTY; without even the implied warranty of
20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21    General Public License for more details.
22
23    You should have received a copy of the GNU General Public License
24    along with this program; if not, write to the Free Software
25    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26    02110-1301, USA.
27
28    The GNU General Public License is contained in the file COPYING.
29
30    Neither the names of the U.S. Department of Energy nor the
31    University of California nor the names of its contributors may be
32    used to endorse or promote products derived from this software
33    without prior written permission.
34 */
35
36 #include "libvex_basictypes.h"
37 #include "libvex_emwarn.h"
38 #include "libvex_guest_x86.h"
39 #include "libvex_ir.h"
40 #include "libvex.h"
41
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"
46
47
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
52    all makes sense.  
53
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
57    guest-x86/toIR.c.
58
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.
64 */
65
66
67 /* Set to 1 to get detailed profiling info about use of the flag
68    machinery. */
69 #define PROFILE_EFLAGS 0
70
71
72 /*---------------------------------------------------------------*/
73 /*--- %eflags run-time helpers.                               ---*/
74 /*---------------------------------------------------------------*/
75
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,
109 };
110
111 /* generalised left-shifter */
112 inline static Int lshift ( Int x, Int n )
113 {
114    if (n >= 0)
115       return x << n;
116    else
117       return x >> (-n);
118 }
119
120 /* identity on ULong */
121 static inline ULong idULong ( ULong x )
122 {
123    return x;
124 }
125
126
127 #define PREAMBLE(__data_bits)                                   \
128    /* const */ UInt DATA_MASK                                   \
129       = __data_bits==8 ? 0xFF                                   \
130                        : (__data_bits==16 ? 0xFFFF              \
131                                           : 0xFFFFFFFF);        \
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;                                       \
141    CC_DEP2 = CC_DEP2;                                           \
142    CC_NDEP = CC_NDEP;
143
144
145 /*-------------------------------------------------------------*/
146
147 #define ACTIONS_ADD(DATA_BITS,DATA_UTYPE)                       \
148 {                                                               \
149    PREAMBLE(DATA_BITS);                                         \
150    { Int cf, pf, af, zf, sf, of;                                \
151      Int argL, argR, res;                                       \
152      argL = CC_DEP1;                                            \
153      argR = CC_DEP2;                                            \
154      res  = argL + argR;                                        \
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;                        \
163    }                                                            \
164 }
165
166 /*-------------------------------------------------------------*/
167
168 #define ACTIONS_SUB(DATA_BITS,DATA_UTYPE)                       \
169 {                                                               \
170    PREAMBLE(DATA_BITS);                                         \
171    { Int cf, pf, af, zf, sf, of;                                \
172      Int argL, argR, res;                                       \
173      argL = CC_DEP1;                                            \
174      argR = CC_DEP2;                                            \
175      res  = argL - argR;                                        \
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;                        \
184    }                                                            \
185 }
186
187 /*-------------------------------------------------------------*/
188
189 #define ACTIONS_ADC(DATA_BITS,DATA_UTYPE)                       \
190 {                                                               \
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;                           \
195      argL = CC_DEP1;                                            \
196      argR = CC_DEP2 ^ oldC;                                     \
197      res  = (argL + argR) + oldC;                               \
198      if (oldC)                                                  \
199         cf = (DATA_UTYPE)res <= (DATA_UTYPE)argL;               \
200      else                                                       \
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;                        \
209    }                                                            \
210 }
211
212 /*-------------------------------------------------------------*/
213
214 #define ACTIONS_SBB(DATA_BITS,DATA_UTYPE)                       \
215 {                                                               \
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;                           \
220      argL = CC_DEP1;                                            \
221      argR = CC_DEP2 ^ oldC;                                     \
222      res  = (argL - argR) - oldC;                               \
223      if (oldC)                                                  \
224         cf = (DATA_UTYPE)argL <= (DATA_UTYPE)argR;              \
225      else                                                       \
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;                        \
234    }                                                            \
235 }
236
237 /*-------------------------------------------------------------*/
238
239 #define ACTIONS_LOGIC(DATA_BITS,DATA_UTYPE)                     \
240 {                                                               \
241    PREAMBLE(DATA_BITS);                                         \
242    { Int cf, pf, af, zf, sf, of;                                \
243      cf = 0;                                                    \
244      pf = parity_table[(UChar)CC_DEP1];                         \
245      af = 0;                                                    \
246      zf = ((DATA_UTYPE)CC_DEP1 == 0) << 6;                      \
247      sf = lshift(CC_DEP1, 8 - DATA_BITS) & 0x80;                \
248      of = 0;                                                    \
249      return cf | pf | af | zf | sf | of;                        \
250    }                                                            \
251 }
252
253 /*-------------------------------------------------------------*/
254
255 #define ACTIONS_INC(DATA_BITS,DATA_UTYPE)                       \
256 {                                                               \
257    PREAMBLE(DATA_BITS);                                         \
258    { Int cf, pf, af, zf, sf, of;                                \
259      Int argL, argR, res;                                       \
260      res  = CC_DEP1;                                            \
261      argL = res - 1;                                            \
262      argR = 1;                                                  \
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;                        \
270    }                                                            \
271 }
272
273 /*-------------------------------------------------------------*/
274
275 #define ACTIONS_DEC(DATA_BITS,DATA_UTYPE)                       \
276 {                                                               \
277    PREAMBLE(DATA_BITS);                                         \
278    { Int cf, pf, af, zf, sf, of;                                \
279      Int argL, argR, res;                                       \
280      res  = CC_DEP1;                                            \
281      argL = res + 1;                                            \
282      argR = 1;                                                  \
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;                        \
291    }                                                            \
292 }
293
294 /*-------------------------------------------------------------*/
295
296 #define ACTIONS_SHL(DATA_BITS,DATA_UTYPE)                       \
297 {                                                               \
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)             \
307           & X86G_CC_MASK_O;                                     \
308      return cf | pf | af | zf | sf | of;                        \
309    }                                                            \
310 }
311
312 /*-------------------------------------------------------------*/
313
314 #define ACTIONS_SHR(DATA_BITS,DATA_UTYPE)                       \
315 {                                                               \
316    PREAMBLE(DATA_BITS);                                         \
317    { Int cf, pf, af, zf, sf, of;                                \
318      cf = CC_DEP2 & 1;                                          \
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)             \
325           & X86G_CC_MASK_O;                                     \
326      return cf | pf | af | zf | sf | of;                        \
327    }                                                            \
328 }
329
330 /*-------------------------------------------------------------*/
331
332 /* ROL: cf' = lsb(result).  of' = msb(result) ^ lsb(result). */
333 /* DEP1 = result, NDEP = old flags */
334 #define ACTIONS_ROL(DATA_BITS,DATA_UTYPE)                       \
335 {                                                               \
336    PREAMBLE(DATA_BITS);                                         \
337    { Int fl                                                     \
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,                  \
341                                       11-(DATA_BITS-1))         \
342                      ^ lshift(CC_DEP1, 11)));                   \
343      return fl;                                                 \
344    }                                                            \
345 }
346
347 /*-------------------------------------------------------------*/
348
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)                       \
352 {                                                               \
353    PREAMBLE(DATA_BITS);                                         \
354    { Int fl                                                     \
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,                  \
358                                       11-(DATA_BITS-1))         \
359                      ^ lshift(CC_DEP1, 11-(DATA_BITS-1)+1)));   \
360      return fl;                                                 \
361    }                                                            \
362 }
363
364 /*-------------------------------------------------------------*/
365
366 #define ACTIONS_UMUL(DATA_BITS, DATA_UTYPE,  NARROWtoU,         \
367                                 DATA_U2TYPE, NARROWto2U)        \
368 {                                                               \
369    PREAMBLE(DATA_BITS);                                         \
370    { Int cf, pf, af, zf, sf, of;                                \
371      DATA_UTYPE  hi;                                            \
372      DATA_UTYPE  lo                                             \
373         = NARROWtoU( ((DATA_UTYPE)CC_DEP1)                      \
374                      * ((DATA_UTYPE)CC_DEP2) );                 \
375      DATA_U2TYPE rr                                             \
376         = NARROWto2U(                                           \
377              ((DATA_U2TYPE)((DATA_UTYPE)CC_DEP1))               \
378              * ((DATA_U2TYPE)((DATA_UTYPE)CC_DEP2)) );          \
379      hi = NARROWtoU(rr >>/*u*/ DATA_BITS);                      \
380      cf = (hi != 0);                                            \
381      pf = parity_table[(UChar)lo];                              \
382      af = 0; /* undefined */                                    \
383      zf = (lo == 0) << 6;                                       \
384      sf = lshift(lo, 8 - DATA_BITS) & 0x80;                     \
385      of = cf << 11;                                             \
386      return cf | pf | af | zf | sf | of;                        \
387    }                                                            \
388 }
389
390 /*-------------------------------------------------------------*/
391
392 #define ACTIONS_SMUL(DATA_BITS, DATA_STYPE,  NARROWtoS,         \
393                                 DATA_S2TYPE, NARROWto2S)        \
394 {                                                               \
395    PREAMBLE(DATA_BITS);                                         \
396    { Int cf, pf, af, zf, sf, of;                                \
397      DATA_STYPE  hi;                                            \
398      DATA_STYPE  lo                                             \
399         = NARROWtoS( ((DATA_STYPE)CC_DEP1)                      \
400                      * ((DATA_STYPE)CC_DEP2) );                 \
401      DATA_S2TYPE rr                                             \
402         = NARROWto2S(                                           \
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;                     \
411      of = cf << 11;                                             \
412      return cf | pf | af | zf | sf | of;                        \
413    }                                                            \
414 }
415
416
417 #if PROFILE_EFLAGS
418
419 static Bool initted     = False;
420
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;
431
432 #define SHOW_COUNTS_NOW (0 == (0x3FFFFF & (n_calc_all+n_calc_c+n_calc_cond)))
433
434
435 static void showCounts ( void )
436 {
437    Int op, co;
438    Char ch;
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);
441
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++) {
447
448       ch = ' ';
449       if (op > 0 && (op-1) % 3 == 0) 
450          ch = 'B';
451       if (op > 0 && (op-1) % 3 == 1) 
452          ch = 'W';
453       if (op > 0 && (op-1) % 3 == 2) 
454          ch = 'L';
455
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];
461          if (n >= 1000) {
462             vex_printf(" %3dK", n / 1000);
463          } else 
464          if (n >= 0) {
465             vex_printf(" %3d ", n );
466          } else {
467             vex_printf("     ");
468          }
469       }
470       vex_printf("\n");
471    }
472    vex_printf("\n");
473 }
474
475 static void initCounts ( void )
476 {
477    Int op, co;
478    initted = True;
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;
483    }
484 }
485
486 #endif /* PROFILE_EFLAGS */
487
488
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. */
492 static
493 UInt x86g_calculate_eflags_all_WRK ( UInt cc_op, 
494                                      UInt cc_dep1_formal, 
495                                      UInt cc_dep2_formal,
496                                      UInt cc_ndep_formal )
497 {
498    switch (cc_op) {
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);
503
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   );
507
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   );
511
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   );
515
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   );
519
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   );
523
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   );
527
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   );
531
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   );
535
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   );
539
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   );
543
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   );
547
548       case X86G_CC_OP_UMULB:  ACTIONS_UMUL(  8, UChar,  toUChar,
549                                                 UShort, toUShort );
550       case X86G_CC_OP_UMULW:  ACTIONS_UMUL( 16, UShort, toUShort,
551                                                 UInt,   toUInt );
552       case X86G_CC_OP_UMULL:  ACTIONS_UMUL( 32, UInt,   toUInt,
553                                                 ULong,  idULong );
554
555       case X86G_CC_OP_SMULB:  ACTIONS_SMUL(  8, Char,   toUChar,
556                                                 Short,  toUShort );
557       case X86G_CC_OP_SMULW:  ACTIONS_SMUL( 16, Short,  toUShort, 
558                                                 Int,    toUInt   );
559       case X86G_CC_OP_SMULL:  ACTIONS_SMUL( 32, Int,    toUInt,
560                                                 Long,   idULong );
561
562       default:
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)");
568    }
569 }
570
571
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, 
575                                  UInt cc_dep1, 
576                                  UInt cc_dep2,
577                                  UInt cc_ndep )
578 {
579 #  if PROFILE_EFLAGS
580    if (!initted) initCounts();
581    n_calc_all++;
582    if (SHOW_COUNTS_NOW) showCounts();
583 #  endif
584    return
585       x86g_calculate_eflags_all_WRK ( cc_op, cc_dep1, cc_dep2, cc_ndep );
586 }
587
588
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, 
593                                UInt cc_dep1, 
594                                UInt cc_dep2,
595                                UInt cc_ndep )
596 {
597 #  if PROFILE_EFLAGS
598    if (!initted) initCounts();
599    n_calc_c++;
600    tabc_fast[cc_op]++;
601    if (SHOW_COUNTS_NOW) showCounts();
602 #  endif
603
604    /* Fast-case some common ones. */
605    switch (cc_op) {
606       case X86G_CC_OP_LOGICL: 
607       case X86G_CC_OP_LOGICW: 
608       case X86G_CC_OP_LOGICB:
609          return 0;
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;
622       default: 
623          break;
624    }
625
626 #  if PROFILE_EFLAGS
627    tabc_fast[cc_op]--;
628    tabc_slow[cc_op]++;
629 #  endif
630
631    return x86g_calculate_eflags_all_WRK(cc_op,cc_dep1,cc_dep2,cc_ndep) 
632           & X86G_CC_MASK_C;
633 }
634
635
636 /* CALLED FROM GENERATED CODE: CLEAN HELPER */
637 /* returns 1 or 0 */
638 UInt x86g_calculate_condition ( UInt/*X86Condcode*/ cond, 
639                                 UInt cc_op, 
640                                 UInt cc_dep1, 
641                                 UInt cc_dep2,
642                                 UInt cc_ndep )
643 {
644    UInt eflags = x86g_calculate_eflags_all_WRK(cc_op, cc_dep1, 
645                                                cc_dep2, cc_ndep);
646    UInt of,sf,zf,cf,pf;
647    UInt inv = cond & 1;
648
649 #  if PROFILE_EFLAGS
650    if (!initted) initCounts();
651    tab_cond[cc_op][cond]++;
652    n_calc_cond++;
653    if (SHOW_COUNTS_NOW) showCounts();
654 #  endif
655
656    switch (cond) {
657       case X86CondNO:
658       case X86CondO: /* OF == 1 */
659          of = eflags >> X86G_CC_SHIFT_O;
660          return 1 & (inv ^ of);
661
662       case X86CondNZ:
663       case X86CondZ: /* ZF == 1 */
664          zf = eflags >> X86G_CC_SHIFT_Z;
665          return 1 & (inv ^ zf);
666
667       case X86CondNB:
668       case X86CondB: /* CF == 1 */
669          cf = eflags >> X86G_CC_SHIFT_C;
670          return 1 & (inv ^ cf);
671          break;
672
673       case X86CondNBE:
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));
678          break;
679
680       case X86CondNS:
681       case X86CondS: /* SF == 1 */
682          sf = eflags >> X86G_CC_SHIFT_S;
683          return 1 & (inv ^ sf);
684
685       case X86CondNP:
686       case X86CondP: /* PF == 1 */
687          pf = eflags >> X86G_CC_SHIFT_P;
688          return 1 & (inv ^ pf);
689
690       case X86CondNL:
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));
695          break;
696
697       case X86CondNLE:
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));
703          break;
704
705       default:
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");
710    }
711 }
712
713
714 /* VISIBLE TO LIBVEX CLIENT */
715 UInt LibVEX_GuestX86_get_eflags ( /*IN*/VexGuestX86State* vex_state )
716 {
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
722                  );
723    UInt dflag = vex_state->guest_DFLAG;
724    vassert(dflag == 1 || dflag == 0xFFFFFFFF);
725    if (dflag == 0xFFFFFFFF)
726       eflags |= (1<<10);
727    if (vex_state->guest_IDFLAG == 1)
728       eflags |= (1<<21);
729    if (vex_state->guest_ACFLAG == 1)
730       eflags |= (1<<18);
731                                              
732    return eflags;
733 }
734
735 /* VISIBLE TO LIBVEX CLIENT */
736 void
737 LibVEX_GuestX86_put_eflag_c ( UInt new_carry_flag,
738                               /*MOD*/VexGuestX86State* vex_state )
739 {
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
745                  );
746    if (new_carry_flag & 1) {
747       oszacp |= X86G_CC_MASK_C;
748    } else {
749       oszacp &= ~X86G_CC_MASK_C;
750    }
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;
755 }
756
757
758 /*---------------------------------------------------------------*/
759 /*--- %eflags translation-time function specialisers.         ---*/
760 /*--- These help iropt specialise calls the above run-time    ---*/
761 /*--- %eflags functions.                                      ---*/
762 /*---------------------------------------------------------------*/
763
764 /* Used by the optimiser to try specialisations.  Returns an
765    equivalent expression, or NULL if none. */
766
767 static inline Bool isU32 ( IRExpr* e, UInt n )
768 {
769    return 
770       toBool( e->tag == Iex_Const
771               && e->Iex.Const.con->tag == Ico_U32
772               && e->Iex.Const.con->Ico.U32 == n );
773 }
774
775 IRExpr* guest_x86_spechelper ( HChar* function_name,
776                                IRExpr** args )
777 {
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))
782
783    Int i, arity = 0;
784    for (i = 0; args[i]; i++)
785       arity++;
786 #  if 0
787    vex_printf("spec request:\n");
788    vex_printf("   %s  ", function_name);
789    for (i = 0; i < arity; i++) {
790       vex_printf("  ");
791       ppIRExpr(args[i]);
792    }
793    vex_printf("\n");
794 #  endif
795
796    /* --------- specialising "x86g_calculate_condition" --------- */
797
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;
801       vassert(arity == 5);
802       cond    = args[0];
803       cc_op   = args[1];
804       cc_dep1 = args[2];
805       cc_dep2 = args[3];
806
807       /*---------------- ADDL ----------------*/
808
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,
812                      binop(Iop_CmpEQ32, 
813                            binop(Iop_Add32, cc_dep1, cc_dep2),
814                            mkU32(0)));
815       }
816
817       /*---------------- SUBL ----------------*/
818
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));
823       }
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));
828       }
829
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));
835       }
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,
840                       unop(Iop_1Uto32,
841                            binop(Iop_CmpLT32S, cc_dep1, cc_dep2)),
842                       mkU32(1));
843       }
844
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));
850       }
851       if (isU32(cc_op, X86G_CC_OP_SUBL) && isU32(cond, X86CondNLE)) {
852          /* long sub/cmp, then NLE (signed not less than or equal)
853             --> test dst >s src 
854             --> test !(dst <=s src) */
855          return binop(Iop_Xor32,
856                       unop(Iop_1Uto32,
857                            binop(Iop_CmpLE32S, cc_dep1, cc_dep2)),
858                       mkU32(1));
859       }
860
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));
866       }
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,
871                       unop(Iop_1Uto32,
872                            binop(Iop_CmpLE32U, cc_dep1, cc_dep2)),
873                       mkU32(1));
874       }
875
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));
881       }
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,
886                       unop(Iop_1Uto32,
887                            binop(Iop_CmpLT32U, cc_dep1, cc_dep2)),
888                       mkU32(1));
889       }
890
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,
894                      binop(Iop_CmpLT32S, 
895                            binop(Iop_Sub32, cc_dep1, cc_dep2),
896                            mkU32(0)));
897       }
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,
901                       unop(Iop_1Uto32,
902                            binop(Iop_CmpLT32S, 
903                                  binop(Iop_Sub32, cc_dep1, cc_dep2),
904                                  mkU32(0))),
905                       mkU32(1));
906       }
907
908       /*---------------- SUBW ----------------*/
909
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,
913                      binop(Iop_CmpEQ16, 
914                            unop(Iop_32to16,cc_dep1), 
915                            unop(Iop_32to16,cc_dep2)));
916       }
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,
920                      binop(Iop_CmpNE16, 
921                            unop(Iop_32to16,cc_dep1), 
922                            unop(Iop_32to16,cc_dep2)));
923       }
924
925       /*---------------- SUBB ----------------*/
926
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,
930                      binop(Iop_CmpEQ8, 
931                            unop(Iop_32to8,cc_dep1), 
932                            unop(Iop_32to8,cc_dep2)));
933       }
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,
937                      binop(Iop_CmpNE8, 
938                            unop(Iop_32to8,cc_dep1), 
939                            unop(Iop_32to8,cc_dep2)));
940       }
941
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,
947                      binop(Iop_CmpLT32U, 
948                            binop(Iop_And32,cc_dep2,mkU32(0xFF)),
949                            binop(Iop_And32,cc_dep1,mkU32(0xFF))));
950       }
951
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) 
955                                          --> test dst <s 0
956                                          --> (UInt)dst[7] 
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)),
964                       mkU32(1));
965       }
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) 
969                                           --> test !(dst <s 0)
970                                           --> (UInt) !dst[7] 
971          */
972          return binop(Iop_Xor32,
973                       binop(Iop_And32,
974                             binop(Iop_Shr32,cc_dep1,mkU8(7)),
975                             mkU32(1)),
976                 mkU32(1));
977       }
978
979       /*---------------- LOGICL ----------------*/
980
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)));
984       }
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)));
988       }
989
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 ...
996          */
997          return unop(Iop_1Uto32,binop(Iop_CmpLE32S, cc_dep1, mkU32(0)));
998       }
999
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 ...
1005          */
1006          return unop(Iop_1Uto32,binop(Iop_CmpEQ32, cc_dep1, mkU32(0)));
1007       }
1008
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)),
1014                       mkU32(1));
1015       }
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,
1020                 binop(Iop_And32,
1021                       binop(Iop_Shr32,cc_dep1,mkU8(31)),
1022                       mkU32(1)),
1023                 mkU32(1));
1024       }
1025
1026       /*---------------- LOGICW ----------------*/
1027
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)), 
1032                                         mkU32(0)));
1033       }
1034
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)),
1040                       mkU32(1));
1041       }
1042
1043       /*---------------- LOGICB ----------------*/
1044
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)), 
1049                                         mkU32(0)));
1050       }
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)), 
1057                                         mkU32(0)));
1058       }
1059
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)),
1070                       mkU32(1));
1071       }
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,
1076                 binop(Iop_And32,
1077                       binop(Iop_Shr32,cc_dep1,mkU8(7)),
1078                       mkU32(1)),
1079                 mkU32(1));
1080       }
1081
1082       /*---------------- DECL ----------------*/
1083
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)));
1087       }
1088
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)));
1092       }
1093
1094       /*---------------- DECW ----------------*/
1095
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,
1099                      binop(Iop_CmpEQ32, 
1100                            binop(Iop_Shl32,cc_dep1,mkU8(16)), 
1101                            mkU32(0)));
1102       }
1103
1104       /*---------------- INCW ----------------*/
1105
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,
1110                      binop(Iop_CmpEQ32, 
1111                            binop(Iop_Shl32,cc_dep1,mkU8(16)),
1112                            mkU32(0)));
1113       }
1114
1115       /*---------------- SHRL ----------------*/
1116
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)));
1120       }
1121
1122       /*---------------- COPY ----------------*/
1123       /* This can happen, as a result of x87 FP compares: "fcom ... ;
1124          fnstsw %ax ; sahf ; jbe" for example. */
1125
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 
1129             (C or Z) == 1. */
1130          /* COPY, then NBE --> extract C and Z from dep1, and test
1131             (C or Z) == 0. */
1132          UInt nnn = isU32(cond, X86CondBE) ? 1 : 0;
1133          return
1134             unop(
1135                Iop_1Uto32,
1136                binop(
1137                   Iop_CmpEQ32,
1138                   binop(
1139                      Iop_And32,
1140                      binop(
1141                         Iop_Or32,
1142                         binop(Iop_Shr32, cc_dep1, mkU8(X86G_CC_SHIFT_C)),
1143                         binop(Iop_Shr32, cc_dep1, mkU8(X86G_CC_SHIFT_Z))
1144                      ),
1145                      mkU32(1)
1146                   ),
1147                   mkU32(nnn)
1148                )
1149             );
1150       }
1151       
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;
1157          return
1158             unop(
1159                Iop_1Uto32,
1160                binop(
1161                   Iop_CmpEQ32,
1162                   binop(
1163                      Iop_And32,
1164                      binop(Iop_Shr32, cc_dep1, mkU8(X86G_CC_SHIFT_C)),
1165                      mkU32(1)
1166                   ),
1167                   mkU32(nnn)
1168                )
1169             );
1170       }
1171
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;
1177          return
1178             unop(
1179                Iop_1Uto32,
1180                binop(
1181                   Iop_CmpEQ32,
1182                   binop(
1183                      Iop_And32,
1184                      binop(Iop_Shr32, cc_dep1, mkU8(X86G_CC_SHIFT_Z)),
1185                      mkU32(1)
1186                   ),
1187                   mkU32(nnn)
1188                )
1189             );
1190       }
1191
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;
1197          return
1198             unop(
1199                Iop_1Uto32,
1200                binop(
1201                   Iop_CmpEQ32,
1202                   binop(
1203                      Iop_And32,
1204                      binop(Iop_Shr32, cc_dep1, mkU8(X86G_CC_SHIFT_P)),
1205                      mkU32(1)
1206                   ),
1207                   mkU32(nnn)
1208                )
1209             );
1210       }
1211
1212       return NULL;
1213    }
1214
1215    /* --------- specialising "x86g_calculate_eflags_c" --------- */
1216
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);
1221       cc_op   = args[0];
1222       cc_dep1 = args[1];
1223       cc_dep2 = args[2];
1224       cc_ndep = args[3];
1225
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));
1230       }
1231       if (isU32(cc_op, X86G_CC_OP_SUBB)) {
1232          /* C after sub denotes unsigned less than */
1233          return unop(Iop_1Uto32,
1234                      binop(Iop_CmpLT32U, 
1235                            binop(Iop_And32,cc_dep1,mkU32(0xFF)),
1236                            binop(Iop_And32,cc_dep2,mkU32(0xFF))));
1237       }
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 */
1242          return mkU32(0);
1243       }
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. */
1246          return cc_ndep;
1247       }
1248       if (isU32(cc_op, X86G_CC_OP_COPY)) {
1249          /* cflag after COPY is stored in DEP1. */
1250          return
1251             binop(
1252                Iop_And32,
1253                binop(Iop_Shr32, cc_dep1, mkU8(X86G_CC_SHIFT_C)),
1254                mkU32(1)
1255             );
1256       }
1257       if (isU32(cc_op, X86G_CC_OP_ADDL)) {
1258          /* C after add denotes sum <u either arg */
1259          return unop(Iop_1Uto32,
1260                      binop(Iop_CmpLT32U, 
1261                            binop(Iop_Add32, cc_dep1, cc_dep2), 
1262                            cc_dep1));
1263       }
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.*/
1272       //   return 
1273       //      unop(Iop_1Uto32,
1274       //           binop(Iop_CmpNE32, 
1275       //                 unop(Iop_64HIto32,
1276       //                      binop(Iop_MullS32, cc_dep1, cc_dep2)),
1277       //                 binop(Iop_Sar32,
1278       //                       binop(Iop_Mul32, cc_dep1, cc_dep2), mkU8(31)) ));
1279       //}
1280 #     if 0
1281       if (cc_op->tag == Iex_Const) {
1282          vex_printf("CFLAG "); ppIRExpr(cc_op); vex_printf("\n");
1283       }
1284 #     endif
1285
1286       return NULL;
1287    }
1288
1289    /* --------- specialising "x86g_calculate_eflags_all" --------- */
1290
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);
1295       cc_op   = args[0];
1296       cc_dep1 = args[1];
1297       /* cc_dep2 = args[2]; */
1298       /* cc_ndep = args[3]; */
1299
1300       if (isU32(cc_op, X86G_CC_OP_COPY)) {
1301          /* eflags after COPY are stored in DEP1. */
1302          return
1303             binop(
1304                Iop_And32,
1305                cc_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)
1308             );
1309       }
1310       return NULL;
1311    }
1312
1313 #  undef unop
1314 #  undef binop
1315 #  undef mkU32
1316 #  undef mkU8
1317
1318    return NULL;
1319 }
1320
1321
1322 /*---------------------------------------------------------------*/
1323 /*--- Supporting functions for x87 FPU activities.            ---*/
1324 /*---------------------------------------------------------------*/
1325
1326 static inline Bool host_is_little_endian ( void )
1327 {
1328    UInt x = 0x76543210;
1329    UChar* p = (UChar*)(&x);
1330    return toBool(*p == 0x10);
1331 }
1332
1333 /* 80 and 64-bit floating point formats:
1334
1335    80-bit:
1336
1337     S  0       0-------0      zero
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
1343
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,
1347    giving 80 in total.
1348
1349    64-bit avoids the confusion of an explicitly represented leading 1
1350    and so is simpler:
1351
1352     S  0      0------0   zero
1353     S  0      X------X   denormals
1354     S  1-7FE  any        normals
1355     S  7FF    0------0   infinity
1356     S  7FF    0X-----X   snan
1357     S  7FF    1X-----X   qnan
1358
1359    Exponent is 11 bits, fractional part is 52 bits, and there is a 
1360    sign bit, giving 64 in total.
1361 */
1362
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 ) 
1366 {
1367    Bool   mantissaIsZero;
1368    Int    bexp;
1369    UChar  sign;
1370    UChar* f64;
1371
1372    vassert(host_is_little_endian());
1373
1374    /* vex_printf("calculate_FXAM ( %d, %llx ) .. ", tag, dbl ); */
1375
1376    f64  = (UChar*)(&dbl);
1377    sign = toUChar( (f64[7] >> 7) & 1 );
1378
1379    /* First off, if the tag indicates the register was empty,
1380       return 1,0,sign,1 */
1381    if (tag == 0) {
1382       /* vex_printf("Empty\n"); */
1383       return X86G_FC_MASK_C3 | 0 | (sign << X86G_FC_SHIFT_C1) 
1384                                  | X86G_FC_MASK_C0;
1385    }
1386
1387    bexp = (f64[7] << 4) | ((f64[6] >> 4) & 0x0F);
1388    bexp &= 0x7FF;
1389
1390    mantissaIsZero
1391       = toBool(
1392            (f64[6] & 0x0F) == 0 
1393            && (f64[5] | f64[4] | f64[3] | f64[2] | f64[1] | f64[0]) == 0
1394         );
1395
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;
1402    }
1403    
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;
1410    }
1411
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) 
1417                                  | X86G_FC_MASK_C0;
1418    }
1419
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;
1425    }
1426
1427    /* Uh, ok, we give up.  It must be a normal finite number.
1428       Return 0,1,sign,0.
1429    */
1430    /* vex_printf("normal\n"); */
1431    return 0 | X86G_FC_MASK_C2 | (sign << X86G_FC_SHIFT_C1) | 0;
1432 }
1433
1434
1435 /* CALLED FROM GENERATED CODE */
1436 /* DIRTY HELPER (reads guest memory) */
1437 ULong x86g_dirtyhelper_loadF80le ( UInt addrU )
1438 {
1439    ULong f64;
1440    convert_f80le_to_f64le ( (UChar*)ULong_to_Ptr(addrU), (UChar*)&f64 );
1441    return f64;
1442 }
1443
1444 /* CALLED FROM GENERATED CODE */
1445 /* DIRTY HELPER (writes guest memory) */
1446 void x86g_dirtyhelper_storeF80le ( UInt addrU, ULong f64 )
1447 {
1448    convert_f64le_to_f80le( (UChar*)&f64, (UChar*)ULong_to_Ptr(addrU) );
1449 }
1450
1451
1452 /*----------------------------------------------*/
1453 /*--- The exported fns ..                    ---*/
1454 /*----------------------------------------------*/
1455
1456 /* Layout of the real x87 state. */
1457 /* 13 June 05: Fpu_State and auxiliary constants was moved to
1458    g_generic_x87.h */
1459
1460
1461 /* CLEAN HELPER */
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. 
1465 */
1466 ULong x86g_check_fldcw ( UInt fpucw )
1467 {
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;
1471
1472    /* Detect any required emulation warnings. */
1473    VexEmWarn ew = EmWarn_NONE;
1474
1475    if ((fpucw & 0x3F) != 0x3F) {
1476       /* unmasked exceptions! */
1477       ew = EmWarn_X86_x87exns;
1478    }
1479    else 
1480    if (((fpucw >> 8) & 3) != 3) {
1481       /* unsupported precision */
1482       ew = EmWarn_X86_x87precision;
1483    }
1484
1485    return (((ULong)ew) << 32) | ((ULong)rmode);
1486 }
1487
1488 /* CLEAN HELPER */
1489 /* Given fpround as an IRRoundingMode value, create a suitable x87
1490    native format FPU control word. */
1491 UInt x86g_create_fpucw ( UInt fpround )
1492 {
1493    fpround &= 3;
1494    return 0x037F | (fpround << 10);
1495 }
1496
1497
1498 /* CLEAN HELPER */
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.
1502 */
1503 ULong x86g_check_ldmxcsr ( UInt mxcsr )
1504 {
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;
1508
1509    /* Detect any required emulation warnings. */
1510    VexEmWarn ew = EmWarn_NONE;
1511
1512    if ((mxcsr & 0x1F80) != 0x1F80) {
1513       /* unmasked exceptions! */
1514       ew = EmWarn_X86_sseExns;
1515    }
1516    else 
1517    if (mxcsr & (1<<15)) {
1518       /* FZ is set */
1519       ew = EmWarn_X86_fz;
1520    } 
1521    else
1522    if (mxcsr & (1<<6)) {
1523       /* DAZ is set */
1524       ew = EmWarn_X86_daz;
1525    }
1526
1527    return (((ULong)ew) << 32) | ((ULong)rmode);
1528 }
1529
1530
1531 /* CLEAN HELPER */
1532 /* Given sseround as an IRRoundingMode value, create a suitable SSE
1533    native format MXCSR value. */
1534 UInt x86g_create_mxcsr ( UInt sseround )
1535 {
1536    sseround &= 3;
1537    return 0x1F80 | (sseround << 13);
1538 }
1539
1540
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 )
1545 {
1546    Int i;
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 */
1551    }
1552    gst->guest_FPROUND = (UInt)Irrm_NEAREST;
1553    gst->guest_FC3210  = 0;
1554 }
1555
1556
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. */
1560 static
1561 VexEmWarn do_put_x87 ( Bool moveRegs,
1562                        /*IN*/UChar* x87_state,
1563                        /*OUT*/VexGuestX86State* vex_state )
1564 {
1565    Int        stno, preg;
1566    UInt       tag;
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;
1574    VexEmWarn  ew;
1575    UInt       fpround;
1576    ULong      pair;
1577
1578    /* Copy registers and tags */
1579    for (stno = 0; stno < 8; stno++) {
1580       preg = (stno + ftop) & 7;
1581       tag = (tagw >> (2*preg)) & 3;
1582       if (tag == 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. */
1588          if (moveRegs)
1589             vexRegs[preg] = 0; /* IEEE754 64-bit zero */
1590          vexTags[preg] = 0;
1591       } else {
1592          /* register is non-empty */
1593          if (moveRegs)
1594             convert_f80le_to_f64le( &x87->reg[10*stno], 
1595                                     (UChar*)&vexRegs[preg] );
1596          vexTags[preg] = 1;
1597       }
1598    }
1599
1600    /* stack pointer */
1601    vex_state->guest_FTOP = ftop;
1602
1603    /* status word */
1604    vex_state->guest_FC3210 = c3210;
1605
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);
1611    
1612    vex_state->guest_FPROUND = fpround & 3;
1613
1614    /* emulation warnings --> caller */
1615    return ew;
1616 }
1617
1618
1619 /* Create an x87 FPU state from the guest state, as close as
1620    we can approximate it. */
1621 static
1622 void do_get_x87 ( /*IN*/VexGuestX86State* vex_state,
1623                   /*OUT*/UChar* x87_state )
1624 {
1625    Int        i, stno, preg;
1626    UInt       tagw;
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;
1632
1633    for (i = 0; i < 14; i++)
1634       x87->env[i] = 0;
1635
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 ));
1641
1642    /* Dump the register stack in ST order. */
1643    tagw = 0;
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] );
1651       } else {
1652          /* register is full. */
1653          tagw |= (0 << (2*preg));
1654          convert_f64le_to_f80le( (UChar*)&vexRegs[preg], 
1655                                  &x87->reg[10*stno] );
1656       }
1657    }
1658    x87->env[FP_ENV_TAG] = toUShort(tagw);
1659 }
1660
1661
1662 /* CALLED FROM GENERATED CODE */
1663 /* DIRTY HELPER (reads guest state, writes guest mem) */
1664 void x86g_dirtyhelper_FXSAVE ( VexGuestX86State* gst, HWord addr )
1665 {
1666    /* Somewhat roundabout, but at least it's simple. */
1667    Fpu_State tmp;
1668    UShort*   addrS = (UShort*)addr;
1669    UChar*    addrC = (UChar*)addr;
1670    U128*     xmm   = (U128*)(addr + 160);
1671    UInt      mxcsr;
1672    UShort    fp_tags;
1673    UInt      summary_tags;
1674    Int       r, stno;
1675    UShort    *srcS, *dstS;
1676
1677    do_get_x87( gst, (UChar*)&tmp );
1678    mxcsr = x86g_create_mxcsr( gst->guest_SSEROUND );
1679
1680    /* Now build the proper fxsave image from the x87 image we just
1681       made. */
1682
1683    addrS[0]  = tmp.env[FP_ENV_CTRL]; /* FCW: fpu control word */
1684    addrS[1]  = tmp.env[FP_ENV_STAT]; /* FCW: fpu status word */
1685
1686    /* set addrS[2] in an endian-independent way */
1687    summary_tags = 0;
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);
1692    }
1693    addrC[4]  = toUChar(summary_tags); /* FTW: tag summary byte */
1694    addrC[5]  = 0; /* pad */
1695
1696    addrS[3]  = 0; /* FOP: fpu opcode (bogus) */
1697    addrS[4]  = 0;
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) */
1701
1702    addrS[7]  = 0; /* Intel reserved */
1703
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
1707                      perhaps? */
1708    addrS[11] = 0; /* Intel reserved */
1709
1710    addrS[12] = toUShort(mxcsr);  /* MXCSR */
1711    addrS[13] = toUShort(mxcsr >> 16);
1712
1713    addrS[14] = 0xFFFF; /* MXCSR mask (lo16); who knows what for */
1714    addrS[15] = 0xFFFF; /* MXCSR mask (hi16); who knows what for */
1715
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]);
1720       dstS[0] = srcS[0];
1721       dstS[1] = srcS[1];
1722       dstS[2] = srcS[2];
1723       dstS[3] = srcS[3];
1724       dstS[4] = srcS[4];
1725       dstS[5] = 0;
1726       dstS[6] = 0;
1727       dstS[7] = 0;
1728    }
1729
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());
1734
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]; }   \
1738       while (0)
1739
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 );
1748
1749 #  undef COPY_U128
1750 }
1751
1752
1753 /* CALLED FROM GENERATED CODE */
1754 /* DIRTY HELPER (writes guest state, reads guest mem) */
1755 VexEmWarn x86g_dirtyhelper_FXRSTOR ( VexGuestX86State* gst, HWord addr )
1756 {
1757    Fpu_State tmp;
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);
1763    UShort    fp_tags;
1764    Int       r, stno, i;
1765
1766    /* Restore %xmm0 .. %xmm7.  If the host is big-endian, these need
1767       to be byte-swapped. */
1768    vassert(host_is_little_endian());
1769
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]; }   \
1773       while (0)
1774
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] );
1783
1784 #  undef COPY_U128
1785
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]);
1794       dstS[0] = srcS[0];
1795       dstS[1] = srcS[1];
1796       dstS[2] = srcS[2];
1797       dstS[3] = srcS[3];
1798       dstS[4] = srcS[4];
1799    }
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 */
1803
1804    fp_tags = 0;
1805    for (r = 0; r < 8; r++) {
1806       if (addrC[4] & (1<<r))
1807          fp_tags |= (0 << (2*r)); /* EMPTY */
1808       else 
1809          fp_tags |= (3 << (2*r)); /* VALID -- not really precise enough. */
1810    }
1811    tmp.env[FP_ENV_TAG] = fp_tags;
1812
1813    /* Now write 'tmp' into the guest state. */
1814    warnX87 = do_put_x87( True/*moveRegs*/, (UChar*)&tmp, gst );
1815
1816    { UInt w32 = (((UInt)addrS[12]) & 0xFFFF)
1817                 | ((((UInt)addrS[13]) & 0xFFFF) << 16);
1818      ULong w64 = x86g_check_ldmxcsr( w32 );
1819
1820      warnXMM = (VexEmWarn)(w64 >> 32);
1821
1822      gst->guest_SSEROUND = (UInt)w64;
1823    }
1824
1825    /* Prefer an X87 emwarn over an XMM one, if both exist. */
1826    if (warnX87 != EmWarn_NONE)
1827       return warnX87;
1828    else
1829       return warnXMM;
1830 }
1831
1832
1833 /* CALLED FROM GENERATED CODE */
1834 /* DIRTY HELPER (reads guest state, writes guest mem) */
1835 void x86g_dirtyhelper_FSAVE ( VexGuestX86State* gst, HWord addr )
1836 {
1837    do_get_x87( gst, (UChar*)addr );
1838 }
1839
1840 /* CALLED FROM GENERATED CODE */
1841 /* DIRTY HELPER (writes guest state, reads guest mem) */
1842 VexEmWarn x86g_dirtyhelper_FRSTOR ( VexGuestX86State* gst, HWord addr )
1843 {
1844    return do_put_x87( True/*regs too*/, (UChar*)addr, gst );
1845 }
1846
1847 /* CALLED FROM GENERATED CODE */
1848 /* DIRTY HELPER (reads guest state, writes guest mem) */
1849 void x86g_dirtyhelper_FSTENV ( VexGuestX86State* gst, HWord addr )
1850 {
1851    /* Somewhat roundabout, but at least it's simple. */
1852    Int       i;
1853    UShort*   addrP = (UShort*)addr;
1854    Fpu_State tmp;
1855    do_get_x87( gst, (UChar*)&tmp );
1856    for (i = 0; i < 14; i++)
1857       addrP[i] = tmp.env[i];
1858 }
1859
1860 /* CALLED FROM GENERATED CODE */
1861 /* DIRTY HELPER (writes guest state, reads guest mem) */
1862 VexEmWarn x86g_dirtyhelper_FLDENV ( VexGuestX86State* gst, HWord addr )
1863 {
1864    return do_put_x87( False/*don't move regs*/, (UChar*)addr, gst);
1865 }
1866
1867
1868 /*---------------------------------------------------------------*/
1869 /*--- Misc integer helpers, including rotates and CPUID.      ---*/
1870 /*---------------------------------------------------------------*/
1871
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.
1876 */
1877 ULong x86g_calculate_RCR ( UInt arg, UInt rot_amt, UInt eflags_in, UInt sz )
1878 {
1879    UInt tempCOUNT = rot_amt & 0x1F, cf=0, of=0, tempcf;
1880
1881    switch (sz) {
1882       case 4:
1883          cf        = (eflags_in >> X86G_CC_SHIFT_C) & 1;
1884          of        = ((arg >> 31) ^ cf) & 1;
1885          while (tempCOUNT > 0) {
1886             tempcf = arg & 1;
1887             arg    = (arg >> 1) | (cf << 31);
1888             cf     = tempcf;
1889             tempCOUNT--;
1890          }
1891          break;
1892       case 2:
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) {
1897             tempcf = arg & 1;
1898             arg    = ((arg >> 1) & 0x7FFF) | (cf << 15);
1899             cf     = tempcf;
1900             tempCOUNT--;
1901          }
1902          break;
1903       case 1:
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) {
1908             tempcf = arg & 1;
1909             arg    = ((arg >> 1) & 0x7F) | (cf << 7);
1910             cf     = tempcf;
1911             tempCOUNT--;
1912          }
1913          break;
1914       default: 
1915          vpanic("calculate_RCR: invalid size");
1916    }
1917
1918    cf &= 1;
1919    of &= 1;
1920    eflags_in &= ~(X86G_CC_MASK_C | X86G_CC_MASK_O);
1921    eflags_in |= (cf << X86G_CC_SHIFT_C) | (of << X86G_CC_SHIFT_O);
1922
1923    return (((ULong)eflags_in) << 32) | ((ULong)arg);
1924 }
1925
1926
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.
1931 */
1932 ULong x86g_calculate_RCL ( UInt arg, UInt rot_amt, UInt eflags_in, UInt sz )
1933 {
1934    UInt tempCOUNT = rot_amt & 0x1F, cf=0, of=0, tempcf;
1935
1936    switch (sz) {
1937       case 4:
1938          cf = (eflags_in >> X86G_CC_SHIFT_C) & 1;
1939          while (tempCOUNT > 0) {
1940             tempcf = (arg >> 31) & 1;
1941             arg    = (arg << 1) | (cf & 1);
1942             cf     = tempcf;
1943             tempCOUNT--;
1944          }
1945          of = ((arg >> 31) ^ cf) & 1;
1946          break;
1947       case 2:
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));
1953             cf     = tempcf;
1954             tempCOUNT--;
1955          }
1956          of = ((arg >> 15) ^ cf) & 1;
1957          break;
1958       case 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));
1964             cf     = tempcf;
1965             tempCOUNT--;
1966          }
1967          of = ((arg >> 7) ^ cf) & 1;
1968          break;
1969       default: 
1970          vpanic("calculate_RCL: invalid size");
1971    }
1972
1973    cf &= 1;
1974    of &= 1;
1975    eflags_in &= ~(X86G_CC_MASK_C | X86G_CC_MASK_O);
1976    eflags_in |= (cf << X86G_CC_SHIFT_C) | (of << X86G_CC_SHIFT_O);
1977
1978    return (((ULong)eflags_in) << 32) | ((ULong)arg);
1979 }
1980
1981
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.
1986 */
1987 static UInt calc_parity_8bit ( UInt w32 ) {
1988    UInt i;
1989    UInt p = 1;
1990    for (i = 0; i < 8; i++)
1991       p ^= (1 & (w32 >> i));
1992    return p;
1993 }
1994 UInt x86g_calculate_daa_das_aaa_aas ( UInt flags_and_AX, UInt opcode )
1995 {
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;
2004    UInt result = 0;
2005
2006    switch (opcode) {
2007       case 0x27: { /* DAA */
2008          UInt old_AL = r_AL;
2009          UInt old_C  = r_C;
2010          r_C = 0;
2011          if ((r_AL & 0xF) > 9 || r_A == 1) {
2012             r_AL = r_AL + 6;
2013             r_C  = old_C;
2014             if (r_AL >= 0x100) r_C = 1;
2015             r_A = 1;
2016          } else {
2017             r_A = 0;
2018          }
2019          if (old_AL > 0x99 || old_C == 1) {
2020             r_AL = r_AL + 0x60;
2021             r_C  = 1;
2022          } else {
2023             r_C = 0;
2024          }
2025          /* O is undefined.  S Z and P are set according to the
2026             result. */
2027          r_AL &= 0xFF;
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 );
2032          break;
2033       }
2034       case 0x2F: { /* DAS */
2035          UInt old_AL = r_AL;
2036          UInt old_C  = r_C;
2037          r_C = 0;
2038          if ((r_AL & 0xF) > 9 || r_A == 1) {
2039             Bool borrow = r_AL < 6;
2040             r_AL = r_AL - 6;
2041             r_C  = old_C;
2042             if (borrow) r_C = 1;
2043             r_A = 1;
2044          } else {
2045             r_A = 0;
2046          }
2047          if (old_AL > 0x99 || old_C == 1) {
2048             r_AL = r_AL - 0x60;
2049             r_C  = 1;
2050          } else {
2051             /* Intel docs are wrong: r_C = 0; */
2052          }
2053          /* O is undefined.  S Z and P are set according to the
2054             result. */
2055          r_AL &= 0xFF;
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 );
2060          break;
2061       }
2062       case 0x37: { /* AAA */
2063          Bool nudge = r_AL > 0xF9;
2064          if ((r_AL & 0xF) > 9 || r_A == 1) {
2065             r_AL = r_AL + 6;
2066             r_AH = r_AH + 1 + (nudge ? 1 : 0);
2067             r_A  = 1;
2068             r_C  = 1;
2069             r_AL = r_AL & 0xF;
2070          } else {
2071             r_A  = 0;
2072             r_C  = 0;
2073             r_AL = r_AL & 0xF;
2074          }
2075          /* O S Z and P are undefined. */
2076          r_O = r_S = r_Z = r_P = 0; /* let's say */
2077          break;
2078       }
2079       case 0x3F: { /* AAS */
2080          Bool nudge = r_AL < 0x06;
2081          if ((r_AL & 0xF) > 9 || r_A == 1) {
2082             r_AL = r_AL - 6;
2083             r_AH = r_AH - 1 - (nudge ? 1 : 0);
2084             r_A  = 1;
2085             r_C  = 1;
2086             r_AL = r_AL & 0xF;
2087          } else {
2088             r_A  = 0;
2089             r_C  = 0;
2090             r_AL = r_AL & 0xF;
2091          }
2092          /* O S Z and P are undefined. */
2093          r_O = r_S = r_Z = r_P = 0; /* let's say */
2094          break;
2095       }
2096       default:
2097          vassert(0);
2098    }
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 );
2107    return result;
2108 }
2109
2110
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 )
2115 {
2116 #  if defined(__i386__)
2117    ULong res;
2118    __asm__ __volatile__("rdtsc" : "=A" (res));
2119    return res;
2120 #  else
2121    return 1ULL;
2122 #  endif
2123 }
2124
2125
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 )
2130 {
2131    switch (st->guest_EAX) {
2132       case 0: 
2133          st->guest_EAX = 0x1;
2134          st->guest_EBX = 0x756e6547;
2135          st->guest_ECX = 0x6c65746e;
2136          st->guest_EDX = 0x49656e69;
2137          break;
2138       default:
2139          st->guest_EAX = 0x543;
2140          st->guest_EBX = 0x0;
2141          st->guest_ECX = 0x0;
2142          st->guest_EDX = 0x8001bf;
2143          break;
2144    }
2145 }
2146
2147 /* CALLED FROM GENERATED CODE */
2148 /* DIRTY HELPER (modifies guest state) */
2149 /* Claim to be the following SSE1-capable CPU:
2150    vendor_id       : GenuineIntel
2151    cpu family      : 6
2152    model           : 11
2153    model name      : Intel(R) Pentium(R) III CPU family      1133MHz
2154    stepping        : 1
2155    cpu MHz         : 1131.013
2156    cache size      : 512 KB
2157 */
2158 void x86g_dirtyhelper_CPUID_sse1 ( VexGuestX86State* st )
2159 {
2160    switch (st->guest_EAX) {
2161       case 0: 
2162          st->guest_EAX = 0x00000002;
2163          st->guest_EBX = 0x756e6547;
2164          st->guest_ECX = 0x6c65746e;
2165          st->guest_EDX = 0x49656e69;
2166          break;
2167       case 1: 
2168          st->guest_EAX = 0x000006b1;
2169          st->guest_EBX = 0x00000004;
2170          st->guest_ECX = 0x00000000;
2171          st->guest_EDX = 0x0383fbff;
2172          break;
2173       default:
2174          st->guest_EAX = 0x03020101;
2175          st->guest_EBX = 0x00000000;
2176          st->guest_ECX = 0x00000000;
2177          st->guest_EDX = 0x0c040883;
2178          break;
2179    }
2180 }
2181
2182 /* Claim to be the following SSSE3-capable CPU (2 x ...):
2183    vendor_id       : GenuineIntel
2184    cpu family      : 6
2185    model           : 15
2186    model name      : Intel(R) Core(TM)2 CPU 6600 @ 2.40GHz
2187    stepping        : 6
2188    cpu MHz         : 2394.000
2189    cache size      : 4096 KB
2190    physical id     : 0
2191    siblings        : 2
2192    core id         : 0
2193    cpu cores       : 2
2194    fpu             : yes
2195    fpu_exception   : yes
2196    cpuid level     : 10
2197    wp              : yes
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
2202                      cx16 xtpr lahf_lm
2203    bogomips        : 4798.78
2204    clflush size    : 64
2205    cache_alignment : 64
2206    address sizes   : 36 bits physical, 48 bits virtual
2207    power management:
2208 */
2209 void x86g_dirtyhelper_CPUID_sse2 ( VexGuestX86State* st )
2210 {
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);        \
2216       } while (0)
2217
2218    switch (st->guest_EAX) {
2219       case 0x00000000:
2220          SET_ABCD(0x0000000a, 0x756e6547, 0x6c65746e, 0x49656e69);
2221          break;
2222       case 0x00000001:
2223          SET_ABCD(0x000006f6, 0x00020800, 0x0000e3bd, 0xbfebfbff);
2224          break;
2225       case 0x00000002:
2226          SET_ABCD(0x05b0b101, 0x005657f0, 0x00000000, 0x2cb43049);
2227          break;
2228       case 0x00000003:
2229          SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2230          break;
2231       case 0x00000004: {
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;
2241          }
2242          break;
2243       }
2244       case 0x00000005:
2245          SET_ABCD(0x00000040, 0x00000040, 0x00000003, 0x00000020);
2246          break;
2247       case 0x00000006:
2248          SET_ABCD(0x00000001, 0x00000002, 0x00000001, 0x00000000);
2249          break;
2250       case 0x00000007:
2251          SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2252          break;
2253       case 0x00000008:
2254          SET_ABCD(0x00000400, 0x00000000, 0x00000000, 0x00000000);
2255          break;
2256       case 0x00000009:
2257          SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2258          break;
2259       case 0x0000000a:
2260       unhandled_eax_value:
2261          SET_ABCD(0x07280202, 0x00000000, 0x00000000, 0x00000000);
2262          break;
2263       case 0x80000000:
2264          SET_ABCD(0x80000008, 0x00000000, 0x00000000, 0x00000000);
2265          break;
2266       case 0x80000001:
2267          SET_ABCD(0x00000000, 0x00000000, 0x00000001, 0x20100000);
2268          break;
2269       case 0x80000002:
2270          SET_ABCD(0x65746e49, 0x2952286c, 0x726f4320, 0x4d542865);
2271          break;
2272       case 0x80000003:
2273          SET_ABCD(0x43203229, 0x20205550, 0x20202020, 0x20202020);
2274          break;
2275       case 0x80000004:
2276          SET_ABCD(0x30303636, 0x20402020, 0x30342e32, 0x007a4847);
2277          break;
2278       case 0x80000005:
2279          SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2280          break;
2281       case 0x80000006:
2282          SET_ABCD(0x00000000, 0x00000000, 0x10008040, 0x00000000);
2283          break;
2284       case 0x80000007:
2285          SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2286          break;
2287       case 0x80000008:
2288          SET_ABCD(0x00003024, 0x00000000, 0x00000000, 0x00000000);
2289          break;
2290       default:
2291          goto unhandled_eax_value;
2292    }
2293 #  undef SET_ABCD
2294 }
2295
2296
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*/ )
2301 {
2302 #  if defined(__i386__)
2303    UInt r = 0;
2304    portno &= 0xFFFF;
2305    switch (sz) {
2306       case 4: 
2307          __asm__ __volatile__("movl $0,%%eax; inl %w1,%0" 
2308                               : "=a" (r) : "Nd" (portno));
2309          break;
2310       case 2: 
2311          __asm__ __volatile__("movl $0,%%eax; inw %w1,%w0" 
2312                               : "=a" (r) : "Nd" (portno));
2313          break;
2314       case 1: 
2315          __asm__ __volatile__("movl $0,%%eax; inb %w1,%b0" 
2316                               : "=a" (r) : "Nd" (portno));
2317          break;
2318       default:
2319          break;
2320    }
2321    return r;
2322 #  else
2323    return 0;
2324 #  endif
2325 }
2326
2327
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*/ )
2332 {
2333 #  if defined(__i386__)
2334    portno &= 0xFFFF;
2335    switch (sz) {
2336       case 4: 
2337          __asm__ __volatile__("outl %0, %w1" 
2338                               : : "a" (data), "Nd" (portno));
2339          break;
2340       case 2: 
2341          __asm__ __volatile__("outw %w0, %w1" 
2342                               : : "a" (data), "Nd" (portno));
2343          break;
2344       case 1: 
2345          __asm__ __volatile__("outb %b0, %w1" 
2346                               : : "a" (data), "Nd" (portno));
2347          break;
2348       default:
2349          break;
2350    }
2351 #  else
2352    /* do nothing */
2353 #  endif
2354 }
2355
2356
2357 /*---------------------------------------------------------------*/
2358 /*--- Helpers for MMX/SSE/SSE2.                               ---*/
2359 /*---------------------------------------------------------------*/
2360
2361 static inline UChar abdU8 ( UChar xx, UChar yy ) {
2362    return toUChar(xx>yy ? xx-yy : yy-xx);
2363 }
2364
2365 static inline ULong mk32x2 ( UInt w1, UInt w0 ) {
2366    return (((ULong)w1) << 32) | ((ULong)w0);
2367 }
2368
2369 static inline UShort sel16x4_3 ( ULong w64 ) {
2370    UInt hi32 = toUInt(w64 >> 32);
2371    return toUShort(hi32 >> 16);
2372 }
2373 static inline UShort sel16x4_2 ( ULong w64 ) {
2374    UInt hi32 = toUInt(w64 >> 32);
2375    return toUShort(hi32);
2376 }
2377 static inline UShort sel16x4_1 ( ULong w64 ) {
2378    UInt lo32 = toUInt(w64);
2379    return toUShort(lo32 >> 16);
2380 }
2381 static inline UShort sel16x4_0 ( ULong w64 ) {
2382    UInt lo32 = toUInt(w64);
2383    return toUShort(lo32);
2384 }
2385
2386 static inline UChar sel8x8_7 ( ULong w64 ) {
2387    UInt hi32 = toUInt(w64 >> 32);
2388    return toUChar(hi32 >> 24);
2389 }
2390 static inline UChar sel8x8_6 ( ULong w64 ) {
2391    UInt hi32 = toUInt(w64 >> 32);
2392    return toUChar(hi32 >> 16);
2393 }
2394 static inline UChar sel8x8_5 ( ULong w64 ) {
2395    UInt hi32 = toUInt(w64 >> 32);
2396    return toUChar(hi32 >> 8);
2397 }
2398 static inline UChar sel8x8_4 ( ULong w64 ) {
2399    UInt hi32 = toUInt(w64 >> 32);
2400    return toUChar(hi32 >> 0);
2401 }
2402 static inline UChar sel8x8_3 ( ULong w64 ) {
2403    UInt lo32 = toUInt(w64);
2404    return toUChar(lo32 >> 24);
2405 }
2406 static inline UChar sel8x8_2 ( ULong w64 ) {
2407    UInt lo32 = toUInt(w64);
2408    return toUChar(lo32 >> 16);
2409 }
2410 static inline UChar sel8x8_1 ( ULong w64 ) {
2411    UInt lo32 = toUInt(w64);
2412    return toUChar(lo32 >> 8);
2413 }
2414 static inline UChar sel8x8_0 ( ULong w64 ) {
2415    UInt lo32 = toUInt(w64);
2416    return toUChar(lo32 >> 0);
2417 }
2418
2419 /* CALLED FROM GENERATED CODE: CLEAN HELPER */
2420 ULong x86g_calculate_mmx_pmaddwd ( ULong xx, ULong yy )
2421 {
2422    return
2423       mk32x2( 
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)))
2428       );
2429 }
2430
2431 /* CALLED FROM GENERATED CODE: CLEAN HELPER */
2432 UInt x86g_calculate_mmx_pmovmskb ( ULong xx )
2433 {
2434    UInt r = 0;
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);
2443    return r;
2444 }
2445
2446 /* CALLED FROM GENERATED CODE: CLEAN HELPER */
2447 ULong x86g_calculate_mmx_psadbw ( ULong xx, ULong yy )
2448 {
2449    UInt t = 0;
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) );
2458    t &= 0xFFFF;
2459    return (ULong)t;
2460 }
2461
2462 /* CALLED FROM GENERATED CODE: CLEAN HELPER */
2463 UInt x86g_calculate_sse_pmovmskb ( ULong w64hi, ULong w64lo )
2464 {
2465    UInt rHi8 = x86g_calculate_mmx_pmovmskb ( w64hi );
2466    UInt rLo8 = x86g_calculate_mmx_pmovmskb ( w64lo );
2467    return ((rHi8 & 0xFF) << 8) | (rLo8 & 0xFF);
2468 }
2469
2470
2471 /*---------------------------------------------------------------*/
2472 /*--- Helpers for dealing with segment overrides.             ---*/
2473 /*---------------------------------------------------------------*/
2474
2475 static inline 
2476 UInt get_segdescr_base ( VexGuestX86SegDescr* ent )
2477 {
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;
2482 }
2483
2484 static inline
2485 UInt get_segdescr_limit ( VexGuestX86SegDescr* ent )
2486 {
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;
2492     return limit;
2493 }
2494
2495 /* CALLED FROM GENERATED CODE: CLEAN HELPER */
2496 ULong x86g_use_seg_selector ( HWord ldt, HWord gdt,
2497                               UInt seg_selector, UInt virtual_addr )
2498 {
2499    UInt tiBit, base, limit;
2500    VexGuestX86SegDescr* the_descrs;
2501
2502    Bool verboze = False;
2503
2504    /* If this isn't true, we're in Big Trouble. */
2505    vassert(8 == sizeof(VexGuestX86SegDescr));
2506
2507    if (verboze) 
2508       vex_printf("x86h_use_seg_selector: "
2509                  "seg_selector = 0x%x, vaddr = 0x%x\n", 
2510                  seg_selector, virtual_addr);
2511
2512    /* Check for wildly invalid selector. */
2513    if (seg_selector & ~0xFFFF)
2514       goto bad;
2515
2516    seg_selector &= 0x0000FFFF;
2517   
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)
2521       goto bad;
2522
2523    /* Extract the TI bit (0 means GDT, 1 means LDT) */
2524    tiBit = (seg_selector >> 2) & 1;
2525
2526    /* Convert the segment selector onto a table index */
2527    seg_selector >>= 3;
2528    vassert(seg_selector >= 0 && seg_selector < 8192);
2529
2530    if (tiBit == 0) {
2531
2532       /* GDT access. */
2533       /* Do we actually have a GDT to look at? */
2534       if (gdt == 0)
2535          goto bad;
2536
2537       /* Check for access to non-existent entry. */
2538       if (seg_selector >= VEX_GUEST_X86_GDT_NENT)
2539          goto bad;
2540
2541       the_descrs = (VexGuestX86SegDescr*)gdt;
2542       base  = get_segdescr_base (&the_descrs[seg_selector]);
2543       limit = get_segdescr_limit(&the_descrs[seg_selector]);
2544
2545    } else {
2546
2547       /* All the same stuff, except for the LDT. */
2548       if (ldt == 0)
2549          goto bad;
2550
2551       if (seg_selector >= VEX_GUEST_X86_LDT_NENT)
2552          goto bad;
2553
2554       the_descrs = (VexGuestX86SegDescr*)ldt;
2555       base  = get_segdescr_base (&the_descrs[seg_selector]);
2556       limit = get_segdescr_limit(&the_descrs[seg_selector]);
2557
2558    }
2559
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)
2565       goto bad;
2566
2567    if (verboze) 
2568       vex_printf("x86h_use_seg_selector: "
2569                  "base = 0x%x, addr = 0x%x\n", 
2570                  base, base + virtual_addr);
2571
2572    /* High 32 bits are zero, indicating success. */
2573    return (ULong)( ((UInt)virtual_addr) + base );
2574
2575  bad:
2576    return 1ULL << 32;
2577 }
2578
2579
2580 /*---------------------------------------------------------------*/
2581 /*--- Helpers for dealing with, and describing,               ---*/
2582 /*--- guest state as a whole.                                 ---*/
2583 /*---------------------------------------------------------------*/
2584
2585 /* Initialise the entire x86 guest state. */
2586 /* VISIBLE TO LIBVEX CLIENT */
2587 void LibVEX_GuestX86_initialise ( /*OUT*/VexGuestX86State* vex_state )
2588 {
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;
2597
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;
2605
2606    vex_state->guest_EIP = 0;
2607
2608    /* Initialise the simulated FPU */
2609    x86g_dirtyhelper_FINIT( vex_state );
2610
2611    /* Initialse the SSE state. */
2612 #  define SSEZERO(_xmm) _xmm[0]=_xmm[1]=_xmm[2]=_xmm[3] = 0;
2613
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);
2623
2624 #  undef SSEZERO
2625
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;
2634
2635    vex_state->guest_EMWARN = EmWarn_NONE;
2636
2637    /* SSE2 has a 'clflush' cache-line-invalidator which uses these. */
2638    vex_state->guest_TISTART = 0;
2639    vex_state->guest_TILEN   = 0;
2640
2641    vex_state->guest_NRADDR   = 0;
2642    vex_state->guest_SC_CLASS = 0;
2643    vex_state->guest_IP_AT_SYSCALL = 0;
2644
2645    vex_state->padding1 = 0;
2646    vex_state->padding2 = 0;
2647    vex_state->padding3 = 0;
2648 }
2649
2650
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).  
2654
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.
2658 */
2659 Bool guest_x86_state_requires_precise_mem_exns ( Int minoff, 
2660                                                  Int maxoff)
2661 {
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;
2668
2669    if (maxoff < ebp_min || minoff > ebp_max) {
2670       /* no overlap with ebp */
2671    } else {
2672       return True;
2673    }
2674
2675    if (maxoff < esp_min || minoff > esp_max) {
2676       /* no overlap with esp */
2677    } else {
2678       return True;
2679    }
2680
2681    if (maxoff < eip_min || minoff > eip_max) {
2682       /* no overlap with eip */
2683    } else {
2684       return True;
2685    }
2686
2687    return False;
2688 }
2689
2690
2691 #define ALWAYSDEFD(field)                           \
2692     { offsetof(VexGuestX86State, field),            \
2693       (sizeof ((VexGuestX86State*)0)->field) }
2694
2695 VexGuestLayout
2696    x86guest_layout 
2697       = { 
2698           /* Total size of the guest state, in bytes. */
2699           .total_sizeB = sizeof(VexGuestX86State),
2700
2701           /* Describe the stack pointer. */
2702           .offset_SP = offsetof(VexGuestX86State,guest_ESP),
2703           .sizeof_SP = 4,
2704
2705           /* Describe the frame pointer. */
2706           .offset_FP = offsetof(VexGuestX86State,guest_EBP),
2707           .sizeof_FP = 4,
2708
2709           /* Describe the instruction pointer. */
2710           .offset_IP = offsetof(VexGuestX86State,guest_EIP),
2711           .sizeof_IP = 4,
2712
2713           /* Describe any sections to be regarded by Memcheck as
2714              'always-defined'. */
2715           .n_alwaysDefd = 24,
2716
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. */
2720           .alwaysDefd 
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)
2745                }
2746         };
2747
2748
2749 /*---------------------------------------------------------------*/
2750 /*--- end                                 guest_x86_helpers.c ---*/
2751 /*---------------------------------------------------------------*/