guest_x86_helpers.c revision 2eef773d07df9bbc5d62c0058ae99d5511c2759d
136ca51378f8851635df814230fa23f2c409b9eddsewardj
236ca51378f8851635df814230fa23f2c409b9eddsewardj/*---------------------------------------------------------------*/
336ca51378f8851635df814230fa23f2c409b9eddsewardj/*---                                                         ---*/
4c0ee2edb4563c90bc8f1a83a09984a1fda86d1d3sewardj/*--- This file (guest-x86/ghelpers.c) is                     ---*/
5dbcfae724d5338205befbcd379a48f2303658198sewardj/*--- Copyright (C) OpenWorks LLP.  All rights reserved.      ---*/
636ca51378f8851635df814230fa23f2c409b9eddsewardj/*---                                                         ---*/
736ca51378f8851635df814230fa23f2c409b9eddsewardj/*---------------------------------------------------------------*/
836ca51378f8851635df814230fa23f2c409b9eddsewardj
9f8ed9d874a7b8651654591c68c6d431c758d787csewardj/*
10f8ed9d874a7b8651654591c68c6d431c758d787csewardj   This file is part of LibVEX, a library for dynamic binary
11f8ed9d874a7b8651654591c68c6d431c758d787csewardj   instrumentation and translation.
12f8ed9d874a7b8651654591c68c6d431c758d787csewardj
137bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj   Copyright (C) 2004-2005 OpenWorks LLP.  All rights reserved.
147bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj
157bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj   This library is made available under a dual licensing scheme.
167bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj
177bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj   If you link LibVEX against other code all of which is itself
187bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj   licensed under the GNU General Public License, version 2 dated June
197bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj   1991 ("GPL v2"), then you may use LibVEX under the terms of the GPL
207bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj   v2, as appearing in the file LICENSE.GPL.  If the file LICENSE.GPL
217bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj   is missing, you can obtain a copy of the GPL v2 from the Free
227bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj   Software Foundation Inc., 51 Franklin St, Fifth Floor, Boston, MA
237bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj   02110-1301, USA.
247bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj
257bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj   For any other uses of LibVEX, you must first obtain a commercial
267bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj   license from OpenWorks LLP.  Please contact info@open-works.co.uk
277bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj   for information about commercial licensing.
287bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj
297bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj   This software is provided by OpenWorks LLP "as is" and any express
307bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj   or implied warranties, including, but not limited to, the implied
317bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj   warranties of merchantability and fitness for a particular purpose
327bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj   are disclaimed.  In no event shall OpenWorks LLP be liable for any
337bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj   direct, indirect, incidental, special, exemplary, or consequential
347bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj   damages (including, but not limited to, procurement of substitute
357bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj   goods or services; loss of use, data, or profits; or business
367bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj   interruption) however caused and on any theory of liability,
377bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj   whether in contract, strict liability, or tort (including
387bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj   negligence or otherwise) arising in any way out of the use of this
397bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj   software, even if advised of the possibility of such damage.
40f8ed9d874a7b8651654591c68c6d431c758d787csewardj
41f8ed9d874a7b8651654591c68c6d431c758d787csewardj   Neither the names of the U.S. Department of Energy nor the
42f8ed9d874a7b8651654591c68c6d431c758d787csewardj   University of California nor the names of its contributors may be
43f8ed9d874a7b8651654591c68c6d431c758d787csewardj   used to endorse or promote products derived from this software
44f8ed9d874a7b8651654591c68c6d431c758d787csewardj   without prior written permission.
45f8ed9d874a7b8651654591c68c6d431c758d787csewardj*/
46f8ed9d874a7b8651654591c68c6d431c758d787csewardj
4736ca51378f8851635df814230fa23f2c409b9eddsewardj#include "libvex_basictypes.h"
48893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj#include "libvex_emwarn.h"
490c2cb623cca372a2b42b073121c7413cdaaf75besewardj#include "libvex_guest_x86.h"
5036ca51378f8851635df814230fa23f2c409b9eddsewardj#include "libvex_ir.h"
5149651f4b59b1ab7e0e70cccd34001630eafbe957sewardj#include "libvex.h"
52c0ee2edb4563c90bc8f1a83a09984a1fda86d1d3sewardj
53c0ee2edb4563c90bc8f1a83a09984a1fda86d1d3sewardj#include "main/vex_util.h"
549e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj#include "guest-generic/bb_to_IR.h"
55c0ee2edb4563c90bc8f1a83a09984a1fda86d1d3sewardj#include "guest-x86/gdefs.h"
5652ff4ccb51f48b40a9b0f4884923637e0329a542sewardj#include "guest-generic/g_generic_x87.h"
57c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
58893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
5936ca51378f8851635df814230fa23f2c409b9eddsewardj/* This file contains helper functions for x86 guest code.
6036ca51378f8851635df814230fa23f2c409b9eddsewardj   Calls to these functions are generated by the back end.
6136ca51378f8851635df814230fa23f2c409b9eddsewardj   These calls are of course in the host machine code and
6236ca51378f8851635df814230fa23f2c409b9eddsewardj   this file will be compiled to host machine code, so that
6336ca51378f8851635df814230fa23f2c409b9eddsewardj   all makes sense.
6436ca51378f8851635df814230fa23f2c409b9eddsewardj
6536ca51378f8851635df814230fa23f2c409b9eddsewardj   Only change the signatures of these helper functions very
6636ca51378f8851635df814230fa23f2c409b9eddsewardj   carefully.  If you change the signature here, you'll have to change
6736ca51378f8851635df814230fa23f2c409b9eddsewardj   the parameters passed to it in the IR calls constructed by
682a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   guest-x86/toIR.c.
6989050e58e7bee40892662fe94231aefc33768cf5sewardj
70893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   The convention used is that all functions called from generated
71893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   code are named x86g_<something>, and any function whose name lacks
72893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   that prefix is not called from generated code.  Note that some
73893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   LibVEX_* functions can however be called by VEX's client, but that
74893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   is not the same as calling them from VEX-generated code.
7536ca51378f8851635df814230fa23f2c409b9eddsewardj*/
7636ca51378f8851635df814230fa23f2c409b9eddsewardj
77893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
7884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj/* Set to 1 to get detailed profiling info about use of the flag
7984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   machinery. */
8084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#define PROFILE_EFLAGS 0
8184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
8284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
83893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/*---------------------------------------------------------------*/
84893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/*--- %eflags run-time helpers.                               ---*/
85893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/*---------------------------------------------------------------*/
86893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
87d44bc6e6692dfb0881dcc249bd4ba3d8f8e97fcasewardjstatic const UChar parity_table[256] = {
882a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
892a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
902a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
912a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
922a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
932a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
942a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
952a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
962a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
972a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
982a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
992a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
1002a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
1012a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
1022a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
1032a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
1042a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
1052a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
1062a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
1072a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
1082a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
1092a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
1102a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
1112a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
1122a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
1132a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
1142a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
1152a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
1162a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
1172a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
1182a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
1192a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
12014731f22bf7759d6d23383ca870ac89d9581f1e9sewardj};
12114731f22bf7759d6d23383ca870ac89d9581f1e9sewardj
1224a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj/* generalised left-shifter */
123df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardjinline static Int lshift ( Int x, Int n )
12414731f22bf7759d6d23383ca870ac89d9581f1e9sewardj{
125df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   if (n >= 0)
126df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj      return x << n;
127df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   else
128df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj      return x >> (-n);
12914731f22bf7759d6d23383ca870ac89d9581f1e9sewardj}
13014731f22bf7759d6d23383ca870ac89d9581f1e9sewardj
1314a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj/* identity on ULong */
1324a6f3844a29aebc9774ab0d71418421c14ba9c41sewardjstatic inline ULong idULong ( ULong x )
1334a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj{
1344a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj   return x;
1354a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj}
1364a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj
13714731f22bf7759d6d23383ca870ac89d9581f1e9sewardj
138b9c5cf639b3b21b972599d27207a033afc76ef67sewardj#define PREAMBLE(__data_bits)					\
139df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   /* const */ UInt DATA_MASK 					\
140b9c5cf639b3b21b972599d27207a033afc76ef67sewardj      = __data_bits==8 ? 0xFF 					\
141b9c5cf639b3b21b972599d27207a033afc76ef67sewardj                       : (__data_bits==16 ? 0xFFFF 		\
142b9c5cf639b3b21b972599d27207a033afc76ef67sewardj                                          : 0xFFFFFFFF); 	\
143df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   /* const */ UInt SIGN_MASK = 1 << (__data_bits - 1);		\
1442a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj   /* const */ UInt CC_DEP1 = cc_dep1_formal;			\
1452a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj   /* const */ UInt CC_DEP2 = cc_dep2_formal;			\
1462a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj   /* const */ UInt CC_NDEP = cc_ndep_formal;			\
1472a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj   /* Four bogus assignments, which hopefully gcc can     */	\
148df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   /* optimise away, and which stop it complaining about  */	\
149df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   /* unused variables.                                   */	\
150df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   SIGN_MASK = SIGN_MASK;					\
151df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   DATA_MASK = DATA_MASK;					\
1522a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj   CC_DEP2 = CC_DEP2;						\
1532a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj   CC_NDEP = CC_NDEP;
154df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj
15514731f22bf7759d6d23383ca870ac89d9581f1e9sewardj
156b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
157b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
158df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_ADD(DATA_BITS,DATA_UTYPE)			\
159b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
160b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
1618fc937421c954ff9f707254f028b1fa0410c473dsewardj   { Int cf, pf, af, zf, sf, of;				\
1628fc937421c954ff9f707254f028b1fa0410c473dsewardj     Int argL, argR, res;					\
1638fc937421c954ff9f707254f028b1fa0410c473dsewardj     argL = CC_DEP1;						\
1648fc937421c954ff9f707254f028b1fa0410c473dsewardj     argR = CC_DEP2;						\
1658fc937421c954ff9f707254f028b1fa0410c473dsewardj     res  = argL + argR;					\
1668fc937421c954ff9f707254f028b1fa0410c473dsewardj     cf = (DATA_UTYPE)res < (DATA_UTYPE)argL;			\
1678fc937421c954ff9f707254f028b1fa0410c473dsewardj     pf = parity_table[(UChar)res];				\
1688fc937421c954ff9f707254f028b1fa0410c473dsewardj     af = (res ^ argL ^ argR) & 0x10;				\
1698fc937421c954ff9f707254f028b1fa0410c473dsewardj     zf = ((DATA_UTYPE)res == 0) << 6;				\
1708fc937421c954ff9f707254f028b1fa0410c473dsewardj     sf = lshift(res, 8 - DATA_BITS) & 0x80;			\
1718fc937421c954ff9f707254f028b1fa0410c473dsewardj     of = lshift((argL ^ argR ^ -1) & (argL ^ res), 		\
1722a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                 12 - DATA_BITS) & X86G_CC_MASK_O;		\
1738fc937421c954ff9f707254f028b1fa0410c473dsewardj     return cf | pf | af | zf | sf | of;			\
1748fc937421c954ff9f707254f028b1fa0410c473dsewardj   }								\
1752ef5f2a829433c4ca17f33e1bf993cf16b9e347dsewardj}
1762ef5f2a829433c4ca17f33e1bf993cf16b9e347dsewardj
177b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
178b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
1792a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj#define ACTIONS_SUB(DATA_BITS,DATA_UTYPE)			\
180b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
181b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
1828fc937421c954ff9f707254f028b1fa0410c473dsewardj   { Int cf, pf, af, zf, sf, of;				\
1838fc937421c954ff9f707254f028b1fa0410c473dsewardj     Int argL, argR, res;					\
1848fc937421c954ff9f707254f028b1fa0410c473dsewardj     argL = CC_DEP1;						\
1858fc937421c954ff9f707254f028b1fa0410c473dsewardj     argR = CC_DEP2;						\
1868fc937421c954ff9f707254f028b1fa0410c473dsewardj     res  = argL - argR;					\
1878fc937421c954ff9f707254f028b1fa0410c473dsewardj     cf = (DATA_UTYPE)argL < (DATA_UTYPE)argR;			\
1888fc937421c954ff9f707254f028b1fa0410c473dsewardj     pf = parity_table[(UChar)res];				\
1898fc937421c954ff9f707254f028b1fa0410c473dsewardj     af = (res ^ argL ^ argR) & 0x10;				\
1908fc937421c954ff9f707254f028b1fa0410c473dsewardj     zf = ((DATA_UTYPE)res == 0) << 6;				\
1918fc937421c954ff9f707254f028b1fa0410c473dsewardj     sf = lshift(res, 8 - DATA_BITS) & 0x80;			\
1928fc937421c954ff9f707254f028b1fa0410c473dsewardj     of = lshift((argL ^ argR) & (argL ^ res),	 		\
1932a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                 12 - DATA_BITS) & X86G_CC_MASK_O; 		\
1948fc937421c954ff9f707254f028b1fa0410c473dsewardj     return cf | pf | af | zf | sf | of;			\
1958fc937421c954ff9f707254f028b1fa0410c473dsewardj   }								\
1962ef5f2a829433c4ca17f33e1bf993cf16b9e347dsewardj}
1972ef5f2a829433c4ca17f33e1bf993cf16b9e347dsewardj
198b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
199b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
2002a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj#define ACTIONS_ADC(DATA_BITS,DATA_UTYPE)			\
201b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
202b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
2038fc937421c954ff9f707254f028b1fa0410c473dsewardj   { Int cf, pf, af, zf, sf, of;				\
2048fc937421c954ff9f707254f028b1fa0410c473dsewardj     Int argL, argR, oldC, res;		       			\
2052a9ad023890d3b34cf45e429df2a8ae88b419128sewardj     oldC = CC_NDEP & X86G_CC_MASK_C;				\
2068fc937421c954ff9f707254f028b1fa0410c473dsewardj     argL = CC_DEP1;						\
2078fc937421c954ff9f707254f028b1fa0410c473dsewardj     argR = CC_DEP2 ^ oldC;	       				\
2088fc937421c954ff9f707254f028b1fa0410c473dsewardj     res  = (argL + argR) + oldC;				\
2098fc937421c954ff9f707254f028b1fa0410c473dsewardj     if (oldC)							\
2108fc937421c954ff9f707254f028b1fa0410c473dsewardj        cf = (DATA_UTYPE)res <= (DATA_UTYPE)argL;		\
2118fc937421c954ff9f707254f028b1fa0410c473dsewardj     else							\
2128fc937421c954ff9f707254f028b1fa0410c473dsewardj        cf = (DATA_UTYPE)res < (DATA_UTYPE)argL;		\
2138fc937421c954ff9f707254f028b1fa0410c473dsewardj     pf = parity_table[(UChar)res];				\
2148fc937421c954ff9f707254f028b1fa0410c473dsewardj     af = (res ^ argL ^ argR) & 0x10;				\
2158fc937421c954ff9f707254f028b1fa0410c473dsewardj     zf = ((DATA_UTYPE)res == 0) << 6;				\
2168fc937421c954ff9f707254f028b1fa0410c473dsewardj     sf = lshift(res, 8 - DATA_BITS) & 0x80;			\
2178fc937421c954ff9f707254f028b1fa0410c473dsewardj     of = lshift((argL ^ argR ^ -1) & (argL ^ res), 		\
2182a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                  12 - DATA_BITS) & X86G_CC_MASK_O;		\
2198fc937421c954ff9f707254f028b1fa0410c473dsewardj     return cf | pf | af | zf | sf | of;			\
2208fc937421c954ff9f707254f028b1fa0410c473dsewardj   }								\
2212ef5f2a829433c4ca17f33e1bf993cf16b9e347dsewardj}
2222ef5f2a829433c4ca17f33e1bf993cf16b9e347dsewardj
223b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
224b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
225df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_SBB(DATA_BITS,DATA_UTYPE)			\
226b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
227b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
2288fc937421c954ff9f707254f028b1fa0410c473dsewardj   { Int cf, pf, af, zf, sf, of;				\
2298fc937421c954ff9f707254f028b1fa0410c473dsewardj     Int argL, argR, oldC, res;		       			\
2302a9ad023890d3b34cf45e429df2a8ae88b419128sewardj     oldC = CC_NDEP & X86G_CC_MASK_C;				\
2318fc937421c954ff9f707254f028b1fa0410c473dsewardj     argL = CC_DEP1;						\
2328fc937421c954ff9f707254f028b1fa0410c473dsewardj     argR = CC_DEP2 ^ oldC;	       				\
2338fc937421c954ff9f707254f028b1fa0410c473dsewardj     res  = (argL - argR) - oldC;				\
2348fc937421c954ff9f707254f028b1fa0410c473dsewardj     if (oldC)							\
2358fc937421c954ff9f707254f028b1fa0410c473dsewardj        cf = (DATA_UTYPE)argL <= (DATA_UTYPE)argR;		\
2368fc937421c954ff9f707254f028b1fa0410c473dsewardj     else							\
2378fc937421c954ff9f707254f028b1fa0410c473dsewardj        cf = (DATA_UTYPE)argL < (DATA_UTYPE)argR;		\
2388fc937421c954ff9f707254f028b1fa0410c473dsewardj     pf = parity_table[(UChar)res];				\
2398fc937421c954ff9f707254f028b1fa0410c473dsewardj     af = (res ^ argL ^ argR) & 0x10;				\
2408fc937421c954ff9f707254f028b1fa0410c473dsewardj     zf = ((DATA_UTYPE)res == 0) << 6;				\
2418fc937421c954ff9f707254f028b1fa0410c473dsewardj     sf = lshift(res, 8 - DATA_BITS) & 0x80;			\
2428fc937421c954ff9f707254f028b1fa0410c473dsewardj     of = lshift((argL ^ argR) & (argL ^ res), 			\
2432a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                 12 - DATA_BITS) & X86G_CC_MASK_O;		\
2448fc937421c954ff9f707254f028b1fa0410c473dsewardj     return cf | pf | af | zf | sf | of;			\
2458fc937421c954ff9f707254f028b1fa0410c473dsewardj   }								\
246a238471814bd386aeb58a76718b41e68b1a794b2sewardj}
247a238471814bd386aeb58a76718b41e68b1a794b2sewardj
248b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
249b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
250df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_LOGIC(DATA_BITS,DATA_UTYPE)			\
251b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
252b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
2538fc937421c954ff9f707254f028b1fa0410c473dsewardj   { Int cf, pf, af, zf, sf, of;				\
2548fc937421c954ff9f707254f028b1fa0410c473dsewardj     cf = 0;							\
2558fc937421c954ff9f707254f028b1fa0410c473dsewardj     pf = parity_table[(UChar)CC_DEP1];				\
2568fc937421c954ff9f707254f028b1fa0410c473dsewardj     af = 0;							\
2578fc937421c954ff9f707254f028b1fa0410c473dsewardj     zf = ((DATA_UTYPE)CC_DEP1 == 0) << 6;			\
2588fc937421c954ff9f707254f028b1fa0410c473dsewardj     sf = lshift(CC_DEP1, 8 - DATA_BITS) & 0x80;		\
2598fc937421c954ff9f707254f028b1fa0410c473dsewardj     of = 0;							\
2608fc937421c954ff9f707254f028b1fa0410c473dsewardj     return cf | pf | af | zf | sf | of;			\
2618fc937421c954ff9f707254f028b1fa0410c473dsewardj   }								\
262a238471814bd386aeb58a76718b41e68b1a794b2sewardj}
263a238471814bd386aeb58a76718b41e68b1a794b2sewardj
264b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
265b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
266df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_INC(DATA_BITS,DATA_UTYPE)			\
267b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
268b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
2698fc937421c954ff9f707254f028b1fa0410c473dsewardj   { Int cf, pf, af, zf, sf, of;				\
2708fc937421c954ff9f707254f028b1fa0410c473dsewardj     Int argL, argR, res;					\
2718fc937421c954ff9f707254f028b1fa0410c473dsewardj     res  = CC_DEP1;						\
2728fc937421c954ff9f707254f028b1fa0410c473dsewardj     argL = res - 1;						\
2738fc937421c954ff9f707254f028b1fa0410c473dsewardj     argR = 1;							\
2742a9ad023890d3b34cf45e429df2a8ae88b419128sewardj     cf = CC_NDEP & X86G_CC_MASK_C;				\
2758fc937421c954ff9f707254f028b1fa0410c473dsewardj     pf = parity_table[(UChar)res];				\
2768fc937421c954ff9f707254f028b1fa0410c473dsewardj     af = (res ^ argL ^ argR) & 0x10;				\
2778fc937421c954ff9f707254f028b1fa0410c473dsewardj     zf = ((DATA_UTYPE)res == 0) << 6;				\
2788fc937421c954ff9f707254f028b1fa0410c473dsewardj     sf = lshift(res, 8 - DATA_BITS) & 0x80;			\
2798fc937421c954ff9f707254f028b1fa0410c473dsewardj     of = ((res & DATA_MASK) == SIGN_MASK) << 11;		\
2808fc937421c954ff9f707254f028b1fa0410c473dsewardj     return cf | pf | af | zf | sf | of;			\
2818fc937421c954ff9f707254f028b1fa0410c473dsewardj   }								\
28289050e58e7bee40892662fe94231aefc33768cf5sewardj}
28389050e58e7bee40892662fe94231aefc33768cf5sewardj
284b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
285b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
286df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_DEC(DATA_BITS,DATA_UTYPE)			\
287b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
288b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
2898fc937421c954ff9f707254f028b1fa0410c473dsewardj   { Int cf, pf, af, zf, sf, of;				\
2908fc937421c954ff9f707254f028b1fa0410c473dsewardj     Int argL, argR, res;					\
2918fc937421c954ff9f707254f028b1fa0410c473dsewardj     res  = CC_DEP1;						\
2928fc937421c954ff9f707254f028b1fa0410c473dsewardj     argL = res + 1;						\
2938fc937421c954ff9f707254f028b1fa0410c473dsewardj     argR = 1;							\
2942a9ad023890d3b34cf45e429df2a8ae88b419128sewardj     cf = CC_NDEP & X86G_CC_MASK_C;				\
2958fc937421c954ff9f707254f028b1fa0410c473dsewardj     pf = parity_table[(UChar)res];				\
2968fc937421c954ff9f707254f028b1fa0410c473dsewardj     af = (res ^ argL ^ argR) & 0x10;				\
2978fc937421c954ff9f707254f028b1fa0410c473dsewardj     zf = ((DATA_UTYPE)res == 0) << 6;				\
2988fc937421c954ff9f707254f028b1fa0410c473dsewardj     sf = lshift(res, 8 - DATA_BITS) & 0x80;			\
2998fc937421c954ff9f707254f028b1fa0410c473dsewardj     of = ((res & DATA_MASK) 					\
3008fc937421c954ff9f707254f028b1fa0410c473dsewardj          == ((UInt)SIGN_MASK - 1)) << 11;			\
3018fc937421c954ff9f707254f028b1fa0410c473dsewardj     return cf | pf | af | zf | sf | of;			\
3028fc937421c954ff9f707254f028b1fa0410c473dsewardj   }								\
30389050e58e7bee40892662fe94231aefc33768cf5sewardj}
30489050e58e7bee40892662fe94231aefc33768cf5sewardj
305b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
306b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
307df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_SHL(DATA_BITS,DATA_UTYPE)			\
308b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
309b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
3108fc937421c954ff9f707254f028b1fa0410c473dsewardj   { Int cf, pf, af, zf, sf, of;				\
3112a9ad023890d3b34cf45e429df2a8ae88b419128sewardj     cf = (CC_DEP2 >> (DATA_BITS - 1)) & X86G_CC_MASK_C;	\
3128fc937421c954ff9f707254f028b1fa0410c473dsewardj     pf = parity_table[(UChar)CC_DEP1];				\
3138fc937421c954ff9f707254f028b1fa0410c473dsewardj     af = 0; /* undefined */					\
3148fc937421c954ff9f707254f028b1fa0410c473dsewardj     zf = ((DATA_UTYPE)CC_DEP1 == 0) << 6;			\
3158fc937421c954ff9f707254f028b1fa0410c473dsewardj     sf = lshift(CC_DEP1, 8 - DATA_BITS) & 0x80;		\
3168fc937421c954ff9f707254f028b1fa0410c473dsewardj     /* of is defined if shift count == 1 */			\
3172a9ad023890d3b34cf45e429df2a8ae88b419128sewardj     of = lshift(CC_DEP2 ^ CC_DEP1, 12 - DATA_BITS) 		\
3182a9ad023890d3b34cf45e429df2a8ae88b419128sewardj          & X86G_CC_MASK_O;					\
3198fc937421c954ff9f707254f028b1fa0410c473dsewardj     return cf | pf | af | zf | sf | of;			\
3208fc937421c954ff9f707254f028b1fa0410c473dsewardj   }								\
3215f6303579435ddb8315e11c2f02c904b978782a0sewardj}
3225f6303579435ddb8315e11c2f02c904b978782a0sewardj
323b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
324b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
3252a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj#define ACTIONS_SHR(DATA_BITS,DATA_UTYPE)			\
326b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
327b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);  					\
3288fc937421c954ff9f707254f028b1fa0410c473dsewardj   { Int cf, pf, af, zf, sf, of;				\
3298fc937421c954ff9f707254f028b1fa0410c473dsewardj     cf = CC_DEP2 & 1;						\
3308fc937421c954ff9f707254f028b1fa0410c473dsewardj     pf = parity_table[(UChar)CC_DEP1];				\
3318fc937421c954ff9f707254f028b1fa0410c473dsewardj     af = 0; /* undefined */					\
3328fc937421c954ff9f707254f028b1fa0410c473dsewardj     zf = ((DATA_UTYPE)CC_DEP1 == 0) << 6;			\
3338fc937421c954ff9f707254f028b1fa0410c473dsewardj     sf = lshift(CC_DEP1, 8 - DATA_BITS) & 0x80;		\
3348fc937421c954ff9f707254f028b1fa0410c473dsewardj     /* of is defined if shift count == 1 */			\
3352a9ad023890d3b34cf45e429df2a8ae88b419128sewardj     of = lshift(CC_DEP2 ^ CC_DEP1, 12 - DATA_BITS)		\
3362a9ad023890d3b34cf45e429df2a8ae88b419128sewardj          & X86G_CC_MASK_O;					\
3378fc937421c954ff9f707254f028b1fa0410c473dsewardj     return cf | pf | af | zf | sf | of;			\
3388fc937421c954ff9f707254f028b1fa0410c473dsewardj   }								\
3395f6303579435ddb8315e11c2f02c904b978782a0sewardj}
3405f6303579435ddb8315e11c2f02c904b978782a0sewardj
341b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
342b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
3438ee2de1f5f72c13120f59c0ca6ac8291219123dfsewardj/* ROL: cf' = lsb(result).  of' = msb(result) ^ lsb(result). */
3442a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj/* DEP1 = result, NDEP = old flags */
345df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_ROL(DATA_BITS,DATA_UTYPE)			\
346b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
347b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
3488fc937421c954ff9f707254f028b1fa0410c473dsewardj   { Int fl 							\
3492a9ad023890d3b34cf45e429df2a8ae88b419128sewardj        = (CC_NDEP & ~(X86G_CC_MASK_O | X86G_CC_MASK_C))	\
3502a9ad023890d3b34cf45e429df2a8ae88b419128sewardj          | (X86G_CC_MASK_C & CC_DEP1)				\
3512a9ad023890d3b34cf45e429df2a8ae88b419128sewardj          | (X86G_CC_MASK_O & (lshift(CC_DEP1,  		\
3522a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                                      11-(DATA_BITS-1)) 	\
3538fc937421c954ff9f707254f028b1fa0410c473dsewardj                     ^ lshift(CC_DEP1, 11)));			\
3548fc937421c954ff9f707254f028b1fa0410c473dsewardj     return fl;							\
3558fc937421c954ff9f707254f028b1fa0410c473dsewardj   }								\
3568c7f1abe9e022f6382634efea09c9cac89ec6336sewardj}
3578c7f1abe9e022f6382634efea09c9cac89ec6336sewardj
358b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
359b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
3601813dbeb912870e9a544cae17a3fadbf8d2b0d55sewardj/* ROR: cf' = msb(result).  of' = msb(result) ^ msb-1(result). */
3612a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj/* DEP1 = result, NDEP = old flags */
362df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_ROR(DATA_BITS,DATA_UTYPE)			\
363b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
364b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
3658fc937421c954ff9f707254f028b1fa0410c473dsewardj   { Int fl 							\
3662a9ad023890d3b34cf45e429df2a8ae88b419128sewardj        = (CC_NDEP & ~(X86G_CC_MASK_O | X86G_CC_MASK_C))	\
3672a9ad023890d3b34cf45e429df2a8ae88b419128sewardj          | (X86G_CC_MASK_C & (CC_DEP1 >> (DATA_BITS-1)))	\
3682a9ad023890d3b34cf45e429df2a8ae88b419128sewardj          | (X86G_CC_MASK_O & (lshift(CC_DEP1, 			\
3692a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                                      11-(DATA_BITS-1)) 	\
3708fc937421c954ff9f707254f028b1fa0410c473dsewardj                     ^ lshift(CC_DEP1, 11-(DATA_BITS-1)+1)));	\
3718fc937421c954ff9f707254f028b1fa0410c473dsewardj     return fl;							\
3728fc937421c954ff9f707254f028b1fa0410c473dsewardj   }								\
3731813dbeb912870e9a544cae17a3fadbf8d2b0d55sewardj}
3741813dbeb912870e9a544cae17a3fadbf8d2b0d55sewardj
375b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
376b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
3774a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj#define ACTIONS_UMUL(DATA_BITS, DATA_UTYPE,  NARROWtoU,         \
3784a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj                                DATA_U2TYPE, NARROWto2U)        \
3792a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj{                                                               \
3802a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj   PREAMBLE(DATA_BITS);                                         \
3818fc937421c954ff9f707254f028b1fa0410c473dsewardj   { Int cf, pf, af, zf, sf, of;                                \
3828fc937421c954ff9f707254f028b1fa0410c473dsewardj     DATA_UTYPE  hi;                                            \
3834a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj     DATA_UTYPE  lo                                             \
3844a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj        = NARROWtoU( ((DATA_UTYPE)CC_DEP1)                      \
3854a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj                     * ((DATA_UTYPE)CC_DEP2) );                 \
3864a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj     DATA_U2TYPE rr                                             \
3874a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj        = NARROWto2U(                                           \
3884a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj             ((DATA_U2TYPE)((DATA_UTYPE)CC_DEP1))               \
3894a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj             * ((DATA_U2TYPE)((DATA_UTYPE)CC_DEP2)) );          \
3904a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj     hi = NARROWtoU(rr >>/*u*/ DATA_BITS);                      \
3918fc937421c954ff9f707254f028b1fa0410c473dsewardj     cf = (hi != 0);                                            \
3928fc937421c954ff9f707254f028b1fa0410c473dsewardj     pf = parity_table[(UChar)lo];                              \
3938fc937421c954ff9f707254f028b1fa0410c473dsewardj     af = 0; /* undefined */                                    \
3948fc937421c954ff9f707254f028b1fa0410c473dsewardj     zf = (lo == 0) << 6;                                       \
3958fc937421c954ff9f707254f028b1fa0410c473dsewardj     sf = lshift(lo, 8 - DATA_BITS) & 0x80;                     \
3968fc937421c954ff9f707254f028b1fa0410c473dsewardj     of = cf << 11;                                             \
3978fc937421c954ff9f707254f028b1fa0410c473dsewardj     return cf | pf | af | zf | sf | of;                        \
3988fc937421c954ff9f707254f028b1fa0410c473dsewardj   }								\
39956296d80c9e15ec59eebecf1c3aea9ebd4dac115sewardj}
40056296d80c9e15ec59eebecf1c3aea9ebd4dac115sewardj
401b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
402b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
4034a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj#define ACTIONS_SMUL(DATA_BITS, DATA_STYPE,  NARROWtoS,         \
4044a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj                                DATA_S2TYPE, NARROWto2S)        \
4052a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj{                                                               \
4062a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj   PREAMBLE(DATA_BITS);                                         \
4078fc937421c954ff9f707254f028b1fa0410c473dsewardj   { Int cf, pf, af, zf, sf, of;                                \
4088fc937421c954ff9f707254f028b1fa0410c473dsewardj     DATA_STYPE  hi;                                            \
4094a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj     DATA_STYPE  lo                                             \
4104a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj        = NARROWtoS( ((DATA_STYPE)CC_DEP1)                      \
4114a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj                     * ((DATA_STYPE)CC_DEP2) );                 \
4124a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj     DATA_S2TYPE rr                                             \
4134a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj        = NARROWto2S(                                           \
4144a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj             ((DATA_S2TYPE)((DATA_STYPE)CC_DEP1))               \
4154a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj             * ((DATA_S2TYPE)((DATA_STYPE)CC_DEP2)) );          \
4164a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj     hi = NARROWtoS(rr >>/*s*/ DATA_BITS);                      \
4178fc937421c954ff9f707254f028b1fa0410c473dsewardj     cf = (hi != (lo >>/*s*/ (DATA_BITS-1)));                   \
4188fc937421c954ff9f707254f028b1fa0410c473dsewardj     pf = parity_table[(UChar)lo];                              \
4198fc937421c954ff9f707254f028b1fa0410c473dsewardj     af = 0; /* undefined */                                    \
4208fc937421c954ff9f707254f028b1fa0410c473dsewardj     zf = (lo == 0) << 6;                                       \
4218fc937421c954ff9f707254f028b1fa0410c473dsewardj     sf = lshift(lo, 8 - DATA_BITS) & 0x80;                     \
4228fc937421c954ff9f707254f028b1fa0410c473dsewardj     of = cf << 11;                                             \
4238fc937421c954ff9f707254f028b1fa0410c473dsewardj     return cf | pf | af | zf | sf | of;                        \
4248fc937421c954ff9f707254f028b1fa0410c473dsewardj   }								\
4257ed2295459ac5e788a98dd5570fef0d4645c27d4sewardj}
426741153c4301023a420ab45b8a10b8e1bac968822sewardj
42736ca51378f8851635df814230fa23f2c409b9eddsewardj
42884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#if PROFILE_EFLAGS
42984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
4309eab588e223e52b1e7b710ff1c0da7b032ab2837sewardjstatic Bool initted     = False;
431893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
432893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/* C flag, fast route */
433893a3302cc943e2ad1db421a8e6a753f82f532a7sewardjstatic UInt tabc_fast[X86G_CC_OP_NUMBER];
434893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/* C flag, slow route */
435893a3302cc943e2ad1db421a8e6a753f82f532a7sewardjstatic UInt tabc_slow[X86G_CC_OP_NUMBER];
436893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/* table for calculate_cond */
437893a3302cc943e2ad1db421a8e6a753f82f532a7sewardjstatic UInt tab_cond[X86G_CC_OP_NUMBER][16];
438893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/* total entry counts for calc_all, calc_c, calc_cond. */
43984ff0657940e62f38e618ea18bac6f27ce0e741fsewardjstatic UInt n_calc_all  = 0;
44084ff0657940e62f38e618ea18bac6f27ce0e741fsewardjstatic UInt n_calc_c    = 0;
441893a3302cc943e2ad1db421a8e6a753f82f532a7sewardjstatic UInt n_calc_cond = 0;
442893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
443893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj#define SHOW_COUNTS_NOW (0 == (0x3FFFFF & (n_calc_all+n_calc_c+n_calc_cond)))
444893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
44584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
44684ff0657940e62f38e618ea18bac6f27ce0e741fsewardjstatic void showCounts ( void )
44784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj{
44884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   Int op, co;
44984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   Char ch;
450a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   vex_printf("\nTotal calls: calc_all=%u   calc_cond=%u   calc_c=%u\n",
451893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj              n_calc_all, n_calc_cond, n_calc_c);
452893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
453893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_printf("      cSLOW  cFAST    O   NO    B   NB    Z   NZ   BE  NBE"
45484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj              "    S   NS    P   NP    L   NL   LE  NLE\n");
455893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_printf("     -----------------------------------------------------"
45684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj              "----------------------------------------\n");
4572a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   for (op = 0; op < X86G_CC_OP_NUMBER; op++) {
45884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
45984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      ch = ' ';
46093d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj      if (op > 0 && (op-1) % 3 == 0)
46193d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj         ch = 'B';
46293d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj      if (op > 0 && (op-1) % 3 == 1)
46393d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj         ch = 'W';
46484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      if (op > 0 && (op-1) % 3 == 2)
46584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         ch = 'L';
46684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
46784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      vex_printf("%2d%c: ", op, ch);
468a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj      vex_printf("%6u ", tabc_slow[op]);
469a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj      vex_printf("%6u ", tabc_fast[op]);
47084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      for (co = 0; co < 16; co++) {
471893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj         Int n = tab_cond[op][co];
47284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         if (n >= 1000) {
47384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj            vex_printf(" %3dK", n / 1000);
47484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         } else
47584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         if (n >= 0) {
476893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj            vex_printf(" %3d ", n );
47784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         } else {
47884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj            vex_printf("     ");
47984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         }
48084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
48184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      vex_printf("\n");
48284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   }
48384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   vex_printf("\n");
48484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj}
48584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
48684ff0657940e62f38e618ea18bac6f27ce0e741fsewardjstatic void initCounts ( void )
48784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj{
48884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   Int op, co;
48984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   initted = True;
4902a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   for (op = 0; op < X86G_CC_OP_NUMBER; op++) {
491893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      tabc_fast[op] = tabc_slow[op] = 0;
49284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      for (co = 0; co < 16; co++)
493893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj         tab_cond[op][co] = 0;
49484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   }
49584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj}
49684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
49784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#endif /* PROFILE_EFLAGS */
49884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
499893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
5009aebb0c3f7a7f43313786826f31402f2b733badfsewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
501893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/* Calculate all the 6 flags from the supplied thunk parameters.
502893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   Worker function, not directly called from generated code. */
503893a3302cc943e2ad1db421a8e6a753f82f532a7sewardjstatic
504893a3302cc943e2ad1db421a8e6a753f82f532a7sewardjUInt x86g_calculate_eflags_all_WRK ( UInt cc_op,
505893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj                                     UInt cc_dep1_formal,
506893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj                                     UInt cc_dep2_formal,
507893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj                                     UInt cc_ndep_formal )
50836ca51378f8851635df814230fa23f2c409b9eddsewardj{
50936ca51378f8851635df814230fa23f2c409b9eddsewardj   switch (cc_op) {
5102a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_COPY:
5112a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj         return cc_dep1_formal
5122a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                & (X86G_CC_MASK_O | X86G_CC_MASK_S | X86G_CC_MASK_Z
5132a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                   | X86G_CC_MASK_A | X86G_CC_MASK_C | X86G_CC_MASK_P);
51414731f22bf7759d6d23383ca870ac89d9581f1e9sewardj
5152a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_ADDB:   ACTIONS_ADD( 8,  UChar  );
5162a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_ADDW:   ACTIONS_ADD( 16, UShort );
5172a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_ADDL:   ACTIONS_ADD( 32, UInt   );
518a238471814bd386aeb58a76718b41e68b1a794b2sewardj
5192a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_ADCB:   ACTIONS_ADC( 8,  UChar  );
5202a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_ADCW:   ACTIONS_ADC( 16, UShort );
5212a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_ADCL:   ACTIONS_ADC( 32, UInt   );
522a238471814bd386aeb58a76718b41e68b1a794b2sewardj
5232a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_SUBB:   ACTIONS_SUB(  8, UChar  );
5242a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_SUBW:   ACTIONS_SUB( 16, UShort );
5252a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_SUBL:   ACTIONS_SUB( 32, UInt   );
526afc5787e1c4b8e9678669577cf57ac509c6cd6b5sewardj
5272a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_SBBB:   ACTIONS_SBB(  8, UChar  );
5282a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_SBBW:   ACTIONS_SBB( 16, UShort );
5292a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_SBBL:   ACTIONS_SBB( 32, UInt   );
530741153c4301023a420ab45b8a10b8e1bac968822sewardj
5312a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_LOGICB: ACTIONS_LOGIC(  8, UChar  );
5322a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_LOGICW: ACTIONS_LOGIC( 16, UShort );
5332a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_LOGICL: ACTIONS_LOGIC( 32, UInt   );
5345f6303579435ddb8315e11c2f02c904b978782a0sewardj
5352a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_INCB:   ACTIONS_INC(  8, UChar  );
5362a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_INCW:   ACTIONS_INC( 16, UShort );
5372a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_INCL:   ACTIONS_INC( 32, UInt   );
5381813dbeb912870e9a544cae17a3fadbf8d2b0d55sewardj
5392a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_DECB:   ACTIONS_DEC(  8, UChar  );
5402a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_DECW:   ACTIONS_DEC( 16, UShort );
5412a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_DECL:   ACTIONS_DEC( 32, UInt   );
5428c7f1abe9e022f6382634efea09c9cac89ec6336sewardj
5432a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_SHLB:   ACTIONS_SHL(  8, UChar  );
5442a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_SHLW:   ACTIONS_SHL( 16, UShort );
5452a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_SHLL:   ACTIONS_SHL( 32, UInt   );
5468c7f1abe9e022f6382634efea09c9cac89ec6336sewardj
5472a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_SHRB:   ACTIONS_SHR(  8, UChar  );
5482a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_SHRW:   ACTIONS_SHR( 16, UShort );
5492a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_SHRL:   ACTIONS_SHR( 32, UInt   );
5501813dbeb912870e9a544cae17a3fadbf8d2b0d55sewardj
5512a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_ROLB:   ACTIONS_ROL(  8, UChar  );
5522a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_ROLW:   ACTIONS_ROL( 16, UShort );
5532a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_ROLL:   ACTIONS_ROL( 32, UInt   );
554750f407b6be1aac303964a219acf0a6de8b8c4dasewardj
5552a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_RORB:   ACTIONS_ROR(  8, UChar  );
5562a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_RORW:   ACTIONS_ROR( 16, UShort );
5572a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_RORL:   ACTIONS_ROR( 32, UInt   );
5587ed2295459ac5e788a98dd5570fef0d4645c27d4sewardj
5594a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj      case X86G_CC_OP_UMULB:  ACTIONS_UMUL(  8, UChar,  toUChar,
5604a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj                                                UShort, toUShort );
5614a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj      case X86G_CC_OP_UMULW:  ACTIONS_UMUL( 16, UShort, toUShort,
5624a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj                                                UInt,   toUInt );
5634a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj      case X86G_CC_OP_UMULL:  ACTIONS_UMUL( 32, UInt,   toUInt,
5644a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj                                                ULong,  idULong );
5654a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj
5664a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj      case X86G_CC_OP_SMULB:  ACTIONS_SMUL(  8, Char,   toUChar,
5674a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj                                                Short,  toUShort );
5684a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj      case X86G_CC_OP_SMULW:  ACTIONS_SMUL( 16, Short,  toUShort,
5694a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj                                                Int,    toUInt   );
5704a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj      case X86G_CC_OP_SMULL:  ACTIONS_SMUL( 32, Int,    toUInt,
5714a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj                                                Long,   idULong );
572741153c4301023a420ab45b8a10b8e1bac968822sewardj
57336ca51378f8851635df814230fa23f2c409b9eddsewardj      default:
57436ca51378f8851635df814230fa23f2c409b9eddsewardj         /* shouldn't really make these calls from generated code */
575893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj         vex_printf("x86g_calculate_eflags_all_WRK(X86)"
576a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj                    "( %u, 0x%x, 0x%x, 0x%x )\n",
5772a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj                    cc_op, cc_dep1_formal, cc_dep2_formal, cc_ndep_formal );
578893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj         vpanic("x86g_calculate_eflags_all_WRK(X86)");
57936ca51378f8851635df814230fa23f2c409b9eddsewardj   }
58036ca51378f8851635df814230fa23f2c409b9eddsewardj}
58136ca51378f8851635df814230fa23f2c409b9eddsewardj
582b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
5839aebb0c3f7a7f43313786826f31402f2b733badfsewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
584893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/* Calculate all the 6 flags from the supplied thunk parameters. */
585893a3302cc943e2ad1db421a8e6a753f82f532a7sewardjUInt x86g_calculate_eflags_all ( UInt cc_op,
586893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj                                 UInt cc_dep1,
587893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj                                 UInt cc_dep2,
588893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj                                 UInt cc_ndep )
589893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj{
590893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj#  if PROFILE_EFLAGS
591893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   if (!initted) initCounts();
592893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   n_calc_all++;
593893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   if (SHOW_COUNTS_NOW) showCounts();
594893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj#  endif
595893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   return
596893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      x86g_calculate_eflags_all_WRK ( cc_op, cc_dep1, cc_dep2, cc_ndep );
597893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj}
598893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
599893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
600893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
601b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/* Calculate just the carry flag from the supplied thunk parameters. */
602893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj__attribute((regparm(3)))
6032a9ad023890d3b34cf45e429df2a8ae88b419128sewardjUInt x86g_calculate_eflags_c ( UInt cc_op,
6042a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                               UInt cc_dep1,
6052a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                               UInt cc_dep2,
6062a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                               UInt cc_ndep )
60736ca51378f8851635df814230fa23f2c409b9eddsewardj{
608893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj#  if PROFILE_EFLAGS
609893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   if (!initted) initCounts();
610893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   n_calc_c++;
611893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   tabc_fast[cc_op]++;
612893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   if (SHOW_COUNTS_NOW) showCounts();
613893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj#  endif
614893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
6159eab588e223e52b1e7b710ff1c0da7b032ab2837sewardj   /* Fast-case some common ones. */
61643c46951628d616290f7245c3af2f9a652180806sewardj   switch (cc_op) {
6172a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_LOGICL:
6182a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_LOGICW:
6192a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_LOGICB:
62043c46951628d616290f7245c3af2f9a652180806sewardj         return 0;
6212a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_SUBL:
62293d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj         return ((UInt)cc_dep1) < ((UInt)cc_dep2)
6232a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                   ? X86G_CC_MASK_C : 0;
624893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      case X86G_CC_OP_SUBW:
625893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj         return ((UInt)(cc_dep1 & 0xFFFF)) < ((UInt)(cc_dep2 & 0xFFFF))
626893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj                   ? X86G_CC_MASK_C : 0;
6272a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_SUBB:
62893d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj         return ((UInt)(cc_dep1 & 0xFF)) < ((UInt)(cc_dep2 & 0xFF))
6292a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                   ? X86G_CC_MASK_C : 0;
630e9ba4328f2afb94bc8474e9a7205e50ed9ac73fcsewardj      case X86G_CC_OP_INCL:
6312a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_DECL:
632e9ba4328f2afb94bc8474e9a7205e50ed9ac73fcsewardj         return cc_ndep & X86G_CC_MASK_C;
63343c46951628d616290f7245c3af2f9a652180806sewardj      default:
63443c46951628d616290f7245c3af2f9a652180806sewardj         break;
63543c46951628d616290f7245c3af2f9a652180806sewardj   }
6369eab588e223e52b1e7b710ff1c0da7b032ab2837sewardj
63784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  if PROFILE_EFLAGS
638893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   tabc_fast[cc_op]--;
639893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   tabc_slow[cc_op]++;
64084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  endif
641893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
642893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   return x86g_calculate_eflags_all_WRK(cc_op,cc_dep1,cc_dep2,cc_ndep)
6432a9ad023890d3b34cf45e429df2a8ae88b419128sewardj          & X86G_CC_MASK_C;
64436ca51378f8851635df814230fa23f2c409b9eddsewardj}
64536ca51378f8851635df814230fa23f2c409b9eddsewardj
64636ca51378f8851635df814230fa23f2c409b9eddsewardj
6479aebb0c3f7a7f43313786826f31402f2b733badfsewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
64884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj/* returns 1 or 0 */
6492a9ad023890d3b34cf45e429df2a8ae88b419128sewardjUInt x86g_calculate_condition ( UInt/*X86Condcode*/ cond,
6502a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                                UInt cc_op,
6512a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                                UInt cc_dep1,
6522a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                                UInt cc_dep2,
6532a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                                UInt cc_ndep )
6542a9ad023890d3b34cf45e429df2a8ae88b419128sewardj{
655893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   UInt eflags = x86g_calculate_eflags_all_WRK(cc_op, cc_dep1,
656893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj                                               cc_dep2, cc_ndep);
65784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   UInt of,sf,zf,cf,pf;
65884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   UInt inv = cond & 1;
65984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
66084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  if PROFILE_EFLAGS
661893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   if (!initted) initCounts();
662893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   tab_cond[cc_op][cond]++;
66384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   n_calc_cond++;
664893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   if (SHOW_COUNTS_NOW) showCounts();
66584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  endif
66684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
66784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   switch (cond) {
6682a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86CondNO:
6692a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86CondO: /* OF == 1 */
6702a9ad023890d3b34cf45e429df2a8ae88b419128sewardj         of = eflags >> X86G_CC_SHIFT_O;
67184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return 1 & (inv ^ of);
67284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
6732a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86CondNZ:
6742a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86CondZ: /* ZF == 1 */
6752a9ad023890d3b34cf45e429df2a8ae88b419128sewardj         zf = eflags >> X86G_CC_SHIFT_Z;
67684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return 1 & (inv ^ zf);
67784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
6782a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86CondNB:
6792a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86CondB: /* CF == 1 */
6802a9ad023890d3b34cf45e429df2a8ae88b419128sewardj         cf = eflags >> X86G_CC_SHIFT_C;
68184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return 1 & (inv ^ cf);
68284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         break;
68384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
6842a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86CondNBE:
6852a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86CondBE: /* (CF or ZF) == 1 */
6862a9ad023890d3b34cf45e429df2a8ae88b419128sewardj         cf = eflags >> X86G_CC_SHIFT_C;
6872a9ad023890d3b34cf45e429df2a8ae88b419128sewardj         zf = eflags >> X86G_CC_SHIFT_Z;
68884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return 1 & (inv ^ (cf | zf));
68984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         break;
69084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
6912a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86CondNS:
6922a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86CondS: /* SF == 1 */
6932a9ad023890d3b34cf45e429df2a8ae88b419128sewardj         sf = eflags >> X86G_CC_SHIFT_S;
69484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return 1 & (inv ^ sf);
69584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
6962a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86CondNP:
6972a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86CondP: /* PF == 1 */
6982a9ad023890d3b34cf45e429df2a8ae88b419128sewardj         pf = eflags >> X86G_CC_SHIFT_P;
69984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return 1 & (inv ^ pf);
70084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
7012a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86CondNL:
7022a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86CondL: /* (SF xor OF) == 1 */
7032a9ad023890d3b34cf45e429df2a8ae88b419128sewardj         sf = eflags >> X86G_CC_SHIFT_S;
7042a9ad023890d3b34cf45e429df2a8ae88b419128sewardj         of = eflags >> X86G_CC_SHIFT_O;
70584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return 1 & (inv ^ (sf ^ of));
70684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         break;
70784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
7082a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86CondNLE:
7092a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86CondLE: /* ((SF xor OF) or ZF)  == 1 */
7102a9ad023890d3b34cf45e429df2a8ae88b419128sewardj         sf = eflags >> X86G_CC_SHIFT_S;
7112a9ad023890d3b34cf45e429df2a8ae88b419128sewardj         of = eflags >> X86G_CC_SHIFT_O;
7122a9ad023890d3b34cf45e429df2a8ae88b419128sewardj         zf = eflags >> X86G_CC_SHIFT_Z;
71384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return 1 & (inv ^ ((sf ^ of) | zf));
71484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         break;
71584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
71684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      default:
71784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         /* shouldn't really make these calls from generated code */
718a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj         vex_printf("x86g_calculate_condition( %u, %u, 0x%x, 0x%x, 0x%x )\n",
7192a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj                    cond, cc_op, cc_dep1, cc_dep2, cc_ndep );
720893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj         vpanic("x86g_calculate_condition");
72184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   }
72284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj}
72384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
72484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
725893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/* VISIBLE TO LIBVEX CLIENT */
726893a3302cc943e2ad1db421a8e6a753f82f532a7sewardjUInt LibVEX_GuestX86_get_eflags ( /*IN*/VexGuestX86State* vex_state )
727893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj{
728893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   UInt eflags = x86g_calculate_eflags_all_WRK(
729893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj                    vex_state->guest_CC_OP,
730893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj                    vex_state->guest_CC_DEP1,
731893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj                    vex_state->guest_CC_DEP2,
732893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj                    vex_state->guest_CC_NDEP
733893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj                 );
734893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   UInt dflag = vex_state->guest_DFLAG;
735893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vassert(dflag == 1 || dflag == 0xFFFFFFFF);
736893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   if (dflag == 0xFFFFFFFF)
737893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      eflags |= (1<<10);
738893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   if (vex_state->guest_IDFLAG == 1)
739893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      eflags |= (1<<21);
7406d26984a0df6a7d20b658bac6edf869eb872cca3sewardj   if (vex_state->guest_ACFLAG == 1)
7416d26984a0df6a7d20b658bac6edf869eb872cca3sewardj      eflags |= (1<<18);
742893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
743893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   return eflags;
744893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj}
745893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
746893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
747893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/*---------------------------------------------------------------*/
748893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/*--- %eflags translation-time function specialisers.         ---*/
749893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/*--- These help iropt specialise calls the above run-time    ---*/
750893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/*--- %eflags functions.                                      ---*/
751893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/*---------------------------------------------------------------*/
752893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
75384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj/* Used by the optimiser to try specialisations.  Returns an
75484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   equivalent expression, or NULL if none. */
75584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
75684ff0657940e62f38e618ea18bac6f27ce0e741fsewardjstatic Bool isU32 ( IRExpr* e, UInt n )
75784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj{
758a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   return
759a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj      toBool( e->tag == Iex_Const
760a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj              && e->Iex.Const.con->tag == Ico_U32
761a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj              && e->Iex.Const.con->Ico.U32 == n );
76284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj}
76384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
7645827784e6bb74e2a032b66ec310776c24fd88729sewardjIRExpr* guest_x86_spechelper ( HChar* function_name,
7652a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                               IRExpr** args )
76684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj{
76784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  define unop(_op,_a1) IRExpr_Unop((_op),(_a1))
76884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  define binop(_op,_a1,_a2) IRExpr_Binop((_op),(_a1),(_a2))
76984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  define mkU32(_n) IRExpr_Const(IRConst_U32(_n))
7704afab82eb869f21ccabc3efb5b93f31a5c343956sewardj#  define mkU8(_n)  IRExpr_Const(IRConst_U8(_n))
77184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
77284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   Int i, arity = 0;
77384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   for (i = 0; args[i]; i++)
77484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      arity++;
77584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  if 0
77684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   vex_printf("spec request:\n");
77784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   vex_printf("   %s  ", function_name);
77884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   for (i = 0; i < arity; i++) {
77984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      vex_printf("  ");
78084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      ppIRExpr(args[i]);
78184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   }
78284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   vex_printf("\n");
78384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  endif
78493d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj
7853835288ac63bb755c0e1d2f3142a13416dcb64c6sewardj   /* --------- specialising "x86g_calculate_condition" --------- */
78693d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj
7873835288ac63bb755c0e1d2f3142a13416dcb64c6sewardj   if (vex_streq(function_name, "x86g_calculate_condition")) {
78884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      /* specialise calls to above "calculate condition" function */
789a8415ffe6c6f0e73519301a55026a4071c701fd1sewardj      IRExpr *cond, *cc_op, *cc_dep1, *cc_dep2;
79093d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj      vassert(arity == 5);
79193d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj      cond    = args[0];
79293d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj      cc_op   = args[1];
79393d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj      cc_dep1 = args[2];
79493d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj      cc_dep2 = args[3];
79584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
796d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj      /*---------------- ADDL ----------------*/
797d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj
7982a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_ADDL) && isU32(cond, X86CondZ)) {
799d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj         /* long add, then Z --> test (dst+src == 0) */
800d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj         return unop(Iop_1Uto32,
801d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj                     binop(Iop_CmpEQ32,
802d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj                           binop(Iop_Add32, cc_dep1, cc_dep2),
803d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj                           mkU32(0)));
804d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj      }
805d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj
80646ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      /*---------------- SUBL ----------------*/
80746ccb51aff085d180120d310c0be2fe6c86e1b65sewardj
8082a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_SUBL) && isU32(cond, X86CondZ)) {
80946ccb51aff085d180120d310c0be2fe6c86e1b65sewardj         /* long sub/cmp, then Z --> test dst==src */
81084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return unop(Iop_1Uto32,
81193d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj                     binop(Iop_CmpEQ32, cc_dep1, cc_dep2));
81246ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      }
81346ccb51aff085d180120d310c0be2fe6c86e1b65sewardj
81466f7a54d5425853debcb5fe77be1021f0c2b6620sewardj      if (isU32(cc_op, X86G_CC_OP_SUBL) && isU32(cond, X86CondNZ)) {
81566f7a54d5425853debcb5fe77be1021f0c2b6620sewardj         /* long sub/cmp, then NZ --> test dst!=src */
81666f7a54d5425853debcb5fe77be1021f0c2b6620sewardj         return unop(Iop_1Uto32,
81766f7a54d5425853debcb5fe77be1021f0c2b6620sewardj                     binop(Iop_CmpNE32, cc_dep1, cc_dep2));
81866f7a54d5425853debcb5fe77be1021f0c2b6620sewardj      }
81966f7a54d5425853debcb5fe77be1021f0c2b6620sewardj
8202a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_SUBL) && isU32(cond, X86CondL)) {
82146ccb51aff085d180120d310c0be2fe6c86e1b65sewardj         /* long sub/cmp, then L (signed less than)
82246ccb51aff085d180120d310c0be2fe6c86e1b65sewardj            --> test dst <s src */
82346ccb51aff085d180120d310c0be2fe6c86e1b65sewardj         return unop(Iop_1Uto32,
82493d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj                     binop(Iop_CmpLT32S, cc_dep1, cc_dep2));
82546ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      }
82646ccb51aff085d180120d310c0be2fe6c86e1b65sewardj
8272a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_SUBL) && isU32(cond, X86CondLE)) {
82846ccb51aff085d180120d310c0be2fe6c86e1b65sewardj         /* long sub/cmp, then LE (signed less than or equal)
82946ccb51aff085d180120d310c0be2fe6c86e1b65sewardj            --> test dst <=s src */
83046ccb51aff085d180120d310c0be2fe6c86e1b65sewardj         return unop(Iop_1Uto32,
83193d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj                     binop(Iop_CmpLE32S, cc_dep1, cc_dep2));
83246ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      }
83346ccb51aff085d180120d310c0be2fe6c86e1b65sewardj
8342a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_SUBL) && isU32(cond, X86CondBE)) {
83546ccb51aff085d180120d310c0be2fe6c86e1b65sewardj         /* long sub/cmp, then BE (unsigned less than or equal)
83646ccb51aff085d180120d310c0be2fe6c86e1b65sewardj            --> test dst <=u src */
83746ccb51aff085d180120d310c0be2fe6c86e1b65sewardj         return unop(Iop_1Uto32,
83893d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj                     binop(Iop_CmpLE32U, cc_dep1, cc_dep2));
83946ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      }
840e664ec4b9f27ed7d7ca87a2d4188fd479059351csewardj
8412a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_SUBL) && isU32(cond, X86CondB)) {
84246ccb51aff085d180120d310c0be2fe6c86e1b65sewardj         /* long sub/cmp, then B (unsigned less than)
84346ccb51aff085d180120d310c0be2fe6c86e1b65sewardj            --> test dst <u src */
84446ccb51aff085d180120d310c0be2fe6c86e1b65sewardj         return unop(Iop_1Uto32,
845e664ec4b9f27ed7d7ca87a2d4188fd479059351csewardj                     binop(Iop_CmpLT32U, cc_dep1, cc_dep2));
84684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
847e664ec4b9f27ed7d7ca87a2d4188fd479059351csewardj
848e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj      if (isU32(cc_op, X86G_CC_OP_SUBL) && isU32(cond, X86CondS)) {
849e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj         /* long sub/cmp, then S --> test (dst-src <s 0) */
850e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj         return unop(Iop_1Uto32,
851e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj                     binop(Iop_CmpLT32S,
852e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj                           binop(Iop_Sub32, cc_dep1, cc_dep2),
853e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj                           mkU32(0)));
854e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj      }
855e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj
85646ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      /*---------------- SUBW ----------------*/
85746ccb51aff085d180120d310c0be2fe6c86e1b65sewardj
8582a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_SUBW) && isU32(cond, X86CondZ)) {
859b9c5cf639b3b21b972599d27207a033afc76ef67sewardj         /* byte sub/cmp, then Z --> test dst==src */
860b9c5cf639b3b21b972599d27207a033afc76ef67sewardj         return unop(Iop_1Uto32,
861b9c5cf639b3b21b972599d27207a033afc76ef67sewardj                     binop(Iop_CmpEQ16,
8627e6644c38b3e0148ff95c2f6f4667f54148b611esewardj                           unop(Iop_32to16,cc_dep1),
8637e6644c38b3e0148ff95c2f6f4667f54148b611esewardj                           unop(Iop_32to16,cc_dep2)));
864b9c5cf639b3b21b972599d27207a033afc76ef67sewardj      }
865b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
86646ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      /*---------------- SUBB ----------------*/
8677e6644c38b3e0148ff95c2f6f4667f54148b611esewardj
8682a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_SUBB) && isU32(cond, X86CondZ)) {
869b9c5cf639b3b21b972599d27207a033afc76ef67sewardj         /* byte sub/cmp, then Z --> test dst==src */
87084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return unop(Iop_1Uto32,
871b9c5cf639b3b21b972599d27207a033afc76ef67sewardj                     binop(Iop_CmpEQ8,
87293d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj                           unop(Iop_32to8,cc_dep1),
87393d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj                           unop(Iop_32to8,cc_dep2)));
87484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
87584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
8762a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_SUBB) && isU32(cond, X86CondNZ)) {
8777e5b7cdbfa65376488d58e4e6d8f13d974f7a8bcsewardj         /* byte sub/cmp, then NZ --> test dst!=src */
87884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return unop(Iop_1Uto32,
879b9c5cf639b3b21b972599d27207a033afc76ef67sewardj                     binop(Iop_CmpNE8,
88093d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj                           unop(Iop_32to8,cc_dep1),
88193d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj                           unop(Iop_32to8,cc_dep2)));
882b9c5cf639b3b21b972599d27207a033afc76ef67sewardj      }
88322419b8f4f2c0104549ca9954f68e190b911d1a0sewardj
8842a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_SUBB) && isU32(cond, X86CondNBE)) {
885b9c5cf639b3b21b972599d27207a033afc76ef67sewardj         /* long sub/cmp, then NBE (unsigned greater than)
886b9c5cf639b3b21b972599d27207a033afc76ef67sewardj            --> test src <=u dst */
8877e5b7cdbfa65376488d58e4e6d8f13d974f7a8bcsewardj         /* Note, args are opposite way round from the usual */
888b9c5cf639b3b21b972599d27207a033afc76ef67sewardj         return unop(Iop_1Uto32,
889b9c5cf639b3b21b972599d27207a033afc76ef67sewardj                     binop(Iop_CmpLT32U,
8907e5b7cdbfa65376488d58e4e6d8f13d974f7a8bcsewardj                           binop(Iop_And32,cc_dep2,mkU32(0xFF)),
8917e5b7cdbfa65376488d58e4e6d8f13d974f7a8bcsewardj			   binop(Iop_And32,cc_dep1,mkU32(0xFF))));
89284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
89384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
89446ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      /*---------------- LOGICL ----------------*/
89546ccb51aff085d180120d310c0be2fe6c86e1b65sewardj
8962a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_LOGICL) && isU32(cond, X86CondZ)) {
89784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         /* long and/or/xor, then Z --> test dst==0 */
89893d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj         return unop(Iop_1Uto32,binop(Iop_CmpEQ32, cc_dep1, mkU32(0)));
89984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
90022419b8f4f2c0104549ca9954f68e190b911d1a0sewardj
9012a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_LOGICL) && isU32(cond, X86CondS)) {
902fae2ca7ef81549a4b28235618317d4352ca32ac2sewardj         /* long and/or/xor, then S --> test dst <s 0 */
9037e6644c38b3e0148ff95c2f6f4667f54148b611esewardj         return unop(Iop_1Uto32,binop(Iop_CmpLT32S, cc_dep1, mkU32(0)));
904fae2ca7ef81549a4b28235618317d4352ca32ac2sewardj      }
90522419b8f4f2c0104549ca9954f68e190b911d1a0sewardj
9062a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_LOGICL) && isU32(cond, X86CondLE)) {
90784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         /* long and/or/xor, then LE
90884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj            This is pretty subtle.  LOGIC sets SF and ZF according to the
90984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj            result and makes OF be zero.  LE computes (SZ ^ OF) | ZF, but
91084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj            OF is zero, so this reduces to SZ | ZF -- which will be 1 iff
91184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj            the result is <=signed 0.  Hence ...
91284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         */
91393d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj         return unop(Iop_1Uto32,binop(Iop_CmpLE32S, cc_dep1, mkU32(0)));
91484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
91584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
91666f7a54d5425853debcb5fe77be1021f0c2b6620sewardj      if (isU32(cc_op, X86G_CC_OP_LOGICL) && isU32(cond, X86CondBE)) {
91766f7a54d5425853debcb5fe77be1021f0c2b6620sewardj         /* long and/or/xor, then BE
91866f7a54d5425853debcb5fe77be1021f0c2b6620sewardj            LOGIC sets ZF according to the result and makes CF be zero.
91966f7a54d5425853debcb5fe77be1021f0c2b6620sewardj            BE computes (CF | ZF), but CF is zero, so this reduces ZF
92066f7a54d5425853debcb5fe77be1021f0c2b6620sewardj            -- which will be 1 iff the result is zero.  Hence ...
92166f7a54d5425853debcb5fe77be1021f0c2b6620sewardj         */
92266f7a54d5425853debcb5fe77be1021f0c2b6620sewardj         return unop(Iop_1Uto32,binop(Iop_CmpEQ32, cc_dep1, mkU32(0)));
92366f7a54d5425853debcb5fe77be1021f0c2b6620sewardj      }
92466f7a54d5425853debcb5fe77be1021f0c2b6620sewardj
925d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj      /*---------------- LOGICW ----------------*/
926d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj
9272a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_LOGICW) && isU32(cond, X86CondZ)) {
928d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj         /* byte and/or/xor, then Z --> test dst==0 */
929d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj         return unop(Iop_1Uto32,
930d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj                     binop(Iop_CmpEQ32, binop(Iop_And32,cc_dep1,mkU32(0xFFFF)),
931d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj                                        mkU32(0)));
932d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj      }
933d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj
93446ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      /*---------------- LOGICB ----------------*/
93584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
9362a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_LOGICB) && isU32(cond, X86CondZ)) {
93746ccb51aff085d180120d310c0be2fe6c86e1b65sewardj         /* byte and/or/xor, then Z --> test dst==0 */
93884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return unop(Iop_1Uto32,
93993d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj                     binop(Iop_CmpEQ32, binop(Iop_And32,cc_dep1,mkU32(255)),
94046ccb51aff085d180120d310c0be2fe6c86e1b65sewardj                                        mkU32(0)));
94184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
94284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
94346ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      /*---------------- DECL ----------------*/
944af991dede2815b7570828b9d9174cf989e636254sewardj
9452a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_DECL) && isU32(cond, X86CondZ)) {
94684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         /* dec L, then Z --> test dst == 0 */
94793d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj         return unop(Iop_1Uto32,binop(Iop_CmpEQ32, cc_dep1, mkU32(0)));
94884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
94922419b8f4f2c0104549ca9954f68e190b911d1a0sewardj
9502a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_DECL) && isU32(cond, X86CondS)) {
951fae2ca7ef81549a4b28235618317d4352ca32ac2sewardj         /* dec L, then S --> compare DST <s 0 */
9527e6644c38b3e0148ff95c2f6f4667f54148b611esewardj         return unop(Iop_1Uto32,binop(Iop_CmpLT32S, cc_dep1, mkU32(0)));
953fae2ca7ef81549a4b28235618317d4352ca32ac2sewardj      }
954fae2ca7ef81549a4b28235618317d4352ca32ac2sewardj
955d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj      /*---------------- SHRL ----------------*/
956d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj
9572a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_SHRL) && isU32(cond, X86CondZ)) {
958d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj         /* SHRL, then Z --> test dep1 == 0 */
959d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj         return unop(Iop_1Uto32,binop(Iop_CmpEQ32, cc_dep1, mkU32(0)));
960d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj      }
961d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj
9624afab82eb869f21ccabc3efb5b93f31a5c343956sewardj      /*---------------- COPY ----------------*/
9634afab82eb869f21ccabc3efb5b93f31a5c343956sewardj      /* This can happen, as a result of x87 FP compares: "fcom ... ;
9644afab82eb869f21ccabc3efb5b93f31a5c343956sewardj         fnstsw %ax ; sahf ; jbe" for example. */
9654afab82eb869f21ccabc3efb5b93f31a5c343956sewardj
96666f7a54d5425853debcb5fe77be1021f0c2b6620sewardj      if (isU32(cc_op, X86G_CC_OP_COPY) &&
96766f7a54d5425853debcb5fe77be1021f0c2b6620sewardj          (isU32(cond, X86CondBE) || isU32(cond, X86CondNBE))) {
9684afab82eb869f21ccabc3efb5b93f31a5c343956sewardj         /* COPY, then BE --> extract C and Z from dep1, and test (C
9694afab82eb869f21ccabc3efb5b93f31a5c343956sewardj            or Z == 1). */
97066f7a54d5425853debcb5fe77be1021f0c2b6620sewardj         /* COPY, then NBE --> extract C and Z from dep1, and test (C
97166f7a54d5425853debcb5fe77be1021f0c2b6620sewardj            or Z == 0). */
97266f7a54d5425853debcb5fe77be1021f0c2b6620sewardj         UInt nnn = isU32(cond, X86CondBE) ? 1 : 0;
9734afab82eb869f21ccabc3efb5b93f31a5c343956sewardj         return
9744afab82eb869f21ccabc3efb5b93f31a5c343956sewardj            unop(
9754afab82eb869f21ccabc3efb5b93f31a5c343956sewardj               Iop_1Uto32,
9764afab82eb869f21ccabc3efb5b93f31a5c343956sewardj               binop(
97766f7a54d5425853debcb5fe77be1021f0c2b6620sewardj                  Iop_CmpEQ32,
9784afab82eb869f21ccabc3efb5b93f31a5c343956sewardj                  binop(
9794afab82eb869f21ccabc3efb5b93f31a5c343956sewardj                     Iop_And32,
9804afab82eb869f21ccabc3efb5b93f31a5c343956sewardj                     binop(
9814afab82eb869f21ccabc3efb5b93f31a5c343956sewardj                        Iop_Or32,
9824afab82eb869f21ccabc3efb5b93f31a5c343956sewardj                        binop(Iop_Shr32, cc_dep1, mkU8(X86G_CC_SHIFT_C)),
9834afab82eb869f21ccabc3efb5b93f31a5c343956sewardj                        binop(Iop_Shr32, cc_dep1, mkU8(X86G_CC_SHIFT_Z))
9844afab82eb869f21ccabc3efb5b93f31a5c343956sewardj                     ),
9854afab82eb869f21ccabc3efb5b93f31a5c343956sewardj                     mkU32(1)
9864afab82eb869f21ccabc3efb5b93f31a5c343956sewardj                  ),
98766f7a54d5425853debcb5fe77be1021f0c2b6620sewardj                  mkU32(nnn)
9884afab82eb869f21ccabc3efb5b93f31a5c343956sewardj               )
9894afab82eb869f21ccabc3efb5b93f31a5c343956sewardj            );
9904afab82eb869f21ccabc3efb5b93f31a5c343956sewardj      }
9914afab82eb869f21ccabc3efb5b93f31a5c343956sewardj
992e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj      if (isU32(cc_op, X86G_CC_OP_COPY) &&
993e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj          (isU32(cond, X86CondB) || isU32(cond, X86CondNB))) {
994e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj         /* COPY, then B --> extract C from dep1, and test (C == 1). */
995e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj         /* COPY, then NB --> extract C from dep1, and test (C == 0). */
996e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj         UInt nnn = isU32(cond, X86CondB) ? 1 : 0;
9974afab82eb869f21ccabc3efb5b93f31a5c343956sewardj         return
9984afab82eb869f21ccabc3efb5b93f31a5c343956sewardj            unop(
9994afab82eb869f21ccabc3efb5b93f31a5c343956sewardj               Iop_1Uto32,
10004afab82eb869f21ccabc3efb5b93f31a5c343956sewardj               binop(
1001e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj                  Iop_CmpEQ32,
10024afab82eb869f21ccabc3efb5b93f31a5c343956sewardj                  binop(
10034afab82eb869f21ccabc3efb5b93f31a5c343956sewardj                     Iop_And32,
10044afab82eb869f21ccabc3efb5b93f31a5c343956sewardj                     binop(Iop_Shr32, cc_dep1, mkU8(X86G_CC_SHIFT_C)),
10054afab82eb869f21ccabc3efb5b93f31a5c343956sewardj                     mkU32(1)
10064afab82eb869f21ccabc3efb5b93f31a5c343956sewardj                  ),
1007e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj                  mkU32(nnn)
1008e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj               )
1009e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj            );
1010e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj      }
1011e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj
1012e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj      if (isU32(cc_op, X86G_CC_OP_COPY) && isU32(cond, X86CondZ)) {
1013e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj         /* COPY, then Z --> extract Z from dep1, and test (Z == 1). */
1014e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj         return
1015e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj            unop(
1016e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj               Iop_1Uto32,
1017e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj               binop(
1018e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj                  Iop_CmpNE32,
1019e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj                  binop(
1020e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj                     Iop_And32,
1021e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj                     binop(Iop_Shr32, cc_dep1, mkU8(X86G_CC_SHIFT_Z)),
1022e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj                     mkU32(1)
1023e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj                  ),
10244afab82eb869f21ccabc3efb5b93f31a5c343956sewardj                  mkU32(0)
10254afab82eb869f21ccabc3efb5b93f31a5c343956sewardj               )
10264afab82eb869f21ccabc3efb5b93f31a5c343956sewardj            );
10274afab82eb869f21ccabc3efb5b93f31a5c343956sewardj      }
10284afab82eb869f21ccabc3efb5b93f31a5c343956sewardj
102984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      return NULL;
103084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   }
103184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
1032893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   /* --------- specialising "x86g_calculate_eflags_c" --------- */
1033893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
1034893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   if (vex_streq(function_name, "x86g_calculate_eflags_c")) {
1035893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      /* specialise calls to above "calculate_eflags_c" function */
1036893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      IRExpr *cc_op, *cc_dep1, *cc_dep2, *cc_ndep;
1037893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      vassert(arity == 4);
1038893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      cc_op   = args[0];
1039893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      cc_dep1 = args[1];
1040893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      cc_dep2 = args[2];
1041893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      cc_ndep = args[3];
1042893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
1043893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      if (isU32(cc_op, X86G_CC_OP_SUBL)) {
1044893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj         /* C after sub denotes unsigned less than */
1045893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj         return unop(Iop_1Uto32,
1046893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj                     binop(Iop_CmpLT32U, cc_dep1, cc_dep2));
1047893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      }
1048893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      if (isU32(cc_op, X86G_CC_OP_SUBB)) {
1049893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj         /* C after sub denotes unsigned less than */
1050893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj         return unop(Iop_1Uto32,
1051893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj                     binop(Iop_CmpLT32U,
1052893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj                           binop(Iop_And32,cc_dep1,mkU32(0xFF)),
1053893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj                           binop(Iop_And32,cc_dep2,mkU32(0xFF))));
1054893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      }
1055893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      if (isU32(cc_op, X86G_CC_OP_LOGICL)
1056893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj          || isU32(cc_op, X86G_CC_OP_LOGICW)
1057893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj          || isU32(cc_op, X86G_CC_OP_LOGICB)) {
1058893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj         /* cflag after logic is zero */
1059893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj         return mkU32(0);
1060893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      }
1061893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      if (isU32(cc_op, X86G_CC_OP_DECL) || isU32(cc_op, X86G_CC_OP_INCL)) {
1062893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj         /* If the thunk is dec or inc, the cflag is supplied as CC_NDEP. */
1063893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj         return cc_ndep;
1064893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      }
1065893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      if (isU32(cc_op, X86G_CC_OP_COPY)) {
1066893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj         /* cflag after COPY is stored in DEP1. */
1067893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj         return
1068893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj            binop(
1069893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj               Iop_And32,
1070893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj               binop(Iop_Shr32, cc_dep1, mkU8(X86G_CC_SHIFT_C)),
1071893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj               mkU32(1)
1072893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj            );
1073893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      }
1074893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj#     if 0
1075893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      if (cc_op->tag == Iex_Const) {
1076893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj         vex_printf("CFLAG "); ppIRExpr(cc_op); vex_printf("\n");
1077893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      }
1078893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj#     endif
1079893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
1080893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      return NULL;
1081893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   }
1082893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
1083893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   /* --------- specialising "x86g_calculate_eflags_all" --------- */
1084893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
1085893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   if (vex_streq(function_name, "x86g_calculate_eflags_all")) {
1086893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      /* specialise calls to above "calculate_eflags_all" function */
108740e144d3c4b155ab30c71f5abc90ff67391e7a87sewardj      IRExpr *cc_op, *cc_dep1; /*, *cc_dep2, *cc_ndep; */
1088893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      vassert(arity == 4);
1089893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      cc_op   = args[0];
1090893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      cc_dep1 = args[1];
109140e144d3c4b155ab30c71f5abc90ff67391e7a87sewardj      /* cc_dep2 = args[2]; */
109240e144d3c4b155ab30c71f5abc90ff67391e7a87sewardj      /* cc_ndep = args[3]; */
1093893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
1094893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      if (isU32(cc_op, X86G_CC_OP_COPY)) {
1095893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj         /* eflags after COPY are stored in DEP1. */
1096893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj         return
1097893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj            binop(
1098893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj               Iop_And32,
1099893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj               cc_dep1,
1100893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj               mkU32(X86G_CC_MASK_O | X86G_CC_MASK_S | X86G_CC_MASK_Z
1101893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj                     | X86G_CC_MASK_A | X86G_CC_MASK_C | X86G_CC_MASK_P)
1102893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj            );
1103893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      }
1104893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      return NULL;
1105893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   }
1106893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
110784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  undef unop
110884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  undef binop
110984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  undef mkU32
11104afab82eb869f21ccabc3efb5b93f31a5c343956sewardj#  undef mkU8
111184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
111284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   return NULL;
111384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj}
111484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
111536ca51378f8851635df814230fa23f2c409b9eddsewardj
1116893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/*---------------------------------------------------------------*/
1117893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/*--- Supporting functions for x87 FPU activities.            ---*/
1118893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/*---------------------------------------------------------------*/
1119893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
1120893a3302cc943e2ad1db421a8e6a753f82f532a7sewardjstatic inline Bool host_is_little_endian ( void )
1121893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj{
1122893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   UInt x = 0x76543210;
1123893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   UChar* p = (UChar*)(&x);
1124a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   return toBool(*p == 0x10);
1125893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj}
1126893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
11270c2cb623cca372a2b42b073121c7413cdaaf75besewardj/* 80 and 64-bit floating point formats:
11280c2cb623cca372a2b42b073121c7413cdaaf75besewardj
11290c2cb623cca372a2b42b073121c7413cdaaf75besewardj   80-bit:
11300c2cb623cca372a2b42b073121c7413cdaaf75besewardj
11310c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  0       0-------0      zero
11320c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  0       0X------X      denormals
11330c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  1-7FFE  1X------X      normals (all normals have leading 1)
11340c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  7FFF    10------0      infinity
11350c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  7FFF    10X-----X      snan
11360c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  7FFF    11X-----X      qnan
11370c2cb623cca372a2b42b073121c7413cdaaf75besewardj
11380c2cb623cca372a2b42b073121c7413cdaaf75besewardj   S is the sign bit.  For runs X----X, at least one of the Xs must be
11390c2cb623cca372a2b42b073121c7413cdaaf75besewardj   nonzero.  Exponent is 15 bits, fractional part is 63 bits, and
11400c2cb623cca372a2b42b073121c7413cdaaf75besewardj   there is an explicitly represented leading 1, and a sign bit,
11410c2cb623cca372a2b42b073121c7413cdaaf75besewardj   giving 80 in total.
11420c2cb623cca372a2b42b073121c7413cdaaf75besewardj
11430c2cb623cca372a2b42b073121c7413cdaaf75besewardj   64-bit avoids the confusion of an explicitly represented leading 1
11440c2cb623cca372a2b42b073121c7413cdaaf75besewardj   and so is simpler:
11450c2cb623cca372a2b42b073121c7413cdaaf75besewardj
11460c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  0      0------0   zero
11470c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  0      X------X   denormals
11480c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  1-7FE  any        normals
11490c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  7FF    0------0   infinity
11500c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  7FF    0X-----X   snan
11510c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  7FF    1X-----X   qnan
11520c2cb623cca372a2b42b073121c7413cdaaf75besewardj
11530c2cb623cca372a2b42b073121c7413cdaaf75besewardj   Exponent is 11 bits, fractional part is 52 bits, and there is a
11540c2cb623cca372a2b42b073121c7413cdaaf75besewardj   sign bit, giving 64 in total.
11550c2cb623cca372a2b42b073121c7413cdaaf75besewardj*/
11560c2cb623cca372a2b42b073121c7413cdaaf75besewardj
1157893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/* Inspect a value and its tag, as per the x87 'FXAM' instruction. */
11589aebb0c3f7a7f43313786826f31402f2b733badfsewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
11592a9ad023890d3b34cf45e429df2a8ae88b419128sewardjUInt x86g_calculate_FXAM ( UInt tag, ULong dbl )
1160c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj{
1161c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   Bool   mantissaIsZero;
1162c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   Int    bexp;
1163c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   UChar  sign;
1164c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   UChar* f64;
1165c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
1166a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   vassert(host_is_little_endian());
1167c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
1168c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   /* vex_printf("calculate_FXAM ( %d, %llx ) .. ", tag, dbl ); */
1169c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
1170c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   f64  = (UChar*)(&dbl);
1171a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   sign = toUChar( (f64[7] >> 7) & 1 );
1172c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
1173c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   /* First off, if the tag indicates the register was empty,
1174c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      return 1,0,sign,1 */
1175c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   if (tag == 0) {
1176c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      /* vex_printf("Empty\n"); */
1177e128ea174ede77daa2edadb3bde0b40dde06f95esewardj      return X86G_FC_MASK_C3 | 0 | (sign << X86G_FC_SHIFT_C1)
1178e128ea174ede77daa2edadb3bde0b40dde06f95esewardj                                 | X86G_FC_MASK_C0;
1179c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   }
1180c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
1181c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   bexp = (f64[7] << 4) | ((f64[6] >> 4) & 0x0F);
1182c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   bexp &= 0x7FF;
1183c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
1184c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   mantissaIsZero
1185a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj      = toBool(
1186a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj           (f64[6] & 0x0F) == 0
1187a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj           && (f64[5] | f64[4] | f64[3] | f64[2] | f64[1] | f64[0]) == 0
1188a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj        );
1189c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
1190c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   /* If both exponent and mantissa are zero, the value is zero.
1191c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      Return 1,0,sign,0. */
1192c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   if (bexp == 0 && mantissaIsZero) {
1193c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      /* vex_printf("Zero\n"); */
1194e128ea174ede77daa2edadb3bde0b40dde06f95esewardj      return X86G_FC_MASK_C3 | 0
1195e128ea174ede77daa2edadb3bde0b40dde06f95esewardj                             | (sign << X86G_FC_SHIFT_C1) | 0;
1196c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   }
1197c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
1198c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   /* If exponent is zero but mantissa isn't, it's a denormal.
1199c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      Return 1,1,sign,0. */
1200c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   if (bexp == 0 && !mantissaIsZero) {
1201c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      /* vex_printf("Denormal\n"); */
1202e128ea174ede77daa2edadb3bde0b40dde06f95esewardj      return X86G_FC_MASK_C3 | X86G_FC_MASK_C2
1203e128ea174ede77daa2edadb3bde0b40dde06f95esewardj                             | (sign << X86G_FC_SHIFT_C1) | 0;
1204c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   }
1205c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
1206c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   /* If the exponent is 7FF and the mantissa is zero, this is an infinity.
1207c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      Return 0,1,sign,1. */
1208c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   if (bexp == 0x7FF && mantissaIsZero) {
1209c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      /* vex_printf("Inf\n"); */
1210e128ea174ede77daa2edadb3bde0b40dde06f95esewardj      return 0 | X86G_FC_MASK_C2 | (sign << X86G_FC_SHIFT_C1)
1211e128ea174ede77daa2edadb3bde0b40dde06f95esewardj                                 | X86G_FC_MASK_C0;
1212c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   }
1213c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
1214c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   /* If the exponent is 7FF and the mantissa isn't zero, this is a NaN.
1215c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      Return 0,0,sign,1. */
1216c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   if (bexp == 0x7FF && !mantissaIsZero) {
1217c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      /* vex_printf("NaN\n"); */
1218e128ea174ede77daa2edadb3bde0b40dde06f95esewardj      return 0 | 0 | (sign << X86G_FC_SHIFT_C1) | X86G_FC_MASK_C0;
1219c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   }
1220c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
1221c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   /* Uh, ok, we give up.  It must be a normal finite number.
1222c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      Return 0,1,sign,0.
1223c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   */
1224c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   /* vex_printf("normal\n"); */
1225e128ea174ede77daa2edadb3bde0b40dde06f95esewardj   return 0 | X86G_FC_MASK_C2 | (sign << X86G_FC_SHIFT_C1) | 0;
1226c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj}
1227c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
12280c2cb623cca372a2b42b073121c7413cdaaf75besewardj
122917442fe8094d0f82266e5a05509f62cac8f7539esewardj/* CALLED FROM GENERATED CODE */
123017442fe8094d0f82266e5a05509f62cac8f7539esewardj/* DIRTY HELPER (reads guest memory) */
12312a9ad023890d3b34cf45e429df2a8ae88b419128sewardjULong x86g_loadF80le ( UInt addrU )
123217442fe8094d0f82266e5a05509f62cac8f7539esewardj{
123317442fe8094d0f82266e5a05509f62cac8f7539esewardj   ULong f64;
1234c2bcb6f78b7fc9066befa79aeaee57f82a087545sewardj   convert_f80le_to_f64le ( (UChar*)ULong_to_Ptr(addrU), (UChar*)&f64 );
123517442fe8094d0f82266e5a05509f62cac8f7539esewardj   return f64;
123617442fe8094d0f82266e5a05509f62cac8f7539esewardj}
123717442fe8094d0f82266e5a05509f62cac8f7539esewardj
123817442fe8094d0f82266e5a05509f62cac8f7539esewardj/* CALLED FROM GENERATED CODE */
123917442fe8094d0f82266e5a05509f62cac8f7539esewardj/* DIRTY HELPER (writes guest memory) */
12402a9ad023890d3b34cf45e429df2a8ae88b419128sewardjvoid x86g_storeF80le ( UInt addrU, ULong f64 )
124117442fe8094d0f82266e5a05509f62cac8f7539esewardj{
1242c2bcb6f78b7fc9066befa79aeaee57f82a087545sewardj   convert_f64le_to_f80le( (UChar*)&f64, (UChar*)ULong_to_Ptr(addrU) );
124317442fe8094d0f82266e5a05509f62cac8f7539esewardj}
124417442fe8094d0f82266e5a05509f62cac8f7539esewardj
12450c2cb623cca372a2b42b073121c7413cdaaf75besewardj
12460c2cb623cca372a2b42b073121c7413cdaaf75besewardj/*----------------------------------------------*/
12470c2cb623cca372a2b42b073121c7413cdaaf75besewardj/*--- The exported fns ..                    ---*/
12480c2cb623cca372a2b42b073121c7413cdaaf75besewardj/*----------------------------------------------*/
12490c2cb623cca372a2b42b073121c7413cdaaf75besewardj
12500c2cb623cca372a2b42b073121c7413cdaaf75besewardj/* Layout of the real x87 state. */
12514017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj/* 13 June 05: Fpu_State and auxiliary constants was moved to
12524017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj   g_generic_x87.h */
12530c2cb623cca372a2b42b073121c7413cdaaf75besewardj
12540c2cb623cca372a2b42b073121c7413cdaaf75besewardj
12557df596b1e36840e2d74c90aa55589934add61ccfsewardj/* CLEAN HELPER */
1256a0e83b06f304527e3e9aec527c344e35e7023d76sewardj/* fpucw[15:0] contains a x87 native format FPU control word.
1257d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj   Extract from it the required FPROUND value and any resulting
1258d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj   emulation warning, and return (warn << 32) | fpround value.
1259d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj*/
12603bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardjULong x86g_check_fldcw ( UInt fpucw )
1261893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj{
1262d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj   /* Decide on a rounding mode.  fpucw[11:10] holds it. */
1263d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj   /* NOTE, encoded exactly as per enum IRRoundingMode. */
1264893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj   UInt rmode = (fpucw >> 10) & 3;
1265893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj
1266893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj   /* Detect any required emulation warnings. */
1267893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj   VexEmWarn ew = EmWarn_NONE;
1268893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj
1269893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj   if ((fpucw & 0x3F) != 0x3F) {
1270893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj      /* unmasked exceptions! */
1271893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj      ew = EmWarn_X86_x87exns;
1272893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj   }
1273893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj   else
1274893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj   if (((fpucw >> 8) & 3) != 3) {
1275893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj      /* unsupported precision */
1276893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj      ew = EmWarn_X86_x87precision;
1277893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj   }
1278893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj
1279d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj   return (((ULong)ew) << 32) | ((ULong)rmode);
1280893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj}
1281893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj
1282893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj/* CLEAN HELPER */
12837df596b1e36840e2d74c90aa55589934add61ccfsewardj/* Given fpround as an IRRoundingMode value, create a suitable x87
12847df596b1e36840e2d74c90aa55589934add61ccfsewardj   native format FPU control word. */
12853bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardjUInt x86g_create_fpucw ( UInt fpround )
1286893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj{
1287d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj   fpround &= 3;
1288d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj   return 0x037F | (fpround << 10);
1289893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj}
1290893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj
1291893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj
12927df596b1e36840e2d74c90aa55589934add61ccfsewardj/* CLEAN HELPER */
1293a0e83b06f304527e3e9aec527c344e35e7023d76sewardj/* mxcsr[15:0] contains a SSE native format MXCSR value.
12947df596b1e36840e2d74c90aa55589934add61ccfsewardj   Extract from it the required SSEROUND value and any resulting
12957df596b1e36840e2d74c90aa55589934add61ccfsewardj   emulation warning, and return (warn << 32) | sseround value.
12967df596b1e36840e2d74c90aa55589934add61ccfsewardj*/
12973bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardjULong x86g_check_ldmxcsr ( UInt mxcsr )
12987df596b1e36840e2d74c90aa55589934add61ccfsewardj{
12997df596b1e36840e2d74c90aa55589934add61ccfsewardj   /* Decide on a rounding mode.  mxcsr[14:13] holds it. */
13007df596b1e36840e2d74c90aa55589934add61ccfsewardj   /* NOTE, encoded exactly as per enum IRRoundingMode. */
13017df596b1e36840e2d74c90aa55589934add61ccfsewardj   UInt rmode = (mxcsr >> 13) & 3;
13027df596b1e36840e2d74c90aa55589934add61ccfsewardj
13037df596b1e36840e2d74c90aa55589934add61ccfsewardj   /* Detect any required emulation warnings. */
13047df596b1e36840e2d74c90aa55589934add61ccfsewardj   VexEmWarn ew = EmWarn_NONE;
13057df596b1e36840e2d74c90aa55589934add61ccfsewardj
13067df596b1e36840e2d74c90aa55589934add61ccfsewardj   if ((mxcsr & 0x1F80) != 0x1F80) {
13077df596b1e36840e2d74c90aa55589934add61ccfsewardj      /* unmasked exceptions! */
13087df596b1e36840e2d74c90aa55589934add61ccfsewardj      ew = EmWarn_X86_sseExns;
13097df596b1e36840e2d74c90aa55589934add61ccfsewardj   }
13107df596b1e36840e2d74c90aa55589934add61ccfsewardj   else
13115edfc26d72ca8ebea2aa0443a1ed4dd218343d04sewardj   if (mxcsr & (1<<15)) {
13125edfc26d72ca8ebea2aa0443a1ed4dd218343d04sewardj      /* FZ is set */
13135edfc26d72ca8ebea2aa0443a1ed4dd218343d04sewardj      ew = EmWarn_X86_fz;
13145edfc26d72ca8ebea2aa0443a1ed4dd218343d04sewardj   }
13155edfc26d72ca8ebea2aa0443a1ed4dd218343d04sewardj   else
13165edfc26d72ca8ebea2aa0443a1ed4dd218343d04sewardj   if (mxcsr & (1<<6)) {
13175edfc26d72ca8ebea2aa0443a1ed4dd218343d04sewardj      /* DAZ is set */
13185edfc26d72ca8ebea2aa0443a1ed4dd218343d04sewardj      ew = EmWarn_X86_daz;
13197df596b1e36840e2d74c90aa55589934add61ccfsewardj   }
13207df596b1e36840e2d74c90aa55589934add61ccfsewardj
13217df596b1e36840e2d74c90aa55589934add61ccfsewardj   return (((ULong)ew) << 32) | ((ULong)rmode);
13227df596b1e36840e2d74c90aa55589934add61ccfsewardj}
13237df596b1e36840e2d74c90aa55589934add61ccfsewardj
13247df596b1e36840e2d74c90aa55589934add61ccfsewardj
13257df596b1e36840e2d74c90aa55589934add61ccfsewardj/* CLEAN HELPER */
13267df596b1e36840e2d74c90aa55589934add61ccfsewardj/* Given sseround as an IRRoundingMode value, create a suitable SSE
13277df596b1e36840e2d74c90aa55589934add61ccfsewardj   native format MXCSR value. */
13283bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardjUInt x86g_create_mxcsr ( UInt sseround )
13297df596b1e36840e2d74c90aa55589934add61ccfsewardj{
13307df596b1e36840e2d74c90aa55589934add61ccfsewardj   sseround &= 3;
13317df596b1e36840e2d74c90aa55589934add61ccfsewardj   return 0x1F80 | (sseround << 13);
13327df596b1e36840e2d74c90aa55589934add61ccfsewardj}
13337df596b1e36840e2d74c90aa55589934add61ccfsewardj
13347df596b1e36840e2d74c90aa55589934add61ccfsewardj
1335a0e83b06f304527e3e9aec527c344e35e7023d76sewardj/* CALLED FROM GENERATED CODE */
1336a0e83b06f304527e3e9aec527c344e35e7023d76sewardj/* DIRTY HELPER (writes guest state) */
1337a0e83b06f304527e3e9aec527c344e35e7023d76sewardj/* Initialise the x87 FPU state as per 'finit'. */
1338a0e83b06f304527e3e9aec527c344e35e7023d76sewardjvoid x86g_dirtyhelper_FINIT ( VexGuestX86State* gst )
1339a0e83b06f304527e3e9aec527c344e35e7023d76sewardj{
1340a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   Int i;
1341a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   gst->guest_FTOP = 0;
1342a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   for (i = 0; i < 8; i++) {
1343a0e83b06f304527e3e9aec527c344e35e7023d76sewardj      gst->guest_FPTAG[i] = 0; /* empty */
1344a0e83b06f304527e3e9aec527c344e35e7023d76sewardj      gst->guest_FPREG[i] = 0; /* IEEE754 64-bit zero */
1345a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   }
1346a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   gst->guest_FPROUND = (UInt)Irrm_NEAREST;
1347a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   gst->guest_FC3210  = 0;
1348a0e83b06f304527e3e9aec527c344e35e7023d76sewardj}
1349a0e83b06f304527e3e9aec527c344e35e7023d76sewardj
1350a0e83b06f304527e3e9aec527c344e35e7023d76sewardj
13517df596b1e36840e2d74c90aa55589934add61ccfsewardj/* This is used to implement both 'frstor' and 'fldenv'.  The latter
13527df596b1e36840e2d74c90aa55589934add61ccfsewardj   appears to differ from the former only in that the 8 FP registers
13537df596b1e36840e2d74c90aa55589934add61ccfsewardj   themselves are not transferred into the guest state. */
13547df596b1e36840e2d74c90aa55589934add61ccfsewardjstatic
135538a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjVexEmWarn do_put_x87 ( Bool moveRegs,
135638a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj                       /*IN*/UChar* x87_state,
135738a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj                       /*OUT*/VexGuestX86State* vex_state )
13580c2cb623cca372a2b42b073121c7413cdaaf75besewardj{
1359a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   Int        stno, preg;
13600c2cb623cca372a2b42b073121c7413cdaaf75besewardj   UInt       tag;
1361f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj   Double*    vexRegs = (Double*)(&vex_state->guest_FPREG[0]);
1362f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj   UChar*     vexTags = (UChar*)(&vex_state->guest_FPTAG[0]);
13630c2cb623cca372a2b42b073121c7413cdaaf75besewardj   Fpu_State* x87     = (Fpu_State*)x87_state;
13640c2cb623cca372a2b42b073121c7413cdaaf75besewardj   UInt       ftop    = (x87->env[FP_ENV_STAT] >> 11) & 7;
13650c2cb623cca372a2b42b073121c7413cdaaf75besewardj   UInt       tagw    = x87->env[FP_ENV_TAG];
13666e0dbda4f7ea53dd29996d4d429d3c5c92ee3640sewardj   UInt       fpucw   = x87->env[FP_ENV_CTRL];
1367c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   UInt       c3210   = x87->env[FP_ENV_STAT] & 0x4700;
1368893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj   VexEmWarn  ew;
1369d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj   UInt       fpround;
1370893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj   ULong      pair;
13710c2cb623cca372a2b42b073121c7413cdaaf75besewardj
13720c2cb623cca372a2b42b073121c7413cdaaf75besewardj   /* Copy registers and tags */
1373a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   for (stno = 0; stno < 8; stno++) {
1374a0e83b06f304527e3e9aec527c344e35e7023d76sewardj      preg = (stno + ftop) & 7;
1375a0e83b06f304527e3e9aec527c344e35e7023d76sewardj      tag = (tagw >> (2*preg)) & 3;
13760c2cb623cca372a2b42b073121c7413cdaaf75besewardj      if (tag == 3) {
13770c2cb623cca372a2b42b073121c7413cdaaf75besewardj         /* register is empty */
1378a0e83b06f304527e3e9aec527c344e35e7023d76sewardj         /* hmm, if it's empty, does it still get written?  Probably
1379a0e83b06f304527e3e9aec527c344e35e7023d76sewardj            safer to say it does.  If we don't, memcheck could get out
1380a0e83b06f304527e3e9aec527c344e35e7023d76sewardj            of sync, in that it thinks all FP registers are defined by
1381a0e83b06f304527e3e9aec527c344e35e7023d76sewardj            this helper, but in reality some have not been updated. */
13820f33861a0aaf18e89f5f24fd5bdfa39a9049dadasewardj         if (moveRegs)
1383a0e83b06f304527e3e9aec527c344e35e7023d76sewardj            vexRegs[preg] = 0.0;
1384a0e83b06f304527e3e9aec527c344e35e7023d76sewardj         vexTags[preg] = 0;
13850c2cb623cca372a2b42b073121c7413cdaaf75besewardj      } else {
13860c2cb623cca372a2b42b073121c7413cdaaf75besewardj         /* register is non-empty */
13877df596b1e36840e2d74c90aa55589934add61ccfsewardj         if (moveRegs)
1388a0e83b06f304527e3e9aec527c344e35e7023d76sewardj            convert_f80le_to_f64le( &x87->reg[10*stno],
1389a0e83b06f304527e3e9aec527c344e35e7023d76sewardj                                    (UChar*)&vexRegs[preg] );
1390a0e83b06f304527e3e9aec527c344e35e7023d76sewardj         vexTags[preg] = 1;
13910c2cb623cca372a2b42b073121c7413cdaaf75besewardj      }
13920c2cb623cca372a2b42b073121c7413cdaaf75besewardj   }
13930c2cb623cca372a2b42b073121c7413cdaaf75besewardj
13940c2cb623cca372a2b42b073121c7413cdaaf75besewardj   /* stack pointer */
1395f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj   vex_state->guest_FTOP = ftop;
13960c2cb623cca372a2b42b073121c7413cdaaf75besewardj
13973f868e5262a8d2488f41cc49058ba60c24843c3esewardj   /* status word */
1398f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj   vex_state->guest_FC3210 = c3210;
1399893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj
1400d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj   /* handle the control word, setting FPROUND and detecting any
1401893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj      emulation warnings. */
14023bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   pair    = x86g_check_fldcw ( (UInt)fpucw );
1403d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj   fpround = (UInt)pair;
1404d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj   ew      = (VexEmWarn)(pair >> 32);
1405893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj
1406d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj   vex_state->guest_FPROUND = fpround & 3;
1407893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj
1408893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj   /* emulation warnings --> caller */
1409893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj   return ew;
14100c2cb623cca372a2b42b073121c7413cdaaf75besewardj}
14110c2cb623cca372a2b42b073121c7413cdaaf75besewardj
14126e0dbda4f7ea53dd29996d4d429d3c5c92ee3640sewardj
1413a0e83b06f304527e3e9aec527c344e35e7023d76sewardj/* Create an x87 FPU state from the guest state, as close as
1414a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   we can approximate it. */
141538a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic
141638a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjvoid do_get_x87 ( /*IN*/VexGuestX86State* vex_state,
141738a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj                  /*OUT*/UChar* x87_state )
14180c2cb623cca372a2b42b073121c7413cdaaf75besewardj{
1419a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   Int        i, stno, preg;
14200c2cb623cca372a2b42b073121c7413cdaaf75besewardj   UInt       tagw;
1421f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj   Double*    vexRegs = (Double*)(&vex_state->guest_FPREG[0]);
1422f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj   UChar*     vexTags = (UChar*)(&vex_state->guest_FPTAG[0]);
14230c2cb623cca372a2b42b073121c7413cdaaf75besewardj   Fpu_State* x87     = (Fpu_State*)x87_state;
1424f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj   UInt       ftop    = vex_state->guest_FTOP;
1425f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj   UInt       c3210   = vex_state->guest_FC3210;
14260c2cb623cca372a2b42b073121c7413cdaaf75besewardj
14270c2cb623cca372a2b42b073121c7413cdaaf75besewardj   for (i = 0; i < 14; i++)
14280c2cb623cca372a2b42b073121c7413cdaaf75besewardj      x87->env[i] = 0;
14290c2cb623cca372a2b42b073121c7413cdaaf75besewardj
14300c2cb623cca372a2b42b073121c7413cdaaf75besewardj   x87->env[1] = x87->env[3] = x87->env[5] = x87->env[13] = 0xFFFF;
1431a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   x87->env[FP_ENV_STAT]
1432a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj      = toUShort(((ftop & 7) << 11) | (c3210 & 0x4700));
1433893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj   x87->env[FP_ENV_CTRL]
1434a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj      = toUShort(x86g_create_fpucw( vex_state->guest_FPROUND ));
14350c2cb623cca372a2b42b073121c7413cdaaf75besewardj
1436a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   /* Dump the register stack in ST order. */
14370c2cb623cca372a2b42b073121c7413cdaaf75besewardj   tagw = 0;
1438a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   for (stno = 0; stno < 8; stno++) {
1439a0e83b06f304527e3e9aec527c344e35e7023d76sewardj      preg = (stno + ftop) & 7;
1440a0e83b06f304527e3e9aec527c344e35e7023d76sewardj      if (vexTags[preg] == 0) {
14410c2cb623cca372a2b42b073121c7413cdaaf75besewardj         /* register is empty */
1442a0e83b06f304527e3e9aec527c344e35e7023d76sewardj         tagw |= (3 << (2*preg));
1443a0e83b06f304527e3e9aec527c344e35e7023d76sewardj         convert_f64le_to_f80le( (UChar*)&vexRegs[preg],
1444a0e83b06f304527e3e9aec527c344e35e7023d76sewardj                                 &x87->reg[10*stno] );
14450c2cb623cca372a2b42b073121c7413cdaaf75besewardj      } else {
14460c2cb623cca372a2b42b073121c7413cdaaf75besewardj         /* register is full. */
1447a0e83b06f304527e3e9aec527c344e35e7023d76sewardj         tagw |= (0 << (2*preg));
1448a0e83b06f304527e3e9aec527c344e35e7023d76sewardj         convert_f64le_to_f80le( (UChar*)&vexRegs[preg],
1449a0e83b06f304527e3e9aec527c344e35e7023d76sewardj                                 &x87->reg[10*stno] );
14500c2cb623cca372a2b42b073121c7413cdaaf75besewardj      }
14510c2cb623cca372a2b42b073121c7413cdaaf75besewardj   }
1452a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   x87->env[FP_ENV_TAG] = toUShort(tagw);
14530c2cb623cca372a2b42b073121c7413cdaaf75besewardj}
14540c2cb623cca372a2b42b073121c7413cdaaf75besewardj
14550c2cb623cca372a2b42b073121c7413cdaaf75besewardj
1456893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/* CALLED FROM GENERATED CODE */
1457893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/* DIRTY HELPER (reads guest state, writes guest mem) */
1458893a3302cc943e2ad1db421a8e6a753f82f532a7sewardjvoid x86g_dirtyhelper_FXSAVE ( VexGuestX86State* gst, HWord addr )
1459f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj{
1460893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   /* Somewhat roundabout, but at least it's simple. */
1461893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   Fpu_State tmp;
1462893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   UShort*   addrS = (UShort*)addr;
1463893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   UChar*    addrC = (UChar*)addr;
1464893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   U128*     xmm   = (U128*)(addr + 160);
1465893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   UInt      mxcsr;
1466893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   UShort    fp_tags;
1467a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   UInt      summary_tags;
1468893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   Int       r, stno;
1469893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   UShort    *srcS, *dstS;
1470f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj
1471893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   do_get_x87( gst, (UChar*)&tmp );
1472893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   mxcsr = x86g_create_mxcsr( gst->guest_SSEROUND );
147376bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj
1474893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   /* Now build the proper fxsave image from the x87 image we just
1475893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      made. */
147676bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj
1477893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   addrS[0]  = tmp.env[FP_ENV_CTRL]; /* FCW: fpu control word */
1478893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   addrS[1]  = tmp.env[FP_ENV_STAT]; /* FCW: fpu status word */
147976bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj
1480893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   /* set addrS[2] in an endian-independent way */
1481893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   summary_tags = 0;
1482893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   fp_tags = tmp.env[FP_ENV_TAG];
1483893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   for (r = 0; r < 8; r++) {
1484893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      if ( ((fp_tags >> (2*r)) & 3) != 3 )
1485893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj         summary_tags |= (1 << r);
1486893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   }
1487a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   addrC[4]  = toUChar(summary_tags); /* FTW: tag summary byte */
1488893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   addrC[5]  = 0; /* pad */
148976bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj
1490893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   addrS[3]  = 0; /* FOP: fpu opcode (bogus) */
1491893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   addrS[4]  = 0;
1492893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   addrS[5]  = 0; /* FPU IP (bogus) */
1493893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   addrS[6]  = 0; /* FPU IP's segment selector (bogus) (although we
1494893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj                     could conceivably dump %CS here) */
1495c9a43665879a03886b27a65b68af2a2c11b04f59sewardj
1496893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   addrS[7]  = 0; /* Intel reserved */
1497c9a43665879a03886b27a65b68af2a2c11b04f59sewardj
1498893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   addrS[8]  = 0; /* FPU DP (operand pointer) (bogus) */
1499893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   addrS[9]  = 0; /* FPU DP (operand pointer) (bogus) */
1500893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   addrS[10] = 0; /* segment selector for above operand pointer; %DS
1501893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj                     perhaps? */
1502893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   addrS[11] = 0; /* Intel reserved */
1503c9a43665879a03886b27a65b68af2a2c11b04f59sewardj
1504a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   addrS[12] = toUShort(mxcsr);  /* MXCSR */
1505a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   addrS[13] = toUShort(mxcsr >> 16);
1506893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj
1507893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   addrS[14] = 0xFFFF; /* MXCSR mask (lo16); who knows what for */
1508893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   addrS[15] = 0xFFFF; /* MXCSR mask (hi16); who knows what for */
1509893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
1510893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   /* Copy in the FP registers, in ST order. */
1511893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   for (stno = 0; stno < 8; stno++) {
1512893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      srcS = (UShort*)(&tmp.reg[10*stno]);
1513893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      dstS = (UShort*)(&addrS[16 + 8*stno]);
1514893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      dstS[0] = srcS[0];
1515893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      dstS[1] = srcS[1];
1516893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      dstS[2] = srcS[2];
1517893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      dstS[3] = srcS[3];
1518893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      dstS[4] = srcS[4];
1519893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      dstS[5] = 0;
1520893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      dstS[6] = 0;
1521893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      dstS[7] = 0;
1522893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   }
1523893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
1524893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   /* That's the first 160 bytes of the image done.  Now only %xmm0
1525893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      .. %xmm7 remain to be copied.  If the host is big-endian, these
1526893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      need to be byte-swapped. */
1527893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vassert(host_is_little_endian());
1528893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
1529893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj#  define COPY_U128(_dst,_src)                       \
1530893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      do { _dst[0] = _src[0]; _dst[1] = _src[1];     \
1531893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj           _dst[2] = _src[2]; _dst[3] = _src[3]; }   \
1532893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      while (0)
1533893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
1534893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   COPY_U128( xmm[0], gst->guest_XMM0 );
1535893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   COPY_U128( xmm[1], gst->guest_XMM1 );
1536893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   COPY_U128( xmm[2], gst->guest_XMM2 );
1537893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   COPY_U128( xmm[3], gst->guest_XMM3 );
1538893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   COPY_U128( xmm[4], gst->guest_XMM4 );
1539893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   COPY_U128( xmm[5], gst->guest_XMM5 );
1540893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   COPY_U128( xmm[6], gst->guest_XMM6 );
1541893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   COPY_U128( xmm[7], gst->guest_XMM7 );
1542893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
1543893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj#  undef COPY_U128
1544dda7a4c98be4c7c6f11eab4e1cad6ab275aed79csewardj}
1545f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj
1546f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj
1547893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/* CALLED FROM GENERATED CODE */
1548893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/* DIRTY HELPER (reads guest state, writes guest mem) */
1549893a3302cc943e2ad1db421a8e6a753f82f532a7sewardjvoid x86g_dirtyhelper_FSAVE ( VexGuestX86State* gst, HWord addr )
1550893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj{
1551893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   do_get_x87( gst, (UChar*)addr );
1552893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj}
1553893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
1554893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/* CALLED FROM GENERATED CODE */
1555893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/* DIRTY HELPER (writes guest state, reads guest mem) */
1556893a3302cc943e2ad1db421a8e6a753f82f532a7sewardjVexEmWarn x86g_dirtyhelper_FRSTOR ( VexGuestX86State* gst, HWord addr )
1557893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj{
1558893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   return do_put_x87( True/*regs too*/, (UChar*)addr, gst );
1559893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj}
1560893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
1561893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/* CALLED FROM GENERATED CODE */
1562893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/* DIRTY HELPER (reads guest state, writes guest mem) */
1563893a3302cc943e2ad1db421a8e6a753f82f532a7sewardjvoid x86g_dirtyhelper_FSTENV ( VexGuestX86State* gst, HWord addr )
1564893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj{
1565893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   /* Somewhat roundabout, but at least it's simple. */
1566893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   Int       i;
1567893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   UShort*   addrP = (UShort*)addr;
1568893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   Fpu_State tmp;
1569893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   do_get_x87( gst, (UChar*)&tmp );
1570893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   for (i = 0; i < 14; i++)
1571893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      addrP[i] = tmp.env[i];
1572893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj}
1573893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
1574893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/* CALLED FROM GENERATED CODE */
1575893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/* DIRTY HELPER (writes guest state, reads guest mem) */
1576893a3302cc943e2ad1db421a8e6a753f82f532a7sewardjVexEmWarn x86g_dirtyhelper_FLDENV ( VexGuestX86State* gst, HWord addr )
1577893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj{
1578893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   return do_put_x87( False/*don't move regs*/, (UChar*)addr, gst);
1579893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj}
1580893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
1581893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
1582893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/*---------------------------------------------------------------*/
1583893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/*--- Misc integer helpers, including rotates and CPUID.      ---*/
1584893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/*---------------------------------------------------------------*/
15859aebb0c3f7a7f43313786826f31402f2b733badfsewardj
15869aebb0c3f7a7f43313786826f31402f2b733badfsewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
15879aebb0c3f7a7f43313786826f31402f2b733badfsewardj/* Calculate both flags and value result for rotate right
15889aebb0c3f7a7f43313786826f31402f2b733badfsewardj   through the carry bit.  Result in low 32 bits,
15899aebb0c3f7a7f43313786826f31402f2b733badfsewardj   new flags (OSZACP) in high 32 bits.
15909aebb0c3f7a7f43313786826f31402f2b733badfsewardj*/
15912a9ad023890d3b34cf45e429df2a8ae88b419128sewardjULong x86g_calculate_RCR ( UInt arg, UInt rot_amt, UInt eflags_in, UInt sz )
15929aebb0c3f7a7f43313786826f31402f2b733badfsewardj{
15939aebb0c3f7a7f43313786826f31402f2b733badfsewardj   UInt tempCOUNT = rot_amt & 0x1F, cf=0, of=0, tempcf;
15949aebb0c3f7a7f43313786826f31402f2b733badfsewardj
15959aebb0c3f7a7f43313786826f31402f2b733badfsewardj   switch (sz) {
15969aebb0c3f7a7f43313786826f31402f2b733badfsewardj      case 4:
15972a9ad023890d3b34cf45e429df2a8ae88b419128sewardj         cf        = (eflags_in >> X86G_CC_SHIFT_C) & 1;
15989aebb0c3f7a7f43313786826f31402f2b733badfsewardj         of        = ((arg >> 31) ^ cf) & 1;
15999aebb0c3f7a7f43313786826f31402f2b733badfsewardj         while (tempCOUNT > 0) {
16009aebb0c3f7a7f43313786826f31402f2b733badfsewardj            tempcf = arg & 1;
16019aebb0c3f7a7f43313786826f31402f2b733badfsewardj            arg    = (arg >> 1) | (cf << 31);
16029aebb0c3f7a7f43313786826f31402f2b733badfsewardj            cf     = tempcf;
16039aebb0c3f7a7f43313786826f31402f2b733badfsewardj            tempCOUNT--;
16049aebb0c3f7a7f43313786826f31402f2b733badfsewardj         }
16059aebb0c3f7a7f43313786826f31402f2b733badfsewardj         break;
16069aebb0c3f7a7f43313786826f31402f2b733badfsewardj      case 2:
16079aebb0c3f7a7f43313786826f31402f2b733badfsewardj         while (tempCOUNT >= 17) tempCOUNT -= 17;
16082a9ad023890d3b34cf45e429df2a8ae88b419128sewardj         cf        = (eflags_in >> X86G_CC_SHIFT_C) & 1;
16099aebb0c3f7a7f43313786826f31402f2b733badfsewardj         of        = ((arg >> 15) ^ cf) & 1;
16109aebb0c3f7a7f43313786826f31402f2b733badfsewardj         while (tempCOUNT > 0) {
16119aebb0c3f7a7f43313786826f31402f2b733badfsewardj            tempcf = arg & 1;
16129aebb0c3f7a7f43313786826f31402f2b733badfsewardj            arg    = ((arg >> 1) & 0x7FFF) | (cf << 15);
16139aebb0c3f7a7f43313786826f31402f2b733badfsewardj            cf     = tempcf;
16149aebb0c3f7a7f43313786826f31402f2b733badfsewardj            tempCOUNT--;
16159aebb0c3f7a7f43313786826f31402f2b733badfsewardj         }
16169aebb0c3f7a7f43313786826f31402f2b733badfsewardj         break;
16179aebb0c3f7a7f43313786826f31402f2b733badfsewardj      case 1:
16189aebb0c3f7a7f43313786826f31402f2b733badfsewardj         while (tempCOUNT >= 9) tempCOUNT -= 9;
16192a9ad023890d3b34cf45e429df2a8ae88b419128sewardj         cf        = (eflags_in >> X86G_CC_SHIFT_C) & 1;
16209aebb0c3f7a7f43313786826f31402f2b733badfsewardj         of        = ((arg >> 7) ^ cf) & 1;
16219aebb0c3f7a7f43313786826f31402f2b733badfsewardj         while (tempCOUNT > 0) {
16229aebb0c3f7a7f43313786826f31402f2b733badfsewardj            tempcf = arg & 1;
16239aebb0c3f7a7f43313786826f31402f2b733badfsewardj            arg    = ((arg >> 1) & 0x7F) | (cf << 7);
16249aebb0c3f7a7f43313786826f31402f2b733badfsewardj            cf     = tempcf;
16259aebb0c3f7a7f43313786826f31402f2b733badfsewardj            tempCOUNT--;
16269aebb0c3f7a7f43313786826f31402f2b733badfsewardj         }
16279aebb0c3f7a7f43313786826f31402f2b733badfsewardj         break;
16289aebb0c3f7a7f43313786826f31402f2b733badfsewardj      default:
16299aebb0c3f7a7f43313786826f31402f2b733badfsewardj         vpanic("calculate_RCR: invalid size");
16309aebb0c3f7a7f43313786826f31402f2b733badfsewardj   }
16319aebb0c3f7a7f43313786826f31402f2b733badfsewardj
16329aebb0c3f7a7f43313786826f31402f2b733badfsewardj   cf &= 1;
16339aebb0c3f7a7f43313786826f31402f2b733badfsewardj   of &= 1;
16342a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   eflags_in &= ~(X86G_CC_MASK_C | X86G_CC_MASK_O);
16352a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   eflags_in |= (cf << X86G_CC_SHIFT_C) | (of << X86G_CC_SHIFT_O);
16369aebb0c3f7a7f43313786826f31402f2b733badfsewardj
16379aebb0c3f7a7f43313786826f31402f2b733badfsewardj   return (((ULong)eflags_in) << 32) | ((ULong)arg);
16389aebb0c3f7a7f43313786826f31402f2b733badfsewardj}
16399aebb0c3f7a7f43313786826f31402f2b733badfsewardj
16407cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardj
16412eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
16422eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj/* Calculate both flags and value result for rotate left
16432eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj   through the carry bit.  Result in low 32 bits,
16442eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj   new flags (OSZACP) in high 32 bits.
16452eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj*/
16462eef773d07df9bbc5d62c0058ae99d5511c2759dsewardjULong x86g_calculate_RCL ( UInt arg, UInt rot_amt, UInt eflags_in, UInt sz )
16472eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj{
16482eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj   UInt tempCOUNT = rot_amt & 0x1F, cf=0, of=0, tempcf;
16492eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj
16502eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj   switch (sz) {
16512eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj      case 4:
16522eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj         cf = (eflags_in >> X86G_CC_SHIFT_C) & 1;
16532eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj         while (tempCOUNT > 0) {
16542eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj            tempcf = (arg >> 31) & 1;
16552eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj            arg    = (arg << 1) | (cf & 1);
16562eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj            cf     = tempcf;
16572eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj            tempCOUNT--;
16582eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj         }
16592eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj         of = ((arg >> 31) ^ cf) & 1;
16602eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj         break;
16612eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj      case 2:
16622eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj         while (tempCOUNT >= 17) tempCOUNT -= 17;
16632eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj         cf = (eflags_in >> X86G_CC_SHIFT_C) & 1;
16642eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj         while (tempCOUNT > 0) {
16652eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj            tempcf = (arg >> 15) & 1;
16662eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj            arg    = 0xFFFF & ((arg << 1) | (cf & 1));
16672eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj            cf     = tempcf;
16682eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj            tempCOUNT--;
16692eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj         }
16702eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj         of = ((arg >> 15) ^ cf) & 1;
16712eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj         break;
16722eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj      case 1:
16732eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj         while (tempCOUNT >= 9) tempCOUNT -= 9;
16742eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj         cf = (eflags_in >> X86G_CC_SHIFT_C) & 1;
16752eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj         while (tempCOUNT > 0) {
16762eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj            tempcf = (arg >> 7) & 1;
16772eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj            arg    = 0xFF & ((arg << 1) | (cf & 1));
16782eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj            cf     = tempcf;
16792eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj            tempCOUNT--;
16802eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj         }
16812eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj         of = ((arg >> 7) ^ cf) & 1;
16822eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj         break;
16832eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj      default:
16842eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj         vpanic("calculate_RCL: invalid size");
16852eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj   }
16862eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj
16872eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj   cf &= 1;
16882eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj   of &= 1;
16892eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj   eflags_in &= ~(X86G_CC_MASK_C | X86G_CC_MASK_O);
16902eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj   eflags_in |= (cf << X86G_CC_SHIFT_C) | (of << X86G_CC_SHIFT_O);
16912eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj
16922eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj   return (((ULong)eflags_in) << 32) | ((ULong)arg);
16932eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj}
16942eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj
16952eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj
16967cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardj/* CALLED FROM GENERATED CODE */
16977cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardj/* DIRTY HELPER (modifies guest state) */
16984ba6ed0799fcf768e3fb9627fabc52fb1d6c2a6csewardj/* Claim to be a P55C (Intel Pentium/MMX) */
16999df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardjvoid x86g_dirtyhelper_CPUID_sse0 ( VexGuestX86State* st )
17007cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardj{
17019df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   switch (st->guest_EAX) {
17029df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj      case 0:
17039df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EAX = 0x1;
17049df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EBX = 0x756e6547;
17059df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_ECX = 0x6c65746e;
17069df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EDX = 0x49656e69;
17079df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         break;
17089df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj      default:
17099df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EAX = 0x543;
17109df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EBX = 0x0;
17119df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_ECX = 0x0;
17129df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EDX = 0x8001bf;
17139df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         break;
17149df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   }
17159df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj}
17169df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj
17179df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj/* CALLED FROM GENERATED CODE */
17189df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj/* DIRTY HELPER (modifies guest state) */
17199df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj/* Claim to be the following SSE1-capable CPU:
17209df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   vendor_id       : GenuineIntel
17219df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   cpu family      : 6
17229df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   model           : 11
17239df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   model name      : Intel(R) Pentium(R) III CPU family      1133MHz
17249df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   stepping        : 1
17259df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   cpu MHz         : 1131.013
17269df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   cache size      : 512 KB
17279df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj*/
17289df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardjvoid x86g_dirtyhelper_CPUID_sse1 ( VexGuestX86State* st )
17299df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj{
17309df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   switch (st->guest_EAX) {
17319df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj      case 0:
17329df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EAX = 0x00000002;
17339df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EBX = 0x756e6547;
17349df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_ECX = 0x6c65746e;
17359df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EDX = 0x49656e69;
17369df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         break;
17379df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj      case 1:
17389df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EAX = 0x000006b1;
17399df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EBX = 0x00000004;
17409df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_ECX = 0x00000000;
17419df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EDX = 0x0383fbff;
17429df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         break;
17439df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj      default:
17449df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EAX = 0x03020101;
17459df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EBX = 0x00000000;
17469df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_ECX = 0x00000000;
17479df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EDX = 0x0c040883;
17489df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         break;
17499df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   }
17509df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj}
17519df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj
17529df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj/* Claim to be the following SSE2-capable CPU:
17539df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   vendor_id       : GenuineIntel
17549df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   cpu family      : 15
17559df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   model           : 2
17569df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   model name      : Intel(R) Pentium(R) 4 CPU 2.40GHz
17579df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   stepping        : 7
17589df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   cpu MHz         : 2394.234
17599df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   cache size      : 512 KB
17609df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj*/
17619df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardjvoid x86g_dirtyhelper_CPUID_sse2 ( VexGuestX86State* st )
17629df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj{
17639df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   switch (st->guest_EAX) {
17649df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj      case 0:
17659df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EAX = 0x00000002;
17669df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EBX = 0x756e6547;
17679df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_ECX = 0x6c65746e;
17689df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EDX = 0x49656e69;
17699df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         break;
17709df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj      case 1:
17719df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EAX = 0x00000f27;
17729df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EBX = 0x00010809;
17739df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_ECX = 0x00004400;
17749df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EDX = 0xbfebfbff;
17759df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         break;
17769df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj      default:
17779df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EAX = 0x665b5101;
17789df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EBX = 0x00000000;
17799df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_ECX = 0x00000000;
17809df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EDX = 0x007b7040;
17819df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         break;
17827cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardj   }
17837cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardj}
17847cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardj
1785464efa446b2db97115d3e5f04af5db3464cc0e93sewardj
1786893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/*---------------------------------------------------------------*/
1787893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/*--- Helpers for MMX/SSE/SSE2.                               ---*/
1788893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/*---------------------------------------------------------------*/
1789464efa446b2db97115d3e5f04af5db3464cc0e93sewardj
179038a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UChar abdU8 ( UChar xx, UChar yy ) {
1791a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   return toUChar(xx>yy ? xx-yy : yy-xx);
179238a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj}
1793464efa446b2db97115d3e5f04af5db3464cc0e93sewardj
179438a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline ULong mk32x2 ( UInt w1, UInt w0 ) {
1795464efa446b2db97115d3e5f04af5db3464cc0e93sewardj   return (((ULong)w1) << 32) | ((ULong)w0);
1796464efa446b2db97115d3e5f04af5db3464cc0e93sewardj}
1797464efa446b2db97115d3e5f04af5db3464cc0e93sewardj
179838a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UShort sel16x4_3 ( ULong w64 ) {
1799a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   UInt hi32 = toUInt(w64 >> 32);
1800a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   return toUShort(hi32 >> 16);
1801464efa446b2db97115d3e5f04af5db3464cc0e93sewardj}
180238a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UShort sel16x4_2 ( ULong w64 ) {
1803a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   UInt hi32 = toUInt(w64 >> 32);
1804a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   return toUShort(hi32);
1805464efa446b2db97115d3e5f04af5db3464cc0e93sewardj}
180638a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UShort sel16x4_1 ( ULong w64 ) {
1807a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   UInt lo32 = toUInt(w64);
1808a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   return toUShort(lo32 >> 16);
1809464efa446b2db97115d3e5f04af5db3464cc0e93sewardj}
181038a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UShort sel16x4_0 ( ULong w64 ) {
1811a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   UInt lo32 = toUInt(w64);
1812a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   return toUShort(lo32);
1813464efa446b2db97115d3e5f04af5db3464cc0e93sewardj}
1814464efa446b2db97115d3e5f04af5db3464cc0e93sewardj
181538a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UChar sel8x8_7 ( ULong w64 ) {
1816a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   UInt hi32 = toUInt(w64 >> 32);
1817a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   return toUChar(hi32 >> 24);
1818464efa446b2db97115d3e5f04af5db3464cc0e93sewardj}
181938a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UChar sel8x8_6 ( ULong w64 ) {
1820a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   UInt hi32 = toUInt(w64 >> 32);
1821a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   return toUChar(hi32 >> 16);
1822464efa446b2db97115d3e5f04af5db3464cc0e93sewardj}
182338a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UChar sel8x8_5 ( ULong w64 ) {
1824a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   UInt hi32 = toUInt(w64 >> 32);
1825a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   return toUChar(hi32 >> 8);
1826464efa446b2db97115d3e5f04af5db3464cc0e93sewardj}
182738a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UChar sel8x8_4 ( ULong w64 ) {
1828a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   UInt hi32 = toUInt(w64 >> 32);
1829a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   return toUChar(hi32 >> 0);
1830464efa446b2db97115d3e5f04af5db3464cc0e93sewardj}
183138a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UChar sel8x8_3 ( ULong w64 ) {
1832a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   UInt lo32 = toUInt(w64);
1833a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   return toUChar(lo32 >> 24);
1834464efa446b2db97115d3e5f04af5db3464cc0e93sewardj}
183538a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UChar sel8x8_2 ( ULong w64 ) {
1836a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   UInt lo32 = toUInt(w64);
1837a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   return toUChar(lo32 >> 16);
1838464efa446b2db97115d3e5f04af5db3464cc0e93sewardj}
183938a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UChar sel8x8_1 ( ULong w64 ) {
1840a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   UInt lo32 = toUInt(w64);
1841a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   return toUChar(lo32 >> 8);
1842464efa446b2db97115d3e5f04af5db3464cc0e93sewardj}
184338a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UChar sel8x8_0 ( ULong w64 ) {
1844a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   UInt lo32 = toUInt(w64);
1845a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   return toUChar(lo32 >> 0);
1846464efa446b2db97115d3e5f04af5db3464cc0e93sewardj}
1847464efa446b2db97115d3e5f04af5db3464cc0e93sewardj
184838a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
184938a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjULong x86g_calculate_mmx_pmaddwd ( ULong xx, ULong yy )
18504340dac5c2cede4962868e6da5b73282da2bc465sewardj{
18514340dac5c2cede4962868e6da5b73282da2bc465sewardj   return
18524340dac5c2cede4962868e6da5b73282da2bc465sewardj      mk32x2(
18534340dac5c2cede4962868e6da5b73282da2bc465sewardj         (((Int)(Short)sel16x4_3(xx)) * ((Int)(Short)sel16x4_3(yy)))
18544340dac5c2cede4962868e6da5b73282da2bc465sewardj            + (((Int)(Short)sel16x4_2(xx)) * ((Int)(Short)sel16x4_2(yy))),
18554340dac5c2cede4962868e6da5b73282da2bc465sewardj         (((Int)(Short)sel16x4_1(xx)) * ((Int)(Short)sel16x4_1(yy)))
18564340dac5c2cede4962868e6da5b73282da2bc465sewardj            + (((Int)(Short)sel16x4_0(xx)) * ((Int)(Short)sel16x4_0(yy)))
18574340dac5c2cede4962868e6da5b73282da2bc465sewardj      );
18584340dac5c2cede4962868e6da5b73282da2bc465sewardj}
18594340dac5c2cede4962868e6da5b73282da2bc465sewardj
186038a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
186138a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjUInt x86g_calculate_mmx_pmovmskb ( ULong xx )
1862b54520819b40c3fe907725b56bcd8db5112c0b9asewardj{
1863b54520819b40c3fe907725b56bcd8db5112c0b9asewardj   UInt r = 0;
1864b54520819b40c3fe907725b56bcd8db5112c0b9asewardj   if (xx & (1ULL << (64-1))) r |= (1<<7);
1865b54520819b40c3fe907725b56bcd8db5112c0b9asewardj   if (xx & (1ULL << (56-1))) r |= (1<<6);
1866b54520819b40c3fe907725b56bcd8db5112c0b9asewardj   if (xx & (1ULL << (48-1))) r |= (1<<5);
1867b54520819b40c3fe907725b56bcd8db5112c0b9asewardj   if (xx & (1ULL << (40-1))) r |= (1<<4);
1868b54520819b40c3fe907725b56bcd8db5112c0b9asewardj   if (xx & (1ULL << (32-1))) r |= (1<<3);
1869b54520819b40c3fe907725b56bcd8db5112c0b9asewardj   if (xx & (1ULL << (24-1))) r |= (1<<2);
1870b54520819b40c3fe907725b56bcd8db5112c0b9asewardj   if (xx & (1ULL << (16-1))) r |= (1<<1);
1871b54520819b40c3fe907725b56bcd8db5112c0b9asewardj   if (xx & (1ULL << ( 8-1))) r |= (1<<0);
1872b54520819b40c3fe907725b56bcd8db5112c0b9asewardj   return r;
1873b54520819b40c3fe907725b56bcd8db5112c0b9asewardj}
1874b54520819b40c3fe907725b56bcd8db5112c0b9asewardj
187538a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
187638a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjULong x86g_calculate_mmx_psadbw ( ULong xx, ULong yy )
18770bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj{
18780bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj   UInt t = 0;
18790bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj   t += (UInt)abdU8( sel8x8_7(xx), sel8x8_7(yy) );
18800bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj   t += (UInt)abdU8( sel8x8_6(xx), sel8x8_6(yy) );
18810bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj   t += (UInt)abdU8( sel8x8_5(xx), sel8x8_5(yy) );
18820bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj   t += (UInt)abdU8( sel8x8_4(xx), sel8x8_4(yy) );
18830bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj   t += (UInt)abdU8( sel8x8_3(xx), sel8x8_3(yy) );
18840bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj   t += (UInt)abdU8( sel8x8_2(xx), sel8x8_2(yy) );
18850bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj   t += (UInt)abdU8( sel8x8_1(xx), sel8x8_1(yy) );
18860bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj   t += (UInt)abdU8( sel8x8_0(xx), sel8x8_0(yy) );
18870bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj   t &= 0xFFFF;
18880bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj   return (ULong)t;
18890bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj}
18900bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj
189138a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
1892e5854d6d470f21677ec84f71d09129434b044246sewardjUInt x86g_calculate_sse_pmovmskb ( ULong w64hi, ULong w64lo )
1893e5854d6d470f21677ec84f71d09129434b044246sewardj{
189438a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj   UInt rHi8 = x86g_calculate_mmx_pmovmskb ( w64hi );
189538a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj   UInt rLo8 = x86g_calculate_mmx_pmovmskb ( w64lo );
1896e5854d6d470f21677ec84f71d09129434b044246sewardj   return ((rHi8 & 0xFF) << 8) | (rLo8 & 0xFF);
1897e5854d6d470f21677ec84f71d09129434b044246sewardj}
1898e5854d6d470f21677ec84f71d09129434b044246sewardj
1899464efa446b2db97115d3e5f04af5db3464cc0e93sewardj
1900893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/*---------------------------------------------------------------*/
1901893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/*--- Helpers for dealing with segment overrides.             ---*/
1902893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/*---------------------------------------------------------------*/
19033bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
19043bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardjstatic inline
19053bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardjUInt get_segdescr_base ( VexGuestX86SegDescr* ent )
19063bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj{
19073bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   UInt lo  = 0xFFFF & (UInt)ent->LdtEnt.Bits.BaseLow;
19083bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   UInt mid =   0xFF & (UInt)ent->LdtEnt.Bits.BaseMid;
19093bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   UInt hi  =   0xFF & (UInt)ent->LdtEnt.Bits.BaseHi;
19103bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   return (hi << 24) | (mid << 16) | lo;
19113bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj}
19123bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
19133bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardjstatic inline
19143bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardjUInt get_segdescr_limit ( VexGuestX86SegDescr* ent )
19153bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj{
19163bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj    UInt lo    = 0xFFFF & (UInt)ent->LdtEnt.Bits.LimitLow;
19173bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj    UInt hi    =    0xF & (UInt)ent->LdtEnt.Bits.LimitHi;
19183bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj    UInt limit = (hi << 16) | lo;
19193bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj    if (ent->LdtEnt.Bits.Granularity)
19203bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj       limit = (limit << 12) | 0xFFF;
19213bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj    return limit;
19223bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj}
19233bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
192438a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
19253bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardjULong x86g_use_seg_selector ( HWord ldt, HWord gdt,
19263bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj                              UInt seg_selector, UInt virtual_addr )
19273bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj{
19283bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   UInt tiBit, base, limit;
19293bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   VexGuestX86SegDescr* the_descrs;
19303bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
19313bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   Bool verboze = False;
19323bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
19333bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   /* If this isn't true, we're in Big Trouble. */
19343bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   vassert(8 == sizeof(VexGuestX86SegDescr));
19353bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
19363bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   if (verboze)
19373bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      vex_printf("x86h_use_seg_selector: "
19383bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj                 "seg_selector = 0x%x, vaddr = 0x%x\n",
19393bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj                 seg_selector, virtual_addr);
19403bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
19413bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   /* Check for wildly invalid selector. */
19423bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   if (seg_selector & ~0xFFFF)
19433bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      goto bad;
19443bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
19453bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   seg_selector &= 0x0000FFFF;
19463bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
19473bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   /* Sanity check the segment selector.  Ensure that RPL=11b (least
19483bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      privilege).  This forms the bottom 2 bits of the selector. */
19493bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   if ((seg_selector & 3) != 3)
19503bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      goto bad;
19513bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
19523bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   /* Extract the TI bit (0 means GDT, 1 means LDT) */
19533bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   tiBit = (seg_selector >> 2) & 1;
19543bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
19553bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   /* Convert the segment selector onto a table index */
19563bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   seg_selector >>= 3;
19573bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   vassert(seg_selector >= 0 && seg_selector < 8192);
19583bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
19593bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   if (tiBit == 0) {
19603bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
19613bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      /* GDT access. */
19623bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      /* Do we actually have a GDT to look at? */
19633bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      if (gdt == 0)
19643bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj         goto bad;
19653bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
19663bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      /* Check for access to non-existent entry. */
19673bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      if (seg_selector >= VEX_GUEST_X86_GDT_NENT)
19683bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj         goto bad;
19693bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
19703bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      the_descrs = (VexGuestX86SegDescr*)gdt;
19713bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      base  = get_segdescr_base (&the_descrs[seg_selector]);
19723bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      limit = get_segdescr_limit(&the_descrs[seg_selector]);
19733bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
19743bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   } else {
19753bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
19763bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      /* All the same stuff, except for the LDT. */
19773bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      if (ldt == 0)
19783bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj         goto bad;
19793bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
19803bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      if (seg_selector >= VEX_GUEST_X86_LDT_NENT)
19813bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj         goto bad;
19823bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
19833bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      the_descrs = (VexGuestX86SegDescr*)ldt;
19843bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      base  = get_segdescr_base (&the_descrs[seg_selector]);
19853bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      limit = get_segdescr_limit(&the_descrs[seg_selector]);
19863bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
19873bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   }
19883bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
19893bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   /* Do the limit check.  Note, this check is just slightly too
19903bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      slack.  Really it should be "if (virtual_addr + size - 1 >=
19913bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      limit)," but we don't have the size info to hand.  Getting it
19923bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      could be significantly complex.  */
19933bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   if (virtual_addr >= limit)
19943bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      goto bad;
19953bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
19963bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   if (verboze)
19973bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      vex_printf("x86h_use_seg_selector: "
19983bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj                 "base = 0x%x, addr = 0x%x\n",
19993bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj                 base, base + virtual_addr);
20003bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
20013bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   /* High 32 bits are zero, indicating success. */
20023bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   return (ULong)( ((UInt)virtual_addr) + base );
20033bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
20043bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj bad:
20053bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   return 1ULL << 32;
20063bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj}
20073bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
20083bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
2009893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/*---------------------------------------------------------------*/
2010893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/*--- Helpers for dealing with, and describing,               ---*/
2011893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/*--- guest state as a whole.                                 ---*/
2012893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/*---------------------------------------------------------------*/
2013893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
2014893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/* Initialise the entire x86 guest state. */
2015893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/* VISIBLE TO LIBVEX CLIENT */
2016893a3302cc943e2ad1db421a8e6a753f82f532a7sewardjvoid LibVEX_GuestX86_initialise ( /*OUT*/VexGuestX86State* vex_state )
2017893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj{
2018893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_state->guest_EAX = 0;
2019893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_state->guest_ECX = 0;
2020893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_state->guest_EDX = 0;
2021893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_state->guest_EBX = 0;
2022893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_state->guest_ESP = 0;
2023893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_state->guest_EBP = 0;
2024893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_state->guest_ESI = 0;
2025893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_state->guest_EDI = 0;
2026893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
2027893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_state->guest_CC_OP   = X86G_CC_OP_COPY;
2028893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_state->guest_CC_DEP1 = 0;
2029893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_state->guest_CC_DEP2 = 0;
2030893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_state->guest_CC_NDEP = 0;
2031893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_state->guest_DFLAG   = 1; /* forwards */
2032893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_state->guest_IDFLAG  = 0;
20336d26984a0df6a7d20b658bac6edf869eb872cca3sewardj   vex_state->guest_ACFLAG  = 0;
2034893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
2035893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_state->guest_EIP = 0;
2036893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
2037893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   /* Initialise the simulated FPU */
2038893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   x86g_dirtyhelper_FINIT( vex_state );
2039893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
2040893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   /* Initialse the SSE state. */
2041893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj#  define SSEZERO(_xmm) _xmm[0]=_xmm[1]=_xmm[2]=_xmm[3] = 0;
2042893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
2043893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_state->guest_SSEROUND = (UInt)Irrm_NEAREST;
2044893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   SSEZERO(vex_state->guest_XMM0);
2045893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   SSEZERO(vex_state->guest_XMM1);
2046893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   SSEZERO(vex_state->guest_XMM2);
2047893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   SSEZERO(vex_state->guest_XMM3);
2048893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   SSEZERO(vex_state->guest_XMM4);
2049893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   SSEZERO(vex_state->guest_XMM5);
2050893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   SSEZERO(vex_state->guest_XMM6);
2051893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   SSEZERO(vex_state->guest_XMM7);
2052893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
2053893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj#  undef SSEZERO
2054893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
2055893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_state->guest_CS  = 0;
2056893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_state->guest_DS  = 0;
2057893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_state->guest_ES  = 0;
2058893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_state->guest_FS  = 0;
2059893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_state->guest_GS  = 0;
2060893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_state->guest_SS  = 0;
2061893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_state->guest_LDT = 0;
2062893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_state->guest_GDT = 0;
2063893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
2064893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_state->guest_EMWARN = EmWarn_NONE;
20651f126c5c092801acfc1ac968d2f1a37dde334bccsewardj
20661f126c5c092801acfc1ac968d2f1a37dde334bccsewardj   /* These should not ever be either read or written, but we
20671f126c5c092801acfc1ac968d2f1a37dde334bccsewardj      initialise them anyway. */
20681f126c5c092801acfc1ac968d2f1a37dde334bccsewardj   vex_state->guest_TISTART = 0;
20691f126c5c092801acfc1ac968d2f1a37dde334bccsewardj   vex_state->guest_TILEN   = 0;
2070893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj}
2071893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
20728d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj
20738d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj/* Figure out if any part of the guest state contained in minoff
20748d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   .. maxoff requires precise memory exceptions.  If in doubt return
20758d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   True (but this is generates significantly slower code).
20768d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj
20774cca75cb48776ceda40e8e305232d85f62021804sewardj   By default we enforce precise exns for guest %ESP, %EBP and %EIP
20784cca75cb48776ceda40e8e305232d85f62021804sewardj   only.  These are the minimum needed to extract correct stack
20794cca75cb48776ceda40e8e305232d85f62021804sewardj   backtraces from x86 code.
20808d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj*/
20818d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardjBool guest_x86_state_requires_precise_mem_exns ( Int minoff,
20828d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj                                                 Int maxoff)
20838d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj{
20844cca75cb48776ceda40e8e305232d85f62021804sewardj   Int ebp_min = offsetof(VexGuestX86State, guest_EBP);
20854cca75cb48776ceda40e8e305232d85f62021804sewardj   Int ebp_max = ebp_min + 4 - 1;
20868d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   Int esp_min = offsetof(VexGuestX86State, guest_ESP);
20878d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   Int esp_max = esp_min + 4 - 1;
20888d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   Int eip_min = offsetof(VexGuestX86State, guest_EIP);
20898d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   Int eip_max = eip_min + 4 - 1;
20908d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj
20914cca75cb48776ceda40e8e305232d85f62021804sewardj   if (maxoff < ebp_min || minoff > ebp_max) {
20924cca75cb48776ceda40e8e305232d85f62021804sewardj      /* no overlap with ebp */
20934cca75cb48776ceda40e8e305232d85f62021804sewardj   } else {
20944cca75cb48776ceda40e8e305232d85f62021804sewardj      return True;
20954cca75cb48776ceda40e8e305232d85f62021804sewardj   }
20964cca75cb48776ceda40e8e305232d85f62021804sewardj
20978d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   if (maxoff < esp_min || minoff > esp_max) {
2098eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj      /* no overlap with esp */
20998d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   } else {
2100eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj      return True;
21018d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   }
21028d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj
21038d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   if (maxoff < eip_min || minoff > eip_max) {
2104eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj      /* no overlap with eip */
21058d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   } else {
2106eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj      return True;
21078d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   }
21088d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj
21098d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   return False;
21108d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj}
21118d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj
21128d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj
2113eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj#define ALWAYSDEFD(field)                           \
2114eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj    { offsetof(VexGuestX86State, field),            \
2115eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj      (sizeof ((VexGuestX86State*)0)->field) }
2116eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj
2117eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardjVexGuestLayout
211849651f4b59b1ab7e0e70cccd34001630eafbe957sewardj   x86guest_layout
2119eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj      = {
2120eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj          /* Total size of the guest state, in bytes. */
2121eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj          .total_sizeB = sizeof(VexGuestX86State),
2122eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj
2123eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj          /* Describe the stack pointer. */
2124eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj          .offset_SP = offsetof(VexGuestX86State,guest_ESP),
2125eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj          .sizeof_SP = 4,
2126eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj
2127cf7879021370aabcccb1a9347244fcc7d5680141sewardj          /* Describe the instruction pointer. */
2128cf7879021370aabcccb1a9347244fcc7d5680141sewardj          .offset_IP = offsetof(VexGuestX86State,guest_EIP),
2129cf7879021370aabcccb1a9347244fcc7d5680141sewardj          .sizeof_IP = 4,
2130eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj
2131eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj          /* Describe any sections to be regarded by Memcheck as
2132eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj             'always-defined'. */
21336d26984a0df6a7d20b658bac6edf869eb872cca3sewardj          .n_alwaysDefd = 22,
21343bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
21352a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj          /* flags thunk: OP and NDEP are always defd, whereas DEP1
21362a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj             and DEP2 have to be tracked.  See detailed comment in
21372a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj             gdefs.h on meaning of thunk fields. */
21388fc937421c954ff9f707254f028b1fa0410c473dsewardj          .alwaysDefd
21398fc937421c954ff9f707254f028b1fa0410c473dsewardj             = { /*  0 */ ALWAYSDEFD(guest_CC_OP),
21408fc937421c954ff9f707254f028b1fa0410c473dsewardj                 /*  1 */ ALWAYSDEFD(guest_CC_NDEP),
21418fc937421c954ff9f707254f028b1fa0410c473dsewardj                 /*  2 */ ALWAYSDEFD(guest_DFLAG),
21428fc937421c954ff9f707254f028b1fa0410c473dsewardj                 /*  3 */ ALWAYSDEFD(guest_IDFLAG),
21436d26984a0df6a7d20b658bac6edf869eb872cca3sewardj                 /*  4 */ ALWAYSDEFD(guest_ACFLAG),
21446d26984a0df6a7d20b658bac6edf869eb872cca3sewardj                 /*  5 */ ALWAYSDEFD(guest_EIP),
21456d26984a0df6a7d20b658bac6edf869eb872cca3sewardj                 /*  6 */ ALWAYSDEFD(guest_FTOP),
21466d26984a0df6a7d20b658bac6edf869eb872cca3sewardj                 /*  7 */ ALWAYSDEFD(guest_FPTAG),
21476d26984a0df6a7d20b658bac6edf869eb872cca3sewardj                 /*  8 */ ALWAYSDEFD(guest_FPROUND),
21486d26984a0df6a7d20b658bac6edf869eb872cca3sewardj                 /*  9 */ ALWAYSDEFD(guest_FC3210),
21496d26984a0df6a7d20b658bac6edf869eb872cca3sewardj                 /* 10 */ ALWAYSDEFD(guest_CS),
21506d26984a0df6a7d20b658bac6edf869eb872cca3sewardj                 /* 11 */ ALWAYSDEFD(guest_DS),
21516d26984a0df6a7d20b658bac6edf869eb872cca3sewardj                 /* 12 */ ALWAYSDEFD(guest_ES),
21526d26984a0df6a7d20b658bac6edf869eb872cca3sewardj                 /* 13 */ ALWAYSDEFD(guest_FS),
21536d26984a0df6a7d20b658bac6edf869eb872cca3sewardj                 /* 14 */ ALWAYSDEFD(guest_GS),
21546d26984a0df6a7d20b658bac6edf869eb872cca3sewardj                 /* 15 */ ALWAYSDEFD(guest_SS),
21556d26984a0df6a7d20b658bac6edf869eb872cca3sewardj                 /* 16 */ ALWAYSDEFD(guest_LDT),
21566d26984a0df6a7d20b658bac6edf869eb872cca3sewardj                 /* 17 */ ALWAYSDEFD(guest_GDT),
21576d26984a0df6a7d20b658bac6edf869eb872cca3sewardj                 /* 18 */ ALWAYSDEFD(guest_EMWARN),
21586d26984a0df6a7d20b658bac6edf869eb872cca3sewardj                 /* 19 */ ALWAYSDEFD(guest_SSEROUND),
21596d26984a0df6a7d20b658bac6edf869eb872cca3sewardj                 /* 20 */ ALWAYSDEFD(guest_TISTART),
21606d26984a0df6a7d20b658bac6edf869eb872cca3sewardj                 /* 21 */ ALWAYSDEFD(guest_TILEN)
21618fc937421c954ff9f707254f028b1fa0410c473dsewardj               }
2162eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj        };
216349651f4b59b1ab7e0e70cccd34001630eafbe957sewardj
216449651f4b59b1ab7e0e70cccd34001630eafbe957sewardj
216536ca51378f8851635df814230fa23f2c409b9eddsewardj/*---------------------------------------------------------------*/
2166c0ee2edb4563c90bc8f1a83a09984a1fda86d1d3sewardj/*--- end                                guest-x86/ghelpers.c ---*/
216736ca51378f8851635df814230fa23f2c409b9eddsewardj/*---------------------------------------------------------------*/
2168