guest_x86_helpers.c revision e9ba4328f2afb94bc8474e9a7205e50ed9ac73fc
136ca51378f8851635df814230fa23f2c409b9eddsewardj
236ca51378f8851635df814230fa23f2c409b9eddsewardj/*---------------------------------------------------------------*/
336ca51378f8851635df814230fa23f2c409b9eddsewardj/*---                                                         ---*/
4c0ee2edb4563c90bc8f1a83a09984a1fda86d1d3sewardj/*--- This file (guest-x86/ghelpers.c) is                     ---*/
536ca51378f8851635df814230fa23f2c409b9eddsewardj/*--- Copyright (c) 2004 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
13f8ed9d874a7b8651654591c68c6d431c758d787csewardj   Copyright (C) 2004 OpenWorks, LLP.
14f8ed9d874a7b8651654591c68c6d431c758d787csewardj
15f8ed9d874a7b8651654591c68c6d431c758d787csewardj   This program is free software; you can redistribute it and/or modify
16f8ed9d874a7b8651654591c68c6d431c758d787csewardj   it under the terms of the GNU General Public License as published by
17f8ed9d874a7b8651654591c68c6d431c758d787csewardj   the Free Software Foundation; Version 2 dated June 1991 of the
18f8ed9d874a7b8651654591c68c6d431c758d787csewardj   license.
19f8ed9d874a7b8651654591c68c6d431c758d787csewardj
20f8ed9d874a7b8651654591c68c6d431c758d787csewardj   This program is distributed in the hope that it will be useful,
21f8ed9d874a7b8651654591c68c6d431c758d787csewardj   but WITHOUT ANY WARRANTY; without even the implied warranty of
22f8ed9d874a7b8651654591c68c6d431c758d787csewardj   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or liability
23f8ed9d874a7b8651654591c68c6d431c758d787csewardj   for damages.  See the GNU General Public License for more details.
24f8ed9d874a7b8651654591c68c6d431c758d787csewardj
25f8ed9d874a7b8651654591c68c6d431c758d787csewardj   Neither the names of the U.S. Department of Energy nor the
26f8ed9d874a7b8651654591c68c6d431c758d787csewardj   University of California nor the names of its contributors may be
27f8ed9d874a7b8651654591c68c6d431c758d787csewardj   used to endorse or promote products derived from this software
28f8ed9d874a7b8651654591c68c6d431c758d787csewardj   without prior written permission.
29f8ed9d874a7b8651654591c68c6d431c758d787csewardj
30f8ed9d874a7b8651654591c68c6d431c758d787csewardj   You should have received a copy of the GNU General Public License
31f8ed9d874a7b8651654591c68c6d431c758d787csewardj   along with this program; if not, write to the Free Software
32f8ed9d874a7b8651654591c68c6d431c758d787csewardj   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
33f8ed9d874a7b8651654591c68c6d431c758d787csewardj   USA.
34f8ed9d874a7b8651654591c68c6d431c758d787csewardj*/
35f8ed9d874a7b8651654591c68c6d431c758d787csewardj
3636ca51378f8851635df814230fa23f2c409b9eddsewardj#include "libvex_basictypes.h"
37893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj#include "libvex_emwarn.h"
380c2cb623cca372a2b42b073121c7413cdaaf75besewardj#include "libvex_guest_x86.h"
3936ca51378f8851635df814230fa23f2c409b9eddsewardj#include "libvex_ir.h"
4049651f4b59b1ab7e0e70cccd34001630eafbe957sewardj#include "libvex.h"
41c0ee2edb4563c90bc8f1a83a09984a1fda86d1d3sewardj
42c0ee2edb4563c90bc8f1a83a09984a1fda86d1d3sewardj#include "main/vex_util.h"
43c0ee2edb4563c90bc8f1a83a09984a1fda86d1d3sewardj#include "guest-x86/gdefs.h"
4436ca51378f8851635df814230fa23f2c409b9eddsewardj
45c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
4636ca51378f8851635df814230fa23f2c409b9eddsewardj/* This file contains helper functions for x86 guest code.
4736ca51378f8851635df814230fa23f2c409b9eddsewardj   Calls to these functions are generated by the back end.
4836ca51378f8851635df814230fa23f2c409b9eddsewardj   These calls are of course in the host machine code and
4936ca51378f8851635df814230fa23f2c409b9eddsewardj   this file will be compiled to host machine code, so that
5036ca51378f8851635df814230fa23f2c409b9eddsewardj   all makes sense.
5136ca51378f8851635df814230fa23f2c409b9eddsewardj
5236ca51378f8851635df814230fa23f2c409b9eddsewardj   Only change the signatures of these helper functions very
5336ca51378f8851635df814230fa23f2c409b9eddsewardj   carefully.  If you change the signature here, you'll have to change
5436ca51378f8851635df814230fa23f2c409b9eddsewardj   the parameters passed to it in the IR calls constructed by
552a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   guest-x86/toIR.c.
5689050e58e7bee40892662fe94231aefc33768cf5sewardj
5789050e58e7bee40892662fe94231aefc33768cf5sewardj   Some of this code/logic is derived from QEMU, which is copyright
5889050e58e7bee40892662fe94231aefc33768cf5sewardj   Fabrice Bellard, licensed under the LGPL.  It is used with
5989050e58e7bee40892662fe94231aefc33768cf5sewardj   permission.
6036ca51378f8851635df814230fa23f2c409b9eddsewardj*/
6136ca51378f8851635df814230fa23f2c409b9eddsewardj
6284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj/* Set to 1 to get detailed profiling info about use of the flag
6384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   machinery. */
6484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#define PROFILE_EFLAGS 0
6584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
6684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
67d44bc6e6692dfb0881dcc249bd4ba3d8f8e97fcasewardjstatic const UChar parity_table[256] = {
682a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
692a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
702a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
712a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
722a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
732a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
742a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
752a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
762a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
772a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
782a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
792a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
802a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
812a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
822a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
832a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
842a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
852a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
862a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
872a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
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    X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
932a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
942a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
952a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
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,
10014731f22bf7759d6d23383ca870ac89d9581f1e9sewardj};
10114731f22bf7759d6d23383ca870ac89d9581f1e9sewardj
10214731f22bf7759d6d23383ca870ac89d9581f1e9sewardj/* n must be a constant to be efficient */
103df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardjinline static Int lshift ( Int x, Int n )
10414731f22bf7759d6d23383ca870ac89d9581f1e9sewardj{
105df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   if (n >= 0)
106df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj      return x << n;
107df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   else
108df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj      return x >> (-n);
10914731f22bf7759d6d23383ca870ac89d9581f1e9sewardj}
11014731f22bf7759d6d23383ca870ac89d9581f1e9sewardj
11114731f22bf7759d6d23383ca870ac89d9581f1e9sewardj
112b9c5cf639b3b21b972599d27207a033afc76ef67sewardj#define PREAMBLE(__data_bits)					\
113df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   /* const */ UInt DATA_MASK 					\
114b9c5cf639b3b21b972599d27207a033afc76ef67sewardj      = __data_bits==8 ? 0xFF 					\
115b9c5cf639b3b21b972599d27207a033afc76ef67sewardj                       : (__data_bits==16 ? 0xFFFF 		\
116b9c5cf639b3b21b972599d27207a033afc76ef67sewardj                                          : 0xFFFFFFFF); 	\
117df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   /* const */ UInt SIGN_MASK = 1 << (__data_bits - 1);		\
1182a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj   /* const */ UInt CC_DEP1 = cc_dep1_formal;			\
1192a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj   /* const */ UInt CC_DEP2 = cc_dep2_formal;			\
1202a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj   /* const */ UInt CC_NDEP = cc_ndep_formal;			\
1212a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj   /* Four bogus assignments, which hopefully gcc can     */	\
122df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   /* optimise away, and which stop it complaining about  */	\
123df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   /* unused variables.                                   */	\
124df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   SIGN_MASK = SIGN_MASK;					\
125df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   DATA_MASK = DATA_MASK;					\
1262a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj   CC_DEP2 = CC_DEP2;						\
1272a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj   CC_NDEP = CC_NDEP;
128df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj
12914731f22bf7759d6d23383ca870ac89d9581f1e9sewardj
130b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
131b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
132df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_ADD(DATA_BITS,DATA_UTYPE)			\
133b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
134b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
1358fc937421c954ff9f707254f028b1fa0410c473dsewardj   { Int cf, pf, af, zf, sf, of;				\
1368fc937421c954ff9f707254f028b1fa0410c473dsewardj     Int argL, argR, res;					\
1378fc937421c954ff9f707254f028b1fa0410c473dsewardj     argL = CC_DEP1;						\
1388fc937421c954ff9f707254f028b1fa0410c473dsewardj     argR = CC_DEP2;						\
1398fc937421c954ff9f707254f028b1fa0410c473dsewardj     res  = argL + argR;					\
1408fc937421c954ff9f707254f028b1fa0410c473dsewardj     cf = (DATA_UTYPE)res < (DATA_UTYPE)argL;			\
1418fc937421c954ff9f707254f028b1fa0410c473dsewardj     pf = parity_table[(UChar)res];				\
1428fc937421c954ff9f707254f028b1fa0410c473dsewardj     af = (res ^ argL ^ argR) & 0x10;				\
1438fc937421c954ff9f707254f028b1fa0410c473dsewardj     zf = ((DATA_UTYPE)res == 0) << 6;				\
1448fc937421c954ff9f707254f028b1fa0410c473dsewardj     sf = lshift(res, 8 - DATA_BITS) & 0x80;			\
1458fc937421c954ff9f707254f028b1fa0410c473dsewardj     of = lshift((argL ^ argR ^ -1) & (argL ^ res), 		\
1462a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                 12 - DATA_BITS) & X86G_CC_MASK_O;		\
1478fc937421c954ff9f707254f028b1fa0410c473dsewardj     return cf | pf | af | zf | sf | of;			\
1488fc937421c954ff9f707254f028b1fa0410c473dsewardj   }								\
1492ef5f2a829433c4ca17f33e1bf993cf16b9e347dsewardj}
1502ef5f2a829433c4ca17f33e1bf993cf16b9e347dsewardj
151b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
152b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
1532a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj#define ACTIONS_SUB(DATA_BITS,DATA_UTYPE)			\
154b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
155b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
1568fc937421c954ff9f707254f028b1fa0410c473dsewardj   { Int cf, pf, af, zf, sf, of;				\
1578fc937421c954ff9f707254f028b1fa0410c473dsewardj     Int argL, argR, res;					\
1588fc937421c954ff9f707254f028b1fa0410c473dsewardj     argL = CC_DEP1;						\
1598fc937421c954ff9f707254f028b1fa0410c473dsewardj     argR = CC_DEP2;						\
1608fc937421c954ff9f707254f028b1fa0410c473dsewardj     res  = argL - argR;					\
1618fc937421c954ff9f707254f028b1fa0410c473dsewardj     cf = (DATA_UTYPE)argL < (DATA_UTYPE)argR;			\
1628fc937421c954ff9f707254f028b1fa0410c473dsewardj     pf = parity_table[(UChar)res];				\
1638fc937421c954ff9f707254f028b1fa0410c473dsewardj     af = (res ^ argL ^ argR) & 0x10;				\
1648fc937421c954ff9f707254f028b1fa0410c473dsewardj     zf = ((DATA_UTYPE)res == 0) << 6;				\
1658fc937421c954ff9f707254f028b1fa0410c473dsewardj     sf = lshift(res, 8 - DATA_BITS) & 0x80;			\
1668fc937421c954ff9f707254f028b1fa0410c473dsewardj     of = lshift((argL ^ argR) & (argL ^ res),	 		\
1672a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                 12 - DATA_BITS) & X86G_CC_MASK_O; 		\
1688fc937421c954ff9f707254f028b1fa0410c473dsewardj     return cf | pf | af | zf | sf | of;			\
1698fc937421c954ff9f707254f028b1fa0410c473dsewardj   }								\
1702ef5f2a829433c4ca17f33e1bf993cf16b9e347dsewardj}
1712ef5f2a829433c4ca17f33e1bf993cf16b9e347dsewardj
172b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
173b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
1742a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj#define ACTIONS_ADC(DATA_BITS,DATA_UTYPE)			\
175b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
176b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
1778fc937421c954ff9f707254f028b1fa0410c473dsewardj   { Int cf, pf, af, zf, sf, of;				\
1788fc937421c954ff9f707254f028b1fa0410c473dsewardj     Int argL, argR, oldC, res;		       			\
1792a9ad023890d3b34cf45e429df2a8ae88b419128sewardj     oldC = CC_NDEP & X86G_CC_MASK_C;				\
1808fc937421c954ff9f707254f028b1fa0410c473dsewardj     argL = CC_DEP1;						\
1818fc937421c954ff9f707254f028b1fa0410c473dsewardj     argR = CC_DEP2 ^ oldC;	       				\
1828fc937421c954ff9f707254f028b1fa0410c473dsewardj     res  = (argL + argR) + oldC;				\
1838fc937421c954ff9f707254f028b1fa0410c473dsewardj     if (oldC)							\
1848fc937421c954ff9f707254f028b1fa0410c473dsewardj        cf = (DATA_UTYPE)res <= (DATA_UTYPE)argL;		\
1858fc937421c954ff9f707254f028b1fa0410c473dsewardj     else							\
1868fc937421c954ff9f707254f028b1fa0410c473dsewardj        cf = (DATA_UTYPE)res < (DATA_UTYPE)argL;		\
1878fc937421c954ff9f707254f028b1fa0410c473dsewardj     pf = parity_table[(UChar)res];				\
1888fc937421c954ff9f707254f028b1fa0410c473dsewardj     af = (res ^ argL ^ argR) & 0x10;				\
1898fc937421c954ff9f707254f028b1fa0410c473dsewardj     zf = ((DATA_UTYPE)res == 0) << 6;				\
1908fc937421c954ff9f707254f028b1fa0410c473dsewardj     sf = lshift(res, 8 - DATA_BITS) & 0x80;			\
1918fc937421c954ff9f707254f028b1fa0410c473dsewardj     of = lshift((argL ^ argR ^ -1) & (argL ^ res), 		\
1922a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                  12 - DATA_BITS) & X86G_CC_MASK_O;		\
1938fc937421c954ff9f707254f028b1fa0410c473dsewardj     return cf | pf | af | zf | sf | of;			\
1948fc937421c954ff9f707254f028b1fa0410c473dsewardj   }								\
1952ef5f2a829433c4ca17f33e1bf993cf16b9e347dsewardj}
1962ef5f2a829433c4ca17f33e1bf993cf16b9e347dsewardj
197b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
198b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
199df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_SBB(DATA_BITS,DATA_UTYPE)			\
200b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
201b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
2028fc937421c954ff9f707254f028b1fa0410c473dsewardj   { Int cf, pf, af, zf, sf, of;				\
2038fc937421c954ff9f707254f028b1fa0410c473dsewardj     Int argL, argR, oldC, res;		       			\
2042a9ad023890d3b34cf45e429df2a8ae88b419128sewardj     oldC = CC_NDEP & X86G_CC_MASK_C;				\
2058fc937421c954ff9f707254f028b1fa0410c473dsewardj     argL = CC_DEP1;						\
2068fc937421c954ff9f707254f028b1fa0410c473dsewardj     argR = CC_DEP2 ^ oldC;	       				\
2078fc937421c954ff9f707254f028b1fa0410c473dsewardj     res  = (argL - argR) - oldC;				\
2088fc937421c954ff9f707254f028b1fa0410c473dsewardj     if (oldC)							\
2098fc937421c954ff9f707254f028b1fa0410c473dsewardj        cf = (DATA_UTYPE)argL <= (DATA_UTYPE)argR;		\
2108fc937421c954ff9f707254f028b1fa0410c473dsewardj     else							\
2118fc937421c954ff9f707254f028b1fa0410c473dsewardj        cf = (DATA_UTYPE)argL < (DATA_UTYPE)argR;		\
2128fc937421c954ff9f707254f028b1fa0410c473dsewardj     pf = parity_table[(UChar)res];				\
2138fc937421c954ff9f707254f028b1fa0410c473dsewardj     af = (res ^ argL ^ argR) & 0x10;				\
2148fc937421c954ff9f707254f028b1fa0410c473dsewardj     zf = ((DATA_UTYPE)res == 0) << 6;				\
2158fc937421c954ff9f707254f028b1fa0410c473dsewardj     sf = lshift(res, 8 - DATA_BITS) & 0x80;			\
2168fc937421c954ff9f707254f028b1fa0410c473dsewardj     of = lshift((argL ^ argR) & (argL ^ res), 			\
2172a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                 12 - DATA_BITS) & X86G_CC_MASK_O;		\
2188fc937421c954ff9f707254f028b1fa0410c473dsewardj     return cf | pf | af | zf | sf | of;			\
2198fc937421c954ff9f707254f028b1fa0410c473dsewardj   }								\
220a238471814bd386aeb58a76718b41e68b1a794b2sewardj}
221a238471814bd386aeb58a76718b41e68b1a794b2sewardj
222b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
223b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
224df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_LOGIC(DATA_BITS,DATA_UTYPE)			\
225b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
226b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
2278fc937421c954ff9f707254f028b1fa0410c473dsewardj   { Int cf, pf, af, zf, sf, of;				\
2288fc937421c954ff9f707254f028b1fa0410c473dsewardj     cf = 0;							\
2298fc937421c954ff9f707254f028b1fa0410c473dsewardj     pf = parity_table[(UChar)CC_DEP1];				\
2308fc937421c954ff9f707254f028b1fa0410c473dsewardj     af = 0;							\
2318fc937421c954ff9f707254f028b1fa0410c473dsewardj     zf = ((DATA_UTYPE)CC_DEP1 == 0) << 6;			\
2328fc937421c954ff9f707254f028b1fa0410c473dsewardj     sf = lshift(CC_DEP1, 8 - DATA_BITS) & 0x80;		\
2338fc937421c954ff9f707254f028b1fa0410c473dsewardj     of = 0;							\
2348fc937421c954ff9f707254f028b1fa0410c473dsewardj     return cf | pf | af | zf | sf | of;			\
2358fc937421c954ff9f707254f028b1fa0410c473dsewardj   }								\
236a238471814bd386aeb58a76718b41e68b1a794b2sewardj}
237a238471814bd386aeb58a76718b41e68b1a794b2sewardj
238b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
239b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
240df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_INC(DATA_BITS,DATA_UTYPE)			\
241b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
242b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
2438fc937421c954ff9f707254f028b1fa0410c473dsewardj   { Int cf, pf, af, zf, sf, of;				\
2448fc937421c954ff9f707254f028b1fa0410c473dsewardj     Int argL, argR, res;					\
2458fc937421c954ff9f707254f028b1fa0410c473dsewardj     res  = CC_DEP1;						\
2468fc937421c954ff9f707254f028b1fa0410c473dsewardj     argL = res - 1;						\
2478fc937421c954ff9f707254f028b1fa0410c473dsewardj     argR = 1;							\
2482a9ad023890d3b34cf45e429df2a8ae88b419128sewardj     cf = CC_NDEP & X86G_CC_MASK_C;				\
2498fc937421c954ff9f707254f028b1fa0410c473dsewardj     pf = parity_table[(UChar)res];				\
2508fc937421c954ff9f707254f028b1fa0410c473dsewardj     af = (res ^ argL ^ argR) & 0x10;				\
2518fc937421c954ff9f707254f028b1fa0410c473dsewardj     zf = ((DATA_UTYPE)res == 0) << 6;				\
2528fc937421c954ff9f707254f028b1fa0410c473dsewardj     sf = lshift(res, 8 - DATA_BITS) & 0x80;			\
2538fc937421c954ff9f707254f028b1fa0410c473dsewardj     of = ((res & DATA_MASK) == SIGN_MASK) << 11;		\
2548fc937421c954ff9f707254f028b1fa0410c473dsewardj     return cf | pf | af | zf | sf | of;			\
2558fc937421c954ff9f707254f028b1fa0410c473dsewardj   }								\
25689050e58e7bee40892662fe94231aefc33768cf5sewardj}
25789050e58e7bee40892662fe94231aefc33768cf5sewardj
258b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
259b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
260df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_DEC(DATA_BITS,DATA_UTYPE)			\
261b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
262b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
2638fc937421c954ff9f707254f028b1fa0410c473dsewardj   { Int cf, pf, af, zf, sf, of;				\
2648fc937421c954ff9f707254f028b1fa0410c473dsewardj     Int argL, argR, res;					\
2658fc937421c954ff9f707254f028b1fa0410c473dsewardj     res  = CC_DEP1;						\
2668fc937421c954ff9f707254f028b1fa0410c473dsewardj     argL = res + 1;						\
2678fc937421c954ff9f707254f028b1fa0410c473dsewardj     argR = 1;							\
2682a9ad023890d3b34cf45e429df2a8ae88b419128sewardj     cf = CC_NDEP & X86G_CC_MASK_C;				\
2698fc937421c954ff9f707254f028b1fa0410c473dsewardj     pf = parity_table[(UChar)res];				\
2708fc937421c954ff9f707254f028b1fa0410c473dsewardj     af = (res ^ argL ^ argR) & 0x10;				\
2718fc937421c954ff9f707254f028b1fa0410c473dsewardj     zf = ((DATA_UTYPE)res == 0) << 6;				\
2728fc937421c954ff9f707254f028b1fa0410c473dsewardj     sf = lshift(res, 8 - DATA_BITS) & 0x80;			\
2738fc937421c954ff9f707254f028b1fa0410c473dsewardj     of = ((res & DATA_MASK) 					\
2748fc937421c954ff9f707254f028b1fa0410c473dsewardj          == ((UInt)SIGN_MASK - 1)) << 11;			\
2758fc937421c954ff9f707254f028b1fa0410c473dsewardj     return cf | pf | af | zf | sf | of;			\
2768fc937421c954ff9f707254f028b1fa0410c473dsewardj   }								\
27789050e58e7bee40892662fe94231aefc33768cf5sewardj}
27889050e58e7bee40892662fe94231aefc33768cf5sewardj
279b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
280b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
281df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_SHL(DATA_BITS,DATA_UTYPE)			\
282b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
283b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
2848fc937421c954ff9f707254f028b1fa0410c473dsewardj   { Int cf, pf, af, zf, sf, of;				\
2852a9ad023890d3b34cf45e429df2a8ae88b419128sewardj     cf = (CC_DEP2 >> (DATA_BITS - 1)) & X86G_CC_MASK_C;	\
2868fc937421c954ff9f707254f028b1fa0410c473dsewardj     pf = parity_table[(UChar)CC_DEP1];				\
2878fc937421c954ff9f707254f028b1fa0410c473dsewardj     af = 0; /* undefined */					\
2888fc937421c954ff9f707254f028b1fa0410c473dsewardj     zf = ((DATA_UTYPE)CC_DEP1 == 0) << 6;			\
2898fc937421c954ff9f707254f028b1fa0410c473dsewardj     sf = lshift(CC_DEP1, 8 - DATA_BITS) & 0x80;		\
2908fc937421c954ff9f707254f028b1fa0410c473dsewardj     /* of is defined if shift count == 1 */			\
2912a9ad023890d3b34cf45e429df2a8ae88b419128sewardj     of = lshift(CC_DEP2 ^ CC_DEP1, 12 - DATA_BITS) 		\
2922a9ad023890d3b34cf45e429df2a8ae88b419128sewardj          & X86G_CC_MASK_O;					\
2938fc937421c954ff9f707254f028b1fa0410c473dsewardj     return cf | pf | af | zf | sf | of;			\
2948fc937421c954ff9f707254f028b1fa0410c473dsewardj   }								\
2955f6303579435ddb8315e11c2f02c904b978782a0sewardj}
2965f6303579435ddb8315e11c2f02c904b978782a0sewardj
297b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
298b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
2992a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj#define ACTIONS_SHR(DATA_BITS,DATA_UTYPE)			\
300b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
301b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);  					\
3028fc937421c954ff9f707254f028b1fa0410c473dsewardj   { Int cf, pf, af, zf, sf, of;				\
3038fc937421c954ff9f707254f028b1fa0410c473dsewardj     cf = CC_DEP2 & 1;						\
3048fc937421c954ff9f707254f028b1fa0410c473dsewardj     pf = parity_table[(UChar)CC_DEP1];				\
3058fc937421c954ff9f707254f028b1fa0410c473dsewardj     af = 0; /* undefined */					\
3068fc937421c954ff9f707254f028b1fa0410c473dsewardj     zf = ((DATA_UTYPE)CC_DEP1 == 0) << 6;			\
3078fc937421c954ff9f707254f028b1fa0410c473dsewardj     sf = lshift(CC_DEP1, 8 - DATA_BITS) & 0x80;		\
3088fc937421c954ff9f707254f028b1fa0410c473dsewardj     /* of is defined if shift count == 1 */			\
3092a9ad023890d3b34cf45e429df2a8ae88b419128sewardj     of = lshift(CC_DEP2 ^ CC_DEP1, 12 - DATA_BITS)		\
3102a9ad023890d3b34cf45e429df2a8ae88b419128sewardj          & X86G_CC_MASK_O;					\
3118fc937421c954ff9f707254f028b1fa0410c473dsewardj     return cf | pf | af | zf | sf | of;			\
3128fc937421c954ff9f707254f028b1fa0410c473dsewardj   }								\
3135f6303579435ddb8315e11c2f02c904b978782a0sewardj}
3145f6303579435ddb8315e11c2f02c904b978782a0sewardj
315b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
316b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
3178ee2de1f5f72c13120f59c0ca6ac8291219123dfsewardj/* ROL: cf' = lsb(result).  of' = msb(result) ^ lsb(result). */
3182a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj/* DEP1 = result, NDEP = old flags */
319df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_ROL(DATA_BITS,DATA_UTYPE)			\
320b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
321b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
3228fc937421c954ff9f707254f028b1fa0410c473dsewardj   { Int fl 							\
3232a9ad023890d3b34cf45e429df2a8ae88b419128sewardj        = (CC_NDEP & ~(X86G_CC_MASK_O | X86G_CC_MASK_C))	\
3242a9ad023890d3b34cf45e429df2a8ae88b419128sewardj          | (X86G_CC_MASK_C & CC_DEP1)				\
3252a9ad023890d3b34cf45e429df2a8ae88b419128sewardj          | (X86G_CC_MASK_O & (lshift(CC_DEP1,  		\
3262a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                                      11-(DATA_BITS-1)) 	\
3278fc937421c954ff9f707254f028b1fa0410c473dsewardj                     ^ lshift(CC_DEP1, 11)));			\
3288fc937421c954ff9f707254f028b1fa0410c473dsewardj     return fl;							\
3298fc937421c954ff9f707254f028b1fa0410c473dsewardj   }								\
3308c7f1abe9e022f6382634efea09c9cac89ec6336sewardj}
3318c7f1abe9e022f6382634efea09c9cac89ec6336sewardj
332b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
333b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
3341813dbeb912870e9a544cae17a3fadbf8d2b0d55sewardj/* ROR: cf' = msb(result).  of' = msb(result) ^ msb-1(result). */
3352a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj/* DEP1 = result, NDEP = old flags */
336df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_ROR(DATA_BITS,DATA_UTYPE)			\
337b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
338b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
3398fc937421c954ff9f707254f028b1fa0410c473dsewardj   { Int fl 							\
3402a9ad023890d3b34cf45e429df2a8ae88b419128sewardj        = (CC_NDEP & ~(X86G_CC_MASK_O | X86G_CC_MASK_C))	\
3412a9ad023890d3b34cf45e429df2a8ae88b419128sewardj          | (X86G_CC_MASK_C & (CC_DEP1 >> (DATA_BITS-1)))	\
3422a9ad023890d3b34cf45e429df2a8ae88b419128sewardj          | (X86G_CC_MASK_O & (lshift(CC_DEP1, 			\
3432a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                                      11-(DATA_BITS-1)) 	\
3448fc937421c954ff9f707254f028b1fa0410c473dsewardj                     ^ lshift(CC_DEP1, 11-(DATA_BITS-1)+1)));	\
3458fc937421c954ff9f707254f028b1fa0410c473dsewardj     return fl;							\
3468fc937421c954ff9f707254f028b1fa0410c473dsewardj   }								\
3471813dbeb912870e9a544cae17a3fadbf8d2b0d55sewardj}
3481813dbeb912870e9a544cae17a3fadbf8d2b0d55sewardj
349b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
350b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
3512a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj#define ACTIONS_UMUL(DATA_BITS,DATA_UTYPE,DATA_U2TYPE)          \
3522a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj{                                                               \
3532a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj   PREAMBLE(DATA_BITS);                                         \
3548fc937421c954ff9f707254f028b1fa0410c473dsewardj   { Int cf, pf, af, zf, sf, of;                                \
3558fc937421c954ff9f707254f028b1fa0410c473dsewardj     DATA_UTYPE  hi;                                            \
3568fc937421c954ff9f707254f028b1fa0410c473dsewardj     DATA_UTYPE  lo = ((DATA_UTYPE)CC_DEP1)                     \
3578fc937421c954ff9f707254f028b1fa0410c473dsewardj                      * ((DATA_UTYPE)CC_DEP2);                  \
3588fc937421c954ff9f707254f028b1fa0410c473dsewardj     DATA_U2TYPE rr = ((DATA_U2TYPE)((DATA_UTYPE)CC_DEP1))      \
3598fc937421c954ff9f707254f028b1fa0410c473dsewardj                      * ((DATA_U2TYPE)((DATA_UTYPE)CC_DEP2));   \
3608fc937421c954ff9f707254f028b1fa0410c473dsewardj     hi = (DATA_UTYPE)(rr >>/*u*/ DATA_BITS);                   \
3618fc937421c954ff9f707254f028b1fa0410c473dsewardj     cf = (hi != 0);                                            \
3628fc937421c954ff9f707254f028b1fa0410c473dsewardj     pf = parity_table[(UChar)lo];                              \
3638fc937421c954ff9f707254f028b1fa0410c473dsewardj     af = 0; /* undefined */                                    \
3648fc937421c954ff9f707254f028b1fa0410c473dsewardj     zf = (lo == 0) << 6;                                       \
3658fc937421c954ff9f707254f028b1fa0410c473dsewardj     sf = lshift(lo, 8 - DATA_BITS) & 0x80;                     \
3668fc937421c954ff9f707254f028b1fa0410c473dsewardj     of = cf << 11;                                             \
3678fc937421c954ff9f707254f028b1fa0410c473dsewardj     return cf | pf | af | zf | sf | of;                        \
3688fc937421c954ff9f707254f028b1fa0410c473dsewardj   }								\
36956296d80c9e15ec59eebecf1c3aea9ebd4dac115sewardj}
37056296d80c9e15ec59eebecf1c3aea9ebd4dac115sewardj
371b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
372b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
3732a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj#define ACTIONS_SMUL(DATA_BITS,DATA_STYPE,DATA_S2TYPE)          \
3742a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj{                                                               \
3752a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj   PREAMBLE(DATA_BITS);                                         \
3768fc937421c954ff9f707254f028b1fa0410c473dsewardj   { Int cf, pf, af, zf, sf, of;                                \
3778fc937421c954ff9f707254f028b1fa0410c473dsewardj     DATA_STYPE  hi;                                            \
3788fc937421c954ff9f707254f028b1fa0410c473dsewardj     DATA_STYPE  lo = ((DATA_STYPE)CC_DEP1)                     \
3798fc937421c954ff9f707254f028b1fa0410c473dsewardj                      * ((DATA_STYPE)CC_DEP2);                  \
3808fc937421c954ff9f707254f028b1fa0410c473dsewardj     DATA_S2TYPE rr = ((DATA_S2TYPE)((DATA_STYPE)CC_DEP1))      \
3818fc937421c954ff9f707254f028b1fa0410c473dsewardj                      * ((DATA_S2TYPE)((DATA_STYPE)CC_DEP2));   \
3828fc937421c954ff9f707254f028b1fa0410c473dsewardj     hi = (DATA_STYPE)(rr >>/*s*/ DATA_BITS);                   \
3838fc937421c954ff9f707254f028b1fa0410c473dsewardj     cf = (hi != (lo >>/*s*/ (DATA_BITS-1)));                   \
3848fc937421c954ff9f707254f028b1fa0410c473dsewardj     pf = parity_table[(UChar)lo];                              \
3858fc937421c954ff9f707254f028b1fa0410c473dsewardj     af = 0; /* undefined */                                    \
3868fc937421c954ff9f707254f028b1fa0410c473dsewardj     zf = (lo == 0) << 6;                                       \
3878fc937421c954ff9f707254f028b1fa0410c473dsewardj     sf = lshift(lo, 8 - DATA_BITS) & 0x80;                     \
3888fc937421c954ff9f707254f028b1fa0410c473dsewardj     of = cf << 11;                                             \
3898fc937421c954ff9f707254f028b1fa0410c473dsewardj     return cf | pf | af | zf | sf | of;                        \
3908fc937421c954ff9f707254f028b1fa0410c473dsewardj   }								\
3917ed2295459ac5e788a98dd5570fef0d4645c27d4sewardj}
392741153c4301023a420ab45b8a10b8e1bac968822sewardj
39336ca51378f8851635df814230fa23f2c409b9eddsewardj
39484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#if PROFILE_EFLAGS
39584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
3962a9ad023890d3b34cf45e429df2a8ae88b419128sewardjstatic UInt tabc[X86G_CC_OP_NUMBER];
3972a9ad023890d3b34cf45e429df2a8ae88b419128sewardjstatic UInt tab[X86G_CC_OP_NUMBER][16];
3989eab588e223e52b1e7b710ff1c0da7b032ab2837sewardjstatic Bool initted     = False;
39984ff0657940e62f38e618ea18bac6f27ce0e741fsewardjstatic UInt n_calc_cond = 0;
40084ff0657940e62f38e618ea18bac6f27ce0e741fsewardjstatic UInt n_calc_all  = 0;
40184ff0657940e62f38e618ea18bac6f27ce0e741fsewardjstatic UInt n_calc_c    = 0;
40284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
40384ff0657940e62f38e618ea18bac6f27ce0e741fsewardjstatic void showCounts ( void )
40484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj{
40584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   Int op, co;
40684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   Char ch;
4079eab588e223e52b1e7b710ff1c0da7b032ab2837sewardj   vex_printf("\nALL=%d  COND=%d   C=%d\n",
40884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj              n_calc_all-n_calc_cond-n_calc_c, n_calc_cond, n_calc_c);
40984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   vex_printf("      CARRY    O   NO    B   NB    Z   NZ   BE  NBE"
41084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj              "    S   NS    P   NP    L   NL   LE  NLE\n");
41184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   vex_printf("     ----------------------------------------------"
41284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj              "----------------------------------------\n");
4132a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   for (op = 0; op < X86G_CC_OP_NUMBER; op++) {
41484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
41584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      ch = ' ';
41693d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj      if (op > 0 && (op-1) % 3 == 0)
41793d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj         ch = 'B';
41893d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj      if (op > 0 && (op-1) % 3 == 1)
41993d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj         ch = 'W';
42084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      if (op > 0 && (op-1) % 3 == 2)
42184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         ch = 'L';
42284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
42384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      vex_printf("%2d%c: ", op, ch);
42484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      vex_printf("%6d ", tabc[op]);
42584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      for (co = 0; co < 16; co++) {
42684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         Int n = tab[op][co];
42784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         if (n >= 1000) {
42884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj            vex_printf(" %3dK", n / 1000);
42984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         } else
43084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         if (n >= 0) {
43184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj           vex_printf(" %3d ", n );
43284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         } else {
43384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj            vex_printf("     ");
43484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         }
43584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
43684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      vex_printf("\n");
43784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   }
43884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   vex_printf("\n");
43984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj}
44084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
44184ff0657940e62f38e618ea18bac6f27ce0e741fsewardjstatic void initCounts ( void )
44284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj{
44384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   Int op, co;
44484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   initted = True;
4452a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   for (op = 0; op < X86G_CC_OP_NUMBER; op++) {
44684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      tabc[op] = 0;
44784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      for (co = 0; co < 16; co++)
44884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         tab[op][co] = 0;
44984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   }
45084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj}
45184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
45284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#endif /* PROFILE_EFLAGS */
45384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
4549aebb0c3f7a7f43313786826f31402f2b733badfsewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
455b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/* Calculate all the 6 flags from the supplied thunk parameters. */
4562a9ad023890d3b34cf45e429df2a8ae88b419128sewardjUInt x86g_calculate_eflags_all ( UInt cc_op,
4572a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                                 UInt cc_dep1_formal,
4582a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                                 UInt cc_dep2_formal,
4592a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                                UInt cc_ndep_formal )
46036ca51378f8851635df814230fa23f2c409b9eddsewardj{
46184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  if PROFILE_EFLAGS
46284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   n_calc_all++;
46384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  endif
46436ca51378f8851635df814230fa23f2c409b9eddsewardj   switch (cc_op) {
4652a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_COPY:
4662a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj         return cc_dep1_formal
4672a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                & (X86G_CC_MASK_O | X86G_CC_MASK_S | X86G_CC_MASK_Z
4682a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                   | X86G_CC_MASK_A | X86G_CC_MASK_C | X86G_CC_MASK_P);
46914731f22bf7759d6d23383ca870ac89d9581f1e9sewardj
4702a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_ADDB:   ACTIONS_ADD( 8,  UChar  );
4712a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_ADDW:   ACTIONS_ADD( 16, UShort );
4722a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_ADDL:   ACTIONS_ADD( 32, UInt   );
473a238471814bd386aeb58a76718b41e68b1a794b2sewardj
4742a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_ADCB:   ACTIONS_ADC( 8,  UChar  );
4752a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_ADCW:   ACTIONS_ADC( 16, UShort );
4762a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_ADCL:   ACTIONS_ADC( 32, UInt   );
477a238471814bd386aeb58a76718b41e68b1a794b2sewardj
4782a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_SUBB:   ACTIONS_SUB(  8, UChar  );
4792a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_SUBW:   ACTIONS_SUB( 16, UShort );
4802a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_SUBL:   ACTIONS_SUB( 32, UInt   );
481afc5787e1c4b8e9678669577cf57ac509c6cd6b5sewardj
4822a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_SBBB:   ACTIONS_SBB(  8, UChar  );
4832a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_SBBW:   ACTIONS_SBB( 16, UShort );
4842a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_SBBL:   ACTIONS_SBB( 32, UInt   );
485741153c4301023a420ab45b8a10b8e1bac968822sewardj
4862a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_LOGICB: ACTIONS_LOGIC(  8, UChar  );
4872a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_LOGICW: ACTIONS_LOGIC( 16, UShort );
4882a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_LOGICL: ACTIONS_LOGIC( 32, UInt   );
4895f6303579435ddb8315e11c2f02c904b978782a0sewardj
4902a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_INCB:   ACTIONS_INC(  8, UChar  );
4912a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_INCW:   ACTIONS_INC( 16, UShort );
4922a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_INCL:   ACTIONS_INC( 32, UInt   );
4931813dbeb912870e9a544cae17a3fadbf8d2b0d55sewardj
4942a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_DECB:   ACTIONS_DEC(  8, UChar  );
4952a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_DECW:   ACTIONS_DEC( 16, UShort );
4962a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_DECL:   ACTIONS_DEC( 32, UInt   );
4978c7f1abe9e022f6382634efea09c9cac89ec6336sewardj
4982a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_SHLB:   ACTIONS_SHL(  8, UChar  );
4992a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_SHLW:   ACTIONS_SHL( 16, UShort );
5002a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_SHLL:   ACTIONS_SHL( 32, UInt   );
5018c7f1abe9e022f6382634efea09c9cac89ec6336sewardj
5022a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_SHRB:   ACTIONS_SHR(  8, UChar  );
5032a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_SHRW:   ACTIONS_SHR( 16, UShort );
5042a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_SHRL:   ACTIONS_SHR( 32, UInt   );
5051813dbeb912870e9a544cae17a3fadbf8d2b0d55sewardj
5062a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_ROLB:   ACTIONS_ROL(  8, UChar  );
5072a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_ROLW:   ACTIONS_ROL( 16, UShort );
5082a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_ROLL:   ACTIONS_ROL( 32, UInt   );
509750f407b6be1aac303964a219acf0a6de8b8c4dasewardj
5102a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_RORB:   ACTIONS_ROR(  8, UChar  );
5112a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_RORW:   ACTIONS_ROR( 16, UShort );
5122a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_RORL:   ACTIONS_ROR( 32, UInt   );
5137ed2295459ac5e788a98dd5570fef0d4645c27d4sewardj
5142a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_UMULB:  ACTIONS_UMUL(  8, UChar,  UShort );
5152a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_UMULW:  ACTIONS_UMUL( 16, UShort, UInt   );
5162a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_UMULL:  ACTIONS_UMUL( 32, UInt,   ULong  );
51756296d80c9e15ec59eebecf1c3aea9ebd4dac115sewardj
5182a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_SMULB:  ACTIONS_SMUL(  8, Char,   Short );
5192a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_SMULW:  ACTIONS_SMUL( 16, Short,  Int   );
5202a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_SMULL:  ACTIONS_SMUL( 32, Int,    Long  );
521741153c4301023a420ab45b8a10b8e1bac968822sewardj
52236ca51378f8851635df814230fa23f2c409b9eddsewardj      default:
52336ca51378f8851635df814230fa23f2c409b9eddsewardj         /* shouldn't really make these calls from generated code */
5242a9ad023890d3b34cf45e429df2a8ae88b419128sewardj         vex_printf("calculate_eflags_all(X86)( %d, 0x%x, 0x%x, 0x%x )\n",
5252a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj                    cc_op, cc_dep1_formal, cc_dep2_formal, cc_ndep_formal );
5262a9ad023890d3b34cf45e429df2a8ae88b419128sewardj         vpanic("calculate_eflags_all(X86)");
52736ca51378f8851635df814230fa23f2c409b9eddsewardj   }
52836ca51378f8851635df814230fa23f2c409b9eddsewardj}
52936ca51378f8851635df814230fa23f2c409b9eddsewardj
530b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
5319aebb0c3f7a7f43313786826f31402f2b733badfsewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
532b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/* Calculate just the carry flag from the supplied thunk parameters. */
5332a9ad023890d3b34cf45e429df2a8ae88b419128sewardjUInt x86g_calculate_eflags_c ( UInt cc_op,
5342a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                               UInt cc_dep1,
5352a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                               UInt cc_dep2,
5362a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                               UInt cc_ndep )
53736ca51378f8851635df814230fa23f2c409b9eddsewardj{
5389eab588e223e52b1e7b710ff1c0da7b032ab2837sewardj   /* Fast-case some common ones. */
53943c46951628d616290f7245c3af2f9a652180806sewardj   switch (cc_op) {
5402a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_LOGICL:
5412a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_LOGICW:
5422a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_LOGICB:
54343c46951628d616290f7245c3af2f9a652180806sewardj         return 0;
5442a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_SUBL:
54593d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj         return ((UInt)cc_dep1) < ((UInt)cc_dep2)
5462a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                   ? X86G_CC_MASK_C : 0;
5472a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_SUBB:
54893d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj         return ((UInt)(cc_dep1 & 0xFF)) < ((UInt)(cc_dep2 & 0xFF))
5492a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                   ? X86G_CC_MASK_C : 0;
550e9ba4328f2afb94bc8474e9a7205e50ed9ac73fcsewardj      case X86G_CC_OP_INCL:
5512a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_DECL:
552e9ba4328f2afb94bc8474e9a7205e50ed9ac73fcsewardj         return cc_ndep & X86G_CC_MASK_C;
553e9ba4328f2afb94bc8474e9a7205e50ed9ac73fcsewardj#if 0
554e9ba4328f2afb94bc8474e9a7205e50ed9ac73fcsewardj      /* unclear if these are correct or not */
5552a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_ADDL:
55643c46951628d616290f7245c3af2f9a652180806sewardj         return ( ((UInt)cc_src + (UInt)cc_dst) < ((UInt)cc_src) )
5572a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                   ? X86G_CC_MASK_C : 0;
5582a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_SUBB:
55943c46951628d616290f7245c3af2f9a652180806sewardj         return ( ((UInt)(cc_src & 0xFF)) > ((UInt)(cc_dst & 0xFF)) )
5602a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                   ? X86G_CC_MASK_C : 0;
561948d48be23eca9df7b9d33be5dca499affb7cb3asewardj#endif
56243c46951628d616290f7245c3af2f9a652180806sewardj      default:
56343c46951628d616290f7245c3af2f9a652180806sewardj         break;
56443c46951628d616290f7245c3af2f9a652180806sewardj   }
5659eab588e223e52b1e7b710ff1c0da7b032ab2837sewardj
56684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  if PROFILE_EFLAGS
56784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   if (!initted)
56884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      initCounts();
56984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   tabc[cc_op]++;
57084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
57184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   n_calc_c++;
57284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  endif
5732a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   return x86g_calculate_eflags_all(cc_op,cc_dep1,cc_dep2,cc_ndep)
5742a9ad023890d3b34cf45e429df2a8ae88b419128sewardj          & X86G_CC_MASK_C;
57536ca51378f8851635df814230fa23f2c409b9eddsewardj}
57636ca51378f8851635df814230fa23f2c409b9eddsewardj
57736ca51378f8851635df814230fa23f2c409b9eddsewardj
5789aebb0c3f7a7f43313786826f31402f2b733badfsewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
57984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj/* returns 1 or 0 */
5802a9ad023890d3b34cf45e429df2a8ae88b419128sewardjUInt x86g_calculate_condition ( UInt/*X86Condcode*/ cond,
5812a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                                UInt cc_op,
5822a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                                UInt cc_dep1,
5832a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                                UInt cc_dep2,
5842a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                                UInt cc_ndep )
5852a9ad023890d3b34cf45e429df2a8ae88b419128sewardj{
5862a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   UInt eflags = x86g_calculate_eflags_all(cc_op, cc_dep1,
5872a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                                           cc_dep2, cc_ndep);
58884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   UInt of,sf,zf,cf,pf;
58984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   UInt inv = cond & 1;
59084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
59184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  if PROFILE_EFLAGS
59284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   if (!initted)
59384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj     initCounts();
59484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
59584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   tab[cc_op][cond]++;
59684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   n_calc_cond++;
59784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
59893d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj   if (0 == ((n_calc_all+n_calc_c) & 0x7FFFF)) showCounts();
59984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  endif
60084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
60184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   switch (cond) {
6022a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86CondNO:
6032a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86CondO: /* OF == 1 */
6042a9ad023890d3b34cf45e429df2a8ae88b419128sewardj         of = eflags >> X86G_CC_SHIFT_O;
60584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return 1 & (inv ^ of);
60684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
6072a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86CondNZ:
6082a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86CondZ: /* ZF == 1 */
6092a9ad023890d3b34cf45e429df2a8ae88b419128sewardj         zf = eflags >> X86G_CC_SHIFT_Z;
61084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return 1 & (inv ^ zf);
61184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
6122a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86CondNB:
6132a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86CondB: /* CF == 1 */
6142a9ad023890d3b34cf45e429df2a8ae88b419128sewardj         cf = eflags >> X86G_CC_SHIFT_C;
61584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return 1 & (inv ^ cf);
61684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         break;
61784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
6182a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86CondNBE:
6192a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86CondBE: /* (CF or ZF) == 1 */
6202a9ad023890d3b34cf45e429df2a8ae88b419128sewardj         cf = eflags >> X86G_CC_SHIFT_C;
6212a9ad023890d3b34cf45e429df2a8ae88b419128sewardj         zf = eflags >> X86G_CC_SHIFT_Z;
62284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return 1 & (inv ^ (cf | zf));
62384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         break;
62484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
6252a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86CondNS:
6262a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86CondS: /* SF == 1 */
6272a9ad023890d3b34cf45e429df2a8ae88b419128sewardj         sf = eflags >> X86G_CC_SHIFT_S;
62884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return 1 & (inv ^ sf);
62984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
6302a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86CondNP:
6312a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86CondP: /* PF == 1 */
6322a9ad023890d3b34cf45e429df2a8ae88b419128sewardj         pf = eflags >> X86G_CC_SHIFT_P;
63384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return 1 & (inv ^ pf);
63484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
6352a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86CondNL:
6362a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86CondL: /* (SF xor OF) == 1 */
6372a9ad023890d3b34cf45e429df2a8ae88b419128sewardj         sf = eflags >> X86G_CC_SHIFT_S;
6382a9ad023890d3b34cf45e429df2a8ae88b419128sewardj         of = eflags >> X86G_CC_SHIFT_O;
63984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return 1 & (inv ^ (sf ^ of));
64084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         break;
64184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
6422a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86CondNLE:
6432a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86CondLE: /* ((SF xor OF) or ZF)  == 1 */
6442a9ad023890d3b34cf45e429df2a8ae88b419128sewardj         sf = eflags >> X86G_CC_SHIFT_S;
6452a9ad023890d3b34cf45e429df2a8ae88b419128sewardj         of = eflags >> X86G_CC_SHIFT_O;
6462a9ad023890d3b34cf45e429df2a8ae88b419128sewardj         zf = eflags >> X86G_CC_SHIFT_Z;
64784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return 1 & (inv ^ ((sf ^ of) | zf));
64884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         break;
64984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
65084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      default:
65184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         /* shouldn't really make these calls from generated code */
6522a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj         vex_printf("calculate_condition( %d, %d, 0x%x, 0x%x, 0x%x )\n",
6532a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj                    cond, cc_op, cc_dep1, cc_dep2, cc_ndep );
65484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         vpanic("calculate_condition");
65584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   }
65684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj}
65784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
65884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
65984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj/* Used by the optimiser to try specialisations.  Returns an
66084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   equivalent expression, or NULL if none. */
66184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
66284ff0657940e62f38e618ea18bac6f27ce0e741fsewardjstatic Bool isU32 ( IRExpr* e, UInt n )
66384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj{
66484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   return e->tag == Iex_Const
66584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj          && e->Iex.Const.con->tag == Ico_U32
66684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj          && e->Iex.Const.con->Ico.U32 == n;
66784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj}
66884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
6692a9ad023890d3b34cf45e429df2a8ae88b419128sewardjIRExpr* guest_x86_spechelper ( Char* function_name,
6702a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                               IRExpr** args )
67184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj{
67284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  define unop(_op,_a1) IRExpr_Unop((_op),(_a1))
67384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  define binop(_op,_a1,_a2) IRExpr_Binop((_op),(_a1),(_a2))
67484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  define mkU32(_n) IRExpr_Const(IRConst_U32(_n))
6754afab82eb869f21ccabc3efb5b93f31a5c343956sewardj#  define mkU8(_n)  IRExpr_Const(IRConst_U8(_n))
67684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
67784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   Int i, arity = 0;
67884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   for (i = 0; args[i]; i++)
67984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      arity++;
68084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  if 0
68184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   vex_printf("spec request:\n");
68284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   vex_printf("   %s  ", function_name);
68384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   for (i = 0; i < arity; i++) {
68484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      vex_printf("  ");
68584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      ppIRExpr(args[i]);
68684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   }
68784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   vex_printf("\n");
68884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  endif
68993d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj
6903835288ac63bb755c0e1d2f3142a13416dcb64c6sewardj   /* --------- specialising "x86g_calculate_eflags_c" --------- */
69193d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj
6923835288ac63bb755c0e1d2f3142a13416dcb64c6sewardj   if (vex_streq(function_name, "x86g_calculate_eflags_c")) {
69384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      /* specialise calls to above "calculate_eflags_c" function */
69493d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj      IRExpr *cc_op, *cc_dep1, *cc_dep2, *cc_ndep;
69593d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj      vassert(arity == 4);
69693d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj      cc_op   = args[0];
69793d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj      cc_dep1 = args[1];
69893d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj      cc_dep2 = args[2];
69993d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj      cc_ndep = args[3];
70084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
7012a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_SUBL)) {
70293d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj         /* C after sub denotes unsigned less than */
70393d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj         return unop(Iop_1Uto32,
70493d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj                     binop(Iop_CmpLT32U, cc_dep1, cc_dep2));
70593d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj      }
706e9ba4328f2afb94bc8474e9a7205e50ed9ac73fcsewardj      if (isU32(cc_op, X86G_CC_OP_SUBB)) {
707e9ba4328f2afb94bc8474e9a7205e50ed9ac73fcsewardj         /* C after sub denotes unsigned less than */
708e9ba4328f2afb94bc8474e9a7205e50ed9ac73fcsewardj         return unop(Iop_1Uto32,
709e9ba4328f2afb94bc8474e9a7205e50ed9ac73fcsewardj                     binop(Iop_CmpLT32U,
710e9ba4328f2afb94bc8474e9a7205e50ed9ac73fcsewardj                           binop(Iop_And32,cc_dep1,mkU32(0xFF)),
711e9ba4328f2afb94bc8474e9a7205e50ed9ac73fcsewardj                           binop(Iop_And32,cc_dep2,mkU32(0xFF))));
712e9ba4328f2afb94bc8474e9a7205e50ed9ac73fcsewardj      }
7132a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_LOGICL)) {
71484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         /* cflag after logic is zero */
71584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return mkU32(0);
71684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
7172a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_DECL) || isU32(cc_op, X86G_CC_OP_INCL)) {
71822419b8f4f2c0104549ca9954f68e190b911d1a0sewardj         /* If the thunk is dec or inc, the cflag is supplied as CC_NDEP. */
719e7bd0686e5d90b22fe7fe12ae00afb8a71ab008asewardj         return cc_ndep;
72084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
72107f284e78c5d8bb00e2f4fcaed5bb29571d6058asewardj      if (isU32(cc_op, X86G_CC_OP_COPY)) {
72207f284e78c5d8bb00e2f4fcaed5bb29571d6058asewardj         /* cflag after COPY is stored in DEP1. */
72307f284e78c5d8bb00e2f4fcaed5bb29571d6058asewardj         return
72407f284e78c5d8bb00e2f4fcaed5bb29571d6058asewardj            binop(
72507f284e78c5d8bb00e2f4fcaed5bb29571d6058asewardj               Iop_And32,
72607f284e78c5d8bb00e2f4fcaed5bb29571d6058asewardj               binop(Iop_Shr32, cc_dep1, mkU8(X86G_CC_SHIFT_C)),
72707f284e78c5d8bb00e2f4fcaed5bb29571d6058asewardj               mkU32(1)
72807f284e78c5d8bb00e2f4fcaed5bb29571d6058asewardj            );
72907f284e78c5d8bb00e2f4fcaed5bb29571d6058asewardj      }
73084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#     if 0
73184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      if (cc_op->tag == Iex_Const) {
73284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         vex_printf("CFLAG "); ppIRExpr(cc_op); vex_printf("\n");
73384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
73484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#     endif
73584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
73684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      return NULL;
73784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   }
73884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
7393835288ac63bb755c0e1d2f3142a13416dcb64c6sewardj   /* --------- specialising "x86g_calculate_condition" --------- */
74093d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj
7413835288ac63bb755c0e1d2f3142a13416dcb64c6sewardj   if (vex_streq(function_name, "x86g_calculate_condition")) {
74284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      /* specialise calls to above "calculate condition" function */
743a8415ffe6c6f0e73519301a55026a4071c701fd1sewardj      IRExpr *cond, *cc_op, *cc_dep1, *cc_dep2;
74493d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj      vassert(arity == 5);
74593d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj      cond    = args[0];
74693d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj      cc_op   = args[1];
74793d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj      cc_dep1 = args[2];
74893d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj      cc_dep2 = args[3];
74984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
750d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj      /*---------------- ADDL ----------------*/
751d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj
7522a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_ADDL) && isU32(cond, X86CondZ)) {
753d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj         /* long add, then Z --> test (dst+src == 0) */
754d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj         return unop(Iop_1Uto32,
755d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj                     binop(Iop_CmpEQ32,
756d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj                           binop(Iop_Add32, cc_dep1, cc_dep2),
757d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj                           mkU32(0)));
758d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj      }
759d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj
76046ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      /*---------------- SUBL ----------------*/
76146ccb51aff085d180120d310c0be2fe6c86e1b65sewardj
7622a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_SUBL) && isU32(cond, X86CondZ)) {
76346ccb51aff085d180120d310c0be2fe6c86e1b65sewardj         /* long sub/cmp, then Z --> test dst==src */
76484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return unop(Iop_1Uto32,
76593d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj                     binop(Iop_CmpEQ32, cc_dep1, cc_dep2));
76646ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      }
76746ccb51aff085d180120d310c0be2fe6c86e1b65sewardj
7682a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_SUBL) && isU32(cond, X86CondL)) {
76946ccb51aff085d180120d310c0be2fe6c86e1b65sewardj         /* long sub/cmp, then L (signed less than)
77046ccb51aff085d180120d310c0be2fe6c86e1b65sewardj            --> test dst <s src */
77146ccb51aff085d180120d310c0be2fe6c86e1b65sewardj         return unop(Iop_1Uto32,
77293d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj                     binop(Iop_CmpLT32S, cc_dep1, cc_dep2));
77346ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      }
77446ccb51aff085d180120d310c0be2fe6c86e1b65sewardj
7752a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_SUBL) && isU32(cond, X86CondLE)) {
77646ccb51aff085d180120d310c0be2fe6c86e1b65sewardj         /* long sub/cmp, then LE (signed less than or equal)
77746ccb51aff085d180120d310c0be2fe6c86e1b65sewardj            --> test dst <=s src */
77846ccb51aff085d180120d310c0be2fe6c86e1b65sewardj         return unop(Iop_1Uto32,
77993d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj                     binop(Iop_CmpLE32S, cc_dep1, cc_dep2));
78046ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      }
78146ccb51aff085d180120d310c0be2fe6c86e1b65sewardj
7822a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_SUBL) && isU32(cond, X86CondBE)) {
78346ccb51aff085d180120d310c0be2fe6c86e1b65sewardj         /* long sub/cmp, then BE (unsigned less than or equal)
78446ccb51aff085d180120d310c0be2fe6c86e1b65sewardj            --> test dst <=u src */
78546ccb51aff085d180120d310c0be2fe6c86e1b65sewardj         return unop(Iop_1Uto32,
78693d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj                     binop(Iop_CmpLE32U, cc_dep1, cc_dep2));
78746ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      }
788e664ec4b9f27ed7d7ca87a2d4188fd479059351csewardj
7892a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_SUBL) && isU32(cond, X86CondB)) {
79046ccb51aff085d180120d310c0be2fe6c86e1b65sewardj         /* long sub/cmp, then B (unsigned less than)
79146ccb51aff085d180120d310c0be2fe6c86e1b65sewardj            --> test dst <u src */
79246ccb51aff085d180120d310c0be2fe6c86e1b65sewardj         return unop(Iop_1Uto32,
793e664ec4b9f27ed7d7ca87a2d4188fd479059351csewardj                     binop(Iop_CmpLT32U, cc_dep1, cc_dep2));
79484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
795e664ec4b9f27ed7d7ca87a2d4188fd479059351csewardj
79646ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      /*---------------- SUBW ----------------*/
79746ccb51aff085d180120d310c0be2fe6c86e1b65sewardj
7982a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_SUBW) && isU32(cond, X86CondZ)) {
799b9c5cf639b3b21b972599d27207a033afc76ef67sewardj         /* byte sub/cmp, then Z --> test dst==src */
800b9c5cf639b3b21b972599d27207a033afc76ef67sewardj         return unop(Iop_1Uto32,
801b9c5cf639b3b21b972599d27207a033afc76ef67sewardj                     binop(Iop_CmpEQ16,
8027e6644c38b3e0148ff95c2f6f4667f54148b611esewardj                           unop(Iop_32to16,cc_dep1),
8037e6644c38b3e0148ff95c2f6f4667f54148b611esewardj                           unop(Iop_32to16,cc_dep2)));
804b9c5cf639b3b21b972599d27207a033afc76ef67sewardj      }
805b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
80646ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      /*---------------- SUBB ----------------*/
8077e6644c38b3e0148ff95c2f6f4667f54148b611esewardj
8082a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_SUBB) && isU32(cond, X86CondZ)) {
809b9c5cf639b3b21b972599d27207a033afc76ef67sewardj         /* byte sub/cmp, then Z --> test dst==src */
81084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return unop(Iop_1Uto32,
811b9c5cf639b3b21b972599d27207a033afc76ef67sewardj                     binop(Iop_CmpEQ8,
81293d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj                           unop(Iop_32to8,cc_dep1),
81393d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj                           unop(Iop_32to8,cc_dep2)));
81484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
81584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
8162a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_SUBB) && isU32(cond, X86CondNZ)) {
8177e5b7cdbfa65376488d58e4e6d8f13d974f7a8bcsewardj         /* byte sub/cmp, then NZ --> test dst!=src */
81884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return unop(Iop_1Uto32,
819b9c5cf639b3b21b972599d27207a033afc76ef67sewardj                     binop(Iop_CmpNE8,
82093d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj                           unop(Iop_32to8,cc_dep1),
82193d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj                           unop(Iop_32to8,cc_dep2)));
822b9c5cf639b3b21b972599d27207a033afc76ef67sewardj      }
82322419b8f4f2c0104549ca9954f68e190b911d1a0sewardj
8242a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_SUBB) && isU32(cond, X86CondNBE)) {
825b9c5cf639b3b21b972599d27207a033afc76ef67sewardj         /* long sub/cmp, then NBE (unsigned greater than)
826b9c5cf639b3b21b972599d27207a033afc76ef67sewardj            --> test src <=u dst */
8277e5b7cdbfa65376488d58e4e6d8f13d974f7a8bcsewardj         /* Note, args are opposite way round from the usual */
828b9c5cf639b3b21b972599d27207a033afc76ef67sewardj         return unop(Iop_1Uto32,
829b9c5cf639b3b21b972599d27207a033afc76ef67sewardj                     binop(Iop_CmpLT32U,
8307e5b7cdbfa65376488d58e4e6d8f13d974f7a8bcsewardj                           binop(Iop_And32,cc_dep2,mkU32(0xFF)),
8317e5b7cdbfa65376488d58e4e6d8f13d974f7a8bcsewardj			   binop(Iop_And32,cc_dep1,mkU32(0xFF))));
83284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
83384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
83446ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      /*---------------- LOGICL ----------------*/
83546ccb51aff085d180120d310c0be2fe6c86e1b65sewardj
8362a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_LOGICL) && isU32(cond, X86CondZ)) {
83784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         /* long and/or/xor, then Z --> test dst==0 */
83893d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj         return unop(Iop_1Uto32,binop(Iop_CmpEQ32, cc_dep1, mkU32(0)));
83984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
84022419b8f4f2c0104549ca9954f68e190b911d1a0sewardj
8412a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_LOGICL) && isU32(cond, X86CondS)) {
842fae2ca7ef81549a4b28235618317d4352ca32ac2sewardj         /* long and/or/xor, then S --> test dst <s 0 */
8437e6644c38b3e0148ff95c2f6f4667f54148b611esewardj         return unop(Iop_1Uto32,binop(Iop_CmpLT32S, cc_dep1, mkU32(0)));
844fae2ca7ef81549a4b28235618317d4352ca32ac2sewardj      }
84522419b8f4f2c0104549ca9954f68e190b911d1a0sewardj
8462a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_LOGICL) && isU32(cond, X86CondLE)) {
84784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         /* long and/or/xor, then LE
84884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj            This is pretty subtle.  LOGIC sets SF and ZF according to the
84984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj            result and makes OF be zero.  LE computes (SZ ^ OF) | ZF, but
85084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj            OF is zero, so this reduces to SZ | ZF -- which will be 1 iff
85184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj            the result is <=signed 0.  Hence ...
85284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         */
85393d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj         return unop(Iop_1Uto32,binop(Iop_CmpLE32S, cc_dep1, mkU32(0)));
85484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
85584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
856d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj      /*---------------- LOGICW ----------------*/
857d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj
8582a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_LOGICW) && isU32(cond, X86CondZ)) {
859d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj         /* byte and/or/xor, then Z --> test dst==0 */
860d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj         return unop(Iop_1Uto32,
861d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj                     binop(Iop_CmpEQ32, binop(Iop_And32,cc_dep1,mkU32(0xFFFF)),
862d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj                                        mkU32(0)));
863d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj      }
864d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj
86546ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      /*---------------- LOGICB ----------------*/
86684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
8672a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_LOGICB) && isU32(cond, X86CondZ)) {
86846ccb51aff085d180120d310c0be2fe6c86e1b65sewardj         /* byte and/or/xor, then Z --> test dst==0 */
86984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return unop(Iop_1Uto32,
87093d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj                     binop(Iop_CmpEQ32, binop(Iop_And32,cc_dep1,mkU32(255)),
87146ccb51aff085d180120d310c0be2fe6c86e1b65sewardj                                        mkU32(0)));
87284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
87384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
87446ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      /*---------------- DECL ----------------*/
875af991dede2815b7570828b9d9174cf989e636254sewardj
8762a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_DECL) && isU32(cond, X86CondZ)) {
87784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         /* dec L, then Z --> test dst == 0 */
87893d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj         return unop(Iop_1Uto32,binop(Iop_CmpEQ32, cc_dep1, mkU32(0)));
87984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
88022419b8f4f2c0104549ca9954f68e190b911d1a0sewardj
8812a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_DECL) && isU32(cond, X86CondS)) {
882fae2ca7ef81549a4b28235618317d4352ca32ac2sewardj         /* dec L, then S --> compare DST <s 0 */
8837e6644c38b3e0148ff95c2f6f4667f54148b611esewardj         return unop(Iop_1Uto32,binop(Iop_CmpLT32S, cc_dep1, mkU32(0)));
884fae2ca7ef81549a4b28235618317d4352ca32ac2sewardj      }
885fae2ca7ef81549a4b28235618317d4352ca32ac2sewardj
886d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj      /*---------------- SHRL ----------------*/
887d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj
8882a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_SHRL) && isU32(cond, X86CondZ)) {
889d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj         /* SHRL, then Z --> test dep1 == 0 */
890d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj         return unop(Iop_1Uto32,binop(Iop_CmpEQ32, cc_dep1, mkU32(0)));
891d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj      }
892d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj
8934afab82eb869f21ccabc3efb5b93f31a5c343956sewardj      /*---------------- COPY ----------------*/
8944afab82eb869f21ccabc3efb5b93f31a5c343956sewardj      /* This can happen, as a result of x87 FP compares: "fcom ... ;
8954afab82eb869f21ccabc3efb5b93f31a5c343956sewardj         fnstsw %ax ; sahf ; jbe" for example. */
8964afab82eb869f21ccabc3efb5b93f31a5c343956sewardj
8974afab82eb869f21ccabc3efb5b93f31a5c343956sewardj      if (isU32(cc_op, X86G_CC_OP_COPY) && isU32(cond, X86CondBE)) {
8984afab82eb869f21ccabc3efb5b93f31a5c343956sewardj         /* COPY, then BE --> extract C and Z from dep1, and test (C
8994afab82eb869f21ccabc3efb5b93f31a5c343956sewardj            or Z == 1). */
9004afab82eb869f21ccabc3efb5b93f31a5c343956sewardj         return
9014afab82eb869f21ccabc3efb5b93f31a5c343956sewardj            unop(
9024afab82eb869f21ccabc3efb5b93f31a5c343956sewardj               Iop_1Uto32,
9034afab82eb869f21ccabc3efb5b93f31a5c343956sewardj               binop(
9044afab82eb869f21ccabc3efb5b93f31a5c343956sewardj                  Iop_CmpNE32,
9054afab82eb869f21ccabc3efb5b93f31a5c343956sewardj                  binop(
9064afab82eb869f21ccabc3efb5b93f31a5c343956sewardj                     Iop_And32,
9074afab82eb869f21ccabc3efb5b93f31a5c343956sewardj                     binop(
9084afab82eb869f21ccabc3efb5b93f31a5c343956sewardj                        Iop_Or32,
9094afab82eb869f21ccabc3efb5b93f31a5c343956sewardj                        binop(Iop_Shr32, cc_dep1, mkU8(X86G_CC_SHIFT_C)),
9104afab82eb869f21ccabc3efb5b93f31a5c343956sewardj                        binop(Iop_Shr32, cc_dep1, mkU8(X86G_CC_SHIFT_Z))
9114afab82eb869f21ccabc3efb5b93f31a5c343956sewardj                     ),
9124afab82eb869f21ccabc3efb5b93f31a5c343956sewardj                     mkU32(1)
9134afab82eb869f21ccabc3efb5b93f31a5c343956sewardj                  ),
9144afab82eb869f21ccabc3efb5b93f31a5c343956sewardj                  mkU32(0)
9154afab82eb869f21ccabc3efb5b93f31a5c343956sewardj               )
9164afab82eb869f21ccabc3efb5b93f31a5c343956sewardj            );
9174afab82eb869f21ccabc3efb5b93f31a5c343956sewardj      }
9184afab82eb869f21ccabc3efb5b93f31a5c343956sewardj
9194afab82eb869f21ccabc3efb5b93f31a5c343956sewardj      if (isU32(cc_op, X86G_CC_OP_COPY) && isU32(cond, X86CondB)) {
9204afab82eb869f21ccabc3efb5b93f31a5c343956sewardj         /* COPY, then B --> extract C dep1, and test (C == 1). */
9214afab82eb869f21ccabc3efb5b93f31a5c343956sewardj         return
9224afab82eb869f21ccabc3efb5b93f31a5c343956sewardj            unop(
9234afab82eb869f21ccabc3efb5b93f31a5c343956sewardj               Iop_1Uto32,
9244afab82eb869f21ccabc3efb5b93f31a5c343956sewardj               binop(
9254afab82eb869f21ccabc3efb5b93f31a5c343956sewardj                  Iop_CmpNE32,
9264afab82eb869f21ccabc3efb5b93f31a5c343956sewardj                  binop(
9274afab82eb869f21ccabc3efb5b93f31a5c343956sewardj                     Iop_And32,
9284afab82eb869f21ccabc3efb5b93f31a5c343956sewardj                     binop(Iop_Shr32, cc_dep1, mkU8(X86G_CC_SHIFT_C)),
9294afab82eb869f21ccabc3efb5b93f31a5c343956sewardj                     mkU32(1)
9304afab82eb869f21ccabc3efb5b93f31a5c343956sewardj                  ),
9314afab82eb869f21ccabc3efb5b93f31a5c343956sewardj                  mkU32(0)
9324afab82eb869f21ccabc3efb5b93f31a5c343956sewardj               )
9334afab82eb869f21ccabc3efb5b93f31a5c343956sewardj            );
9344afab82eb869f21ccabc3efb5b93f31a5c343956sewardj      }
9354afab82eb869f21ccabc3efb5b93f31a5c343956sewardj
93684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      return NULL;
93784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   }
93884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
93984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  undef unop
94084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  undef binop
94184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  undef mkU32
9424afab82eb869f21ccabc3efb5b93f31a5c343956sewardj#  undef mkU8
94384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
94484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   return NULL;
94584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj}
94684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
94736ca51378f8851635df814230fa23f2c409b9eddsewardj
9480c2cb623cca372a2b42b073121c7413cdaaf75besewardj/*-----------------------------------------------------------*/
9490c2cb623cca372a2b42b073121c7413cdaaf75besewardj/*--- Utility functions for x87 FPU conversions.          ---*/
9500c2cb623cca372a2b42b073121c7413cdaaf75besewardj/*-----------------------------------------------------------*/
9510c2cb623cca372a2b42b073121c7413cdaaf75besewardj
9520c2cb623cca372a2b42b073121c7413cdaaf75besewardj
9530c2cb623cca372a2b42b073121c7413cdaaf75besewardj/* 80 and 64-bit floating point formats:
9540c2cb623cca372a2b42b073121c7413cdaaf75besewardj
9550c2cb623cca372a2b42b073121c7413cdaaf75besewardj   80-bit:
9560c2cb623cca372a2b42b073121c7413cdaaf75besewardj
9570c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  0       0-------0      zero
9580c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  0       0X------X      denormals
9590c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  1-7FFE  1X------X      normals (all normals have leading 1)
9600c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  7FFF    10------0      infinity
9610c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  7FFF    10X-----X      snan
9620c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  7FFF    11X-----X      qnan
9630c2cb623cca372a2b42b073121c7413cdaaf75besewardj
9640c2cb623cca372a2b42b073121c7413cdaaf75besewardj   S is the sign bit.  For runs X----X, at least one of the Xs must be
9650c2cb623cca372a2b42b073121c7413cdaaf75besewardj   nonzero.  Exponent is 15 bits, fractional part is 63 bits, and
9660c2cb623cca372a2b42b073121c7413cdaaf75besewardj   there is an explicitly represented leading 1, and a sign bit,
9670c2cb623cca372a2b42b073121c7413cdaaf75besewardj   giving 80 in total.
9680c2cb623cca372a2b42b073121c7413cdaaf75besewardj
9690c2cb623cca372a2b42b073121c7413cdaaf75besewardj   64-bit avoids the confusion of an explicitly represented leading 1
9700c2cb623cca372a2b42b073121c7413cdaaf75besewardj   and so is simpler:
9710c2cb623cca372a2b42b073121c7413cdaaf75besewardj
9720c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  0      0------0   zero
9730c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  0      X------X   denormals
9740c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  1-7FE  any        normals
9750c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  7FF    0------0   infinity
9760c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  7FF    0X-----X   snan
9770c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  7FF    1X-----X   qnan
9780c2cb623cca372a2b42b073121c7413cdaaf75besewardj
9790c2cb623cca372a2b42b073121c7413cdaaf75besewardj   Exponent is 11 bits, fractional part is 52 bits, and there is a
9800c2cb623cca372a2b42b073121c7413cdaaf75besewardj   sign bit, giving 64 in total.
9810c2cb623cca372a2b42b073121c7413cdaaf75besewardj*/
9820c2cb623cca372a2b42b073121c7413cdaaf75besewardj
983c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardjstatic inline Bool host_is_little_endian ( void )
984c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj{
985c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   UInt x = 0x76543210;
986c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   UChar* p = (UChar*)(&x);
987c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   return (*p == 0x10);
988c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj}
989c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
9909aebb0c3f7a7f43313786826f31402f2b733badfsewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
9912a9ad023890d3b34cf45e429df2a8ae88b419128sewardjUInt x86g_calculate_FXAM ( UInt tag, ULong dbl )
992c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj{
993c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   Bool   mantissaIsZero;
994c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   Int    bexp;
995c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   UChar  sign;
996c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   UChar* f64;
997c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
998a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   vassert(host_is_little_endian());
999c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
1000c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   /* vex_printf("calculate_FXAM ( %d, %llx ) .. ", tag, dbl ); */
1001c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
1002c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   f64  = (UChar*)(&dbl);
1003c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   sign = (f64[7] >> 7) & 1;
1004c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
1005c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   /* First off, if the tag indicates the register was empty,
1006c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      return 1,0,sign,1 */
1007c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   if (tag == 0) {
1008c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      /* vex_printf("Empty\n"); */
10092a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      return X86G_FC_MASK_C3 | 0 | sign | X86G_FC_MASK_C0;
1010c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   }
1011c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
1012c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   bexp = (f64[7] << 4) | ((f64[6] >> 4) & 0x0F);
1013c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   bexp &= 0x7FF;
1014c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
1015c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   mantissaIsZero
1016c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      = (f64[6] & 0x0F) == 0
1017c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj        && (f64[5] | f64[4] | f64[3] | f64[2] | f64[1] | f64[0]) == 0;
1018c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
1019c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   /* If both exponent and mantissa are zero, the value is zero.
1020c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      Return 1,0,sign,0. */
1021c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   if (bexp == 0 && mantissaIsZero) {
1022c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      /* vex_printf("Zero\n"); */
10232a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      return X86G_FC_MASK_C3 | 0 | sign | 0;
1024c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   }
1025c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
1026c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   /* If exponent is zero but mantissa isn't, it's a denormal.
1027c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      Return 1,1,sign,0. */
1028c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   if (bexp == 0 && !mantissaIsZero) {
1029c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      /* vex_printf("Denormal\n"); */
10302a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      return X86G_FC_MASK_C3 | X86G_FC_MASK_C2 | sign | 0;
1031c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   }
1032c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
1033c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   /* If the exponent is 7FF and the mantissa is zero, this is an infinity.
1034c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      Return 0,1,sign,1. */
1035c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   if (bexp == 0x7FF && mantissaIsZero) {
1036c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      /* vex_printf("Inf\n"); */
10372a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      return 0 | X86G_FC_MASK_C2 | sign | X86G_FC_MASK_C0;
1038c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   }
1039c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
1040c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   /* If the exponent is 7FF and the mantissa isn't zero, this is a NaN.
1041c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      Return 0,0,sign,1. */
1042c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   if (bexp == 0x7FF && !mantissaIsZero) {
1043c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      /* vex_printf("NaN\n"); */
10442a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      return 0 | 0 | sign | X86G_FC_MASK_C0;
1045c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   }
1046c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
1047c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   /* Uh, ok, we give up.  It must be a normal finite number.
1048c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      Return 0,1,sign,0.
1049c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   */
1050c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   /* vex_printf("normal\n"); */
10512a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   return 0 | X86G_FC_MASK_C2 | sign | 0;
1052c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj}
1053c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
10540c2cb623cca372a2b42b073121c7413cdaaf75besewardj
105514d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj/////////////////////////////////////////////////////////////////
105614d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj
105714d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardjstatic inline
105814d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardjUInt read_bit_array ( UChar* arr, UInt n )
105914d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj{
106014d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj   UChar c = arr[n >> 3];
106114d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj   c >>= (n&7);
106214d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj   return c & 1;
106314d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj}
106414d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj
106514d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardjstatic inline
106614d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardjvoid write_bit_array ( UChar* arr, UInt n, UInt b )
106714d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj{
106814d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj   UChar c = arr[n >> 3];
106914d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj   c &= ~(1 << (n&7));
107014d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj   c |= ((b&1) << (n&7));
107114d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj   arr[n >> 3] = c;
107214d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj}
107314d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj
107414d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj
10750c2cb623cca372a2b42b073121c7413cdaaf75besewardj/* Convert a IEEE754 double (64-bit) into an x87 extended double
10760c2cb623cca372a2b42b073121c7413cdaaf75besewardj   (80-bit), mimicing the hardware fairly closely.  Both numbers are
10770c2cb623cca372a2b42b073121c7413cdaaf75besewardj   stored little-endian.  Limitations, all of which could be fixed,
10780c2cb623cca372a2b42b073121c7413cdaaf75besewardj   given some level of hassle:
10790c2cb623cca372a2b42b073121c7413cdaaf75besewardj
10800c2cb623cca372a2b42b073121c7413cdaaf75besewardj   * Identity of NaNs is not preserved.
10810c2cb623cca372a2b42b073121c7413cdaaf75besewardj
10820c2cb623cca372a2b42b073121c7413cdaaf75besewardj   See comments in the code for more details.
10830c2cb623cca372a2b42b073121c7413cdaaf75besewardj*/
10840c2cb623cca372a2b42b073121c7413cdaaf75besewardjstatic void convert_f64le_to_f80le ( /*IN*/UChar* f64, /*OUT*/UChar* f80 )
10850c2cb623cca372a2b42b073121c7413cdaaf75besewardj{
108614d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj   Bool  mantissaIsZero;
108714d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj   Int   bexp, i, j, shift;
10880c2cb623cca372a2b42b073121c7413cdaaf75besewardj   UChar sign;
10890c2cb623cca372a2b42b073121c7413cdaaf75besewardj
10900c2cb623cca372a2b42b073121c7413cdaaf75besewardj   sign = (f64[7] >> 7) & 1;
10910c2cb623cca372a2b42b073121c7413cdaaf75besewardj   bexp = (f64[7] << 4) | ((f64[6] >> 4) & 0x0F);
10920c2cb623cca372a2b42b073121c7413cdaaf75besewardj   bexp &= 0x7FF;
10930c2cb623cca372a2b42b073121c7413cdaaf75besewardj
109414d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj   mantissaIsZero = False;
109514d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj   if (bexp == 0 || bexp == 0x7FF) {
109614d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj      /* We'll need to know whether or not the mantissa (bits 51:0) is
109714d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj         all zeroes in order to handle these cases.  So figure it
109814d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj         out. */
109914d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj      mantissaIsZero
110014d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj         = (f64[6] & 0x0F) == 0
110114d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj           && f64[5] == 0 && f64[4] == 0 && f64[3] == 0
110214d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj           && f64[2] == 0 && f64[1] == 0 && f64[0] == 0;
110314d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj   }
110414d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj
11050c2cb623cca372a2b42b073121c7413cdaaf75besewardj   /* If the exponent is zero, either we have a zero or a denormal.
11060c2cb623cca372a2b42b073121c7413cdaaf75besewardj      Produce a zero.  This is a hack in that it forces denormals to
11070c2cb623cca372a2b42b073121c7413cdaaf75besewardj      zero.  Could do better. */
11080c2cb623cca372a2b42b073121c7413cdaaf75besewardj   if (bexp == 0) {
11090c2cb623cca372a2b42b073121c7413cdaaf75besewardj      f80[9] = sign << 7;
11100c2cb623cca372a2b42b073121c7413cdaaf75besewardj      f80[8] = f80[7] = f80[6] = f80[5] = f80[4]
11110c2cb623cca372a2b42b073121c7413cdaaf75besewardj             = f80[3] = f80[2] = f80[1] = f80[0] = 0;
111214d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj
111314d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj      if (mantissaIsZero)
111414d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj         /* It really is zero, so that's all we can do. */
111514d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj         return;
111614d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj
111714d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj      /* There is at least one 1-bit in the mantissa.  So it's a
111814d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj         potentially denormalised double -- but we can produce a
111914d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj         normalised long double.  Count the leading zeroes in the
112014d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj         mantissa so as to decide how much to bump the exponent down
112114d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj         by.  Note, this is SLOW. */
112214d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj      shift = 0;
112314d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj      for (i = 51; i >= 0; i--) {
112414d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj        if (read_bit_array(f64, i))
112514d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj           break;
112614d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj        shift++;
112714d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj      }
112814d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj
112914d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj      /* and copy into place as many bits as we can get our hands on. */
113014d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj      j = 63;
113114d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj      for (i = 51 - shift; i >= 0; i--) {
113214d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj         write_bit_array( f80, j,
113314d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj     	 read_bit_array( f64, i ) );
113414d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj         j--;
113514d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj      }
113614d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj
113714d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj      /* Set the exponent appropriately, and we're done. */
113814d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj      bexp -= shift;
113914d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj      bexp += (16383 - 1023);
114014d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj      f80[9] = (sign << 7) | ((bexp >> 8) & 0xFF);
114114d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj      f80[8] = bexp & 0xFF;
11420c2cb623cca372a2b42b073121c7413cdaaf75besewardj      return;
11430c2cb623cca372a2b42b073121c7413cdaaf75besewardj   }
114414d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj
11450c2cb623cca372a2b42b073121c7413cdaaf75besewardj   /* If the exponent is 7FF, this is either an Infinity, a SNaN or
11460c2cb623cca372a2b42b073121c7413cdaaf75besewardj      QNaN, as determined by examining bits 51:0, thus:
11470c2cb623cca372a2b42b073121c7413cdaaf75besewardj          0  ... 0    Inf
11480c2cb623cca372a2b42b073121c7413cdaaf75besewardj          0X ... X    SNaN
11490c2cb623cca372a2b42b073121c7413cdaaf75besewardj          1X ... X    QNaN
11500c2cb623cca372a2b42b073121c7413cdaaf75besewardj      where at least one of the Xs is not zero.
11510c2cb623cca372a2b42b073121c7413cdaaf75besewardj   */
11520c2cb623cca372a2b42b073121c7413cdaaf75besewardj   if (bexp == 0x7FF) {
115314d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj      if (mantissaIsZero) {
11540c2cb623cca372a2b42b073121c7413cdaaf75besewardj         /* Produce an appropriately signed infinity:
11550c2cb623cca372a2b42b073121c7413cdaaf75besewardj            S 1--1 (15)  1  0--0 (63)
11560c2cb623cca372a2b42b073121c7413cdaaf75besewardj         */
11570c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f80[9] = (sign << 7) | 0x7F;
11580c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f80[8] = 0xFF;
11590c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f80[7] = 0x80;
11600c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f80[6] = f80[5] = f80[4] = f80[3]
11610c2cb623cca372a2b42b073121c7413cdaaf75besewardj                = f80[2] = f80[1] = f80[0] = 0;
11620c2cb623cca372a2b42b073121c7413cdaaf75besewardj         return;
11630c2cb623cca372a2b42b073121c7413cdaaf75besewardj      }
11640c2cb623cca372a2b42b073121c7413cdaaf75besewardj      /* So it's either a QNaN or SNaN.  Distinguish by considering
11650c2cb623cca372a2b42b073121c7413cdaaf75besewardj         bit 51.  Note, this destroys all the trailing bits
11660c2cb623cca372a2b42b073121c7413cdaaf75besewardj         (identity?) of the NaN.  IEEE754 doesn't require preserving
11670c2cb623cca372a2b42b073121c7413cdaaf75besewardj         these (it only requires that there be one QNaN value and one
11680c2cb623cca372a2b42b073121c7413cdaaf75besewardj         SNaN value), but x87 does seem to have some ability to
11690c2cb623cca372a2b42b073121c7413cdaaf75besewardj         preserve them.  Anyway, here, the NaN's identity is
11700c2cb623cca372a2b42b073121c7413cdaaf75besewardj         destroyed.  Could be improved. */
11710c2cb623cca372a2b42b073121c7413cdaaf75besewardj      if (f64[6] & 8) {
11720c2cb623cca372a2b42b073121c7413cdaaf75besewardj         /* QNaN.  Make a QNaN:
11730c2cb623cca372a2b42b073121c7413cdaaf75besewardj            S 1--1 (15)  1  1--1 (63)
11740c2cb623cca372a2b42b073121c7413cdaaf75besewardj         */
11750c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f80[9] = (sign << 7) | 0x7F;
11760c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f80[8] = 0xFF;
11770c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f80[7] = 0xFF;
11780c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f80[6] = f80[5] = f80[4] = f80[3]
11790c2cb623cca372a2b42b073121c7413cdaaf75besewardj                = f80[2] = f80[1] = f80[0] = 0xFF;
11800c2cb623cca372a2b42b073121c7413cdaaf75besewardj      } else {
11810c2cb623cca372a2b42b073121c7413cdaaf75besewardj         /* SNaN.  Make a SNaN:
11820c2cb623cca372a2b42b073121c7413cdaaf75besewardj            S 1--1 (15)  0  1--1 (63)
11830c2cb623cca372a2b42b073121c7413cdaaf75besewardj         */
11840c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f80[9] = (sign << 7) | 0x7F;
11850c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f80[8] = 0xFF;
11860c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f80[7] = 0x7F;
11870c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f80[6] = f80[5] = f80[4] = f80[3]
11880c2cb623cca372a2b42b073121c7413cdaaf75besewardj                = f80[2] = f80[1] = f80[0] = 0xFF;
11890c2cb623cca372a2b42b073121c7413cdaaf75besewardj      }
11900c2cb623cca372a2b42b073121c7413cdaaf75besewardj      return;
11910c2cb623cca372a2b42b073121c7413cdaaf75besewardj   }
11920c2cb623cca372a2b42b073121c7413cdaaf75besewardj
11930c2cb623cca372a2b42b073121c7413cdaaf75besewardj   /* It's not a zero, denormal, infinity or nan.  So it must be a
11940c2cb623cca372a2b42b073121c7413cdaaf75besewardj      normalised number.  Rebias the exponent and build the new
11950c2cb623cca372a2b42b073121c7413cdaaf75besewardj      number.  */
11960c2cb623cca372a2b42b073121c7413cdaaf75besewardj   bexp += (16383 - 1023);
11970c2cb623cca372a2b42b073121c7413cdaaf75besewardj
11980c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f80[9] = (sign << 7) | ((bexp >> 8) & 0xFF);
11990c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f80[8] = bexp & 0xFF;
12000c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f80[7] = (1 << 7) | ((f64[6] << 3) & 0x78) | ((f64[5] >> 5) & 7);
12010c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f80[6] = ((f64[5] << 3) & 0xF8) | ((f64[4] >> 5) & 7);
12020c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f80[5] = ((f64[4] << 3) & 0xF8) | ((f64[3] >> 5) & 7);
12030c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f80[4] = ((f64[3] << 3) & 0xF8) | ((f64[2] >> 5) & 7);
12040c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f80[3] = ((f64[2] << 3) & 0xF8) | ((f64[1] >> 5) & 7);
12050c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f80[2] = ((f64[1] << 3) & 0xF8) | ((f64[0] >> 5) & 7);
12060c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f80[1] = ((f64[0] << 3) & 0xF8);
12070c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f80[0] = 0;
12080c2cb623cca372a2b42b073121c7413cdaaf75besewardj}
12090c2cb623cca372a2b42b073121c7413cdaaf75besewardj
12100c2cb623cca372a2b42b073121c7413cdaaf75besewardj
12110c2cb623cca372a2b42b073121c7413cdaaf75besewardj/////////////////////////////////////////////////////////////////
12120c2cb623cca372a2b42b073121c7413cdaaf75besewardj
12130c2cb623cca372a2b42b073121c7413cdaaf75besewardj/* Convert a x87 extended double (80-bit) into an IEEE 754 double
121414d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj   (64-bit), mimicking the hardware fairly closely.  Both numbers are
121514d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj   stored little-endian.  Limitations, both of which could be fixed,
12160c2cb623cca372a2b42b073121c7413cdaaf75besewardj   given some level of hassle:
12170c2cb623cca372a2b42b073121c7413cdaaf75besewardj
12180c2cb623cca372a2b42b073121c7413cdaaf75besewardj   * Rounding following truncation could be a bit better.
12190c2cb623cca372a2b42b073121c7413cdaaf75besewardj
12200c2cb623cca372a2b42b073121c7413cdaaf75besewardj   * Identity of NaNs is not preserved.
12210c2cb623cca372a2b42b073121c7413cdaaf75besewardj
122214d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj   See comments in the code for more details.
12230c2cb623cca372a2b42b073121c7413cdaaf75besewardj*/
12240c2cb623cca372a2b42b073121c7413cdaaf75besewardjstatic void convert_f80le_to_f64le ( /*IN*/UChar* f80, /*OUT*/UChar* f64 )
12250c2cb623cca372a2b42b073121c7413cdaaf75besewardj{
12260c2cb623cca372a2b42b073121c7413cdaaf75besewardj   Bool  isInf;
122714d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj   Int   bexp, i, j;
12280c2cb623cca372a2b42b073121c7413cdaaf75besewardj   UChar sign;
12290c2cb623cca372a2b42b073121c7413cdaaf75besewardj
12300c2cb623cca372a2b42b073121c7413cdaaf75besewardj   sign = (f80[9] >> 7) & 1;
12310c2cb623cca372a2b42b073121c7413cdaaf75besewardj   bexp = (((UInt)f80[9]) << 8) | (UInt)f80[8];
12320c2cb623cca372a2b42b073121c7413cdaaf75besewardj   bexp &= 0x7FFF;
12330c2cb623cca372a2b42b073121c7413cdaaf75besewardj
12340c2cb623cca372a2b42b073121c7413cdaaf75besewardj   /* If the exponent is zero, either we have a zero or a denormal.
12350c2cb623cca372a2b42b073121c7413cdaaf75besewardj      But an extended precision denormal becomes a double precision
12360c2cb623cca372a2b42b073121c7413cdaaf75besewardj      zero, so in either case, just produce the appropriately signed
12370c2cb623cca372a2b42b073121c7413cdaaf75besewardj      zero. */
12380c2cb623cca372a2b42b073121c7413cdaaf75besewardj   if (bexp == 0) {
12390c2cb623cca372a2b42b073121c7413cdaaf75besewardj      f64[7] = sign << 7;
12400c2cb623cca372a2b42b073121c7413cdaaf75besewardj      f64[6] = f64[5] = f64[4] = f64[3] = f64[2] = f64[1] = f64[0] = 0;
12410c2cb623cca372a2b42b073121c7413cdaaf75besewardj      return;
12420c2cb623cca372a2b42b073121c7413cdaaf75besewardj   }
12430c2cb623cca372a2b42b073121c7413cdaaf75besewardj
12440c2cb623cca372a2b42b073121c7413cdaaf75besewardj   /* If the exponent is 7FFF, this is either an Infinity, a SNaN or
12450c2cb623cca372a2b42b073121c7413cdaaf75besewardj      QNaN, as determined by examining bits 62:0, thus:
12460c2cb623cca372a2b42b073121c7413cdaaf75besewardj          0  ... 0    Inf
12470c2cb623cca372a2b42b073121c7413cdaaf75besewardj          0X ... X    SNaN
12480c2cb623cca372a2b42b073121c7413cdaaf75besewardj          1X ... X    QNaN
12490c2cb623cca372a2b42b073121c7413cdaaf75besewardj      where at least one of the Xs is not zero.
12500c2cb623cca372a2b42b073121c7413cdaaf75besewardj   */
12510c2cb623cca372a2b42b073121c7413cdaaf75besewardj   if (bexp == 0x7FFF) {
12520c2cb623cca372a2b42b073121c7413cdaaf75besewardj      isInf = (f80[7] & 0x7F) == 0
12530c2cb623cca372a2b42b073121c7413cdaaf75besewardj              && f80[6] == 0 && f80[5] == 0 && f80[4] == 0
12540c2cb623cca372a2b42b073121c7413cdaaf75besewardj              && f80[3] == 0 && f80[2] == 0 && f80[1] == 0 && f80[0] == 0;
12550c2cb623cca372a2b42b073121c7413cdaaf75besewardj      if (isInf) {
12560c2cb623cca372a2b42b073121c7413cdaaf75besewardj         if (0 == (f80[7] & 0x80))
12570c2cb623cca372a2b42b073121c7413cdaaf75besewardj            goto wierd_NaN;
12580c2cb623cca372a2b42b073121c7413cdaaf75besewardj         /* Produce an appropriately signed infinity:
12590c2cb623cca372a2b42b073121c7413cdaaf75besewardj            S 1--1 (11)  0--0 (52)
12600c2cb623cca372a2b42b073121c7413cdaaf75besewardj         */
12610c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f64[7] = (sign << 7) | 0x7F;
12620c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f64[6] = 0xF0;
12630c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f64[5] = f64[4] = f64[3] = f64[2] = f64[1] = f64[0] = 0;
12640c2cb623cca372a2b42b073121c7413cdaaf75besewardj         return;
12650c2cb623cca372a2b42b073121c7413cdaaf75besewardj      }
12660c2cb623cca372a2b42b073121c7413cdaaf75besewardj      /* So it's either a QNaN or SNaN.  Distinguish by considering
12670c2cb623cca372a2b42b073121c7413cdaaf75besewardj         bit 62.  Note, this destroys all the trailing bits
12680c2cb623cca372a2b42b073121c7413cdaaf75besewardj         (identity?) of the NaN.  IEEE754 doesn't require preserving
12690c2cb623cca372a2b42b073121c7413cdaaf75besewardj         these (it only requires that there be one QNaN value and one
12700c2cb623cca372a2b42b073121c7413cdaaf75besewardj         SNaN value), but x87 does seem to have some ability to
12710c2cb623cca372a2b42b073121c7413cdaaf75besewardj         preserve them.  Anyway, here, the NaN's identity is
12720c2cb623cca372a2b42b073121c7413cdaaf75besewardj         destroyed.  Could be improved. */
12730c2cb623cca372a2b42b073121c7413cdaaf75besewardj      if (f80[8] & 0x40) {
12740c2cb623cca372a2b42b073121c7413cdaaf75besewardj         /* QNaN.  Make a QNaN:
12750c2cb623cca372a2b42b073121c7413cdaaf75besewardj            S 1--1 (11)  1  1--1 (51)
12760c2cb623cca372a2b42b073121c7413cdaaf75besewardj         */
12770c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f64[7] = (sign << 7) | 0x7F;
12780c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f64[6] = 0xFF;
12790c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f64[5] = f64[4] = f64[3] = f64[2] = f64[1] = f64[0] = 0xFF;
12800c2cb623cca372a2b42b073121c7413cdaaf75besewardj      } else {
12810c2cb623cca372a2b42b073121c7413cdaaf75besewardj         /* SNaN.  Make a SNaN:
12820c2cb623cca372a2b42b073121c7413cdaaf75besewardj            S 1--1 (11)  0  1--1 (51)
12830c2cb623cca372a2b42b073121c7413cdaaf75besewardj         */
12840c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f64[7] = (sign << 7) | 0x7F;
12850c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f64[6] = 0xF7;
12860c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f64[5] = f64[4] = f64[3] = f64[2] = f64[1] = f64[0] = 0xFF;
12870c2cb623cca372a2b42b073121c7413cdaaf75besewardj      }
12880c2cb623cca372a2b42b073121c7413cdaaf75besewardj      return;
12890c2cb623cca372a2b42b073121c7413cdaaf75besewardj   }
12900c2cb623cca372a2b42b073121c7413cdaaf75besewardj
12910c2cb623cca372a2b42b073121c7413cdaaf75besewardj   /* If it's not a Zero, NaN or Inf, and the integer part (bit 62) is
12920c2cb623cca372a2b42b073121c7413cdaaf75besewardj      zero, the x87 FPU appears to consider the number denormalised
12930c2cb623cca372a2b42b073121c7413cdaaf75besewardj      and converts it to a QNaN. */
12940c2cb623cca372a2b42b073121c7413cdaaf75besewardj   if (0 == (f80[7] & 0x80)) {
12950c2cb623cca372a2b42b073121c7413cdaaf75besewardj      wierd_NaN:
12960c2cb623cca372a2b42b073121c7413cdaaf75besewardj      /* Strange hardware QNaN:
12970c2cb623cca372a2b42b073121c7413cdaaf75besewardj         S 1--1 (11)  1  0--0 (51)
12980c2cb623cca372a2b42b073121c7413cdaaf75besewardj      */
12990c2cb623cca372a2b42b073121c7413cdaaf75besewardj      /* On a PIII, these QNaNs always appear with sign==1.  I have
13000c2cb623cca372a2b42b073121c7413cdaaf75besewardj         no idea why. */
13010c2cb623cca372a2b42b073121c7413cdaaf75besewardj      f64[7] = (1 /*sign*/ << 7) | 0x7F;
13020c2cb623cca372a2b42b073121c7413cdaaf75besewardj      f64[6] = 0xF8;
13030c2cb623cca372a2b42b073121c7413cdaaf75besewardj      f64[5] = f64[4] = f64[3] = f64[2] = f64[1] = f64[0] = 0;
13040c2cb623cca372a2b42b073121c7413cdaaf75besewardj      return;
13050c2cb623cca372a2b42b073121c7413cdaaf75besewardj   }
13060c2cb623cca372a2b42b073121c7413cdaaf75besewardj
13070c2cb623cca372a2b42b073121c7413cdaaf75besewardj   /* It's not a zero, denormal, infinity or nan.  So it must be a
13080c2cb623cca372a2b42b073121c7413cdaaf75besewardj      normalised number.  Rebias the exponent and consider. */
13090c2cb623cca372a2b42b073121c7413cdaaf75besewardj   bexp -= (16383 - 1023);
13100c2cb623cca372a2b42b073121c7413cdaaf75besewardj   if (bexp >= 0x7FF) {
13110c2cb623cca372a2b42b073121c7413cdaaf75besewardj      /* It's too big for a double.  Construct an infinity. */
13120c2cb623cca372a2b42b073121c7413cdaaf75besewardj      f64[7] = (sign << 7) | 0x7F;
13130c2cb623cca372a2b42b073121c7413cdaaf75besewardj      f64[6] = 0xF0;
13140c2cb623cca372a2b42b073121c7413cdaaf75besewardj      f64[5] = f64[4] = f64[3] = f64[2] = f64[1] = f64[0] = 0;
13150c2cb623cca372a2b42b073121c7413cdaaf75besewardj      return;
13160c2cb623cca372a2b42b073121c7413cdaaf75besewardj   }
13170c2cb623cca372a2b42b073121c7413cdaaf75besewardj
131814d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj   if (bexp <= 0) {
131914d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj      /* It's too small for a normalised double.  First construct a
132014d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj         zero and then see if it can be improved into a denormal.  */
13210c2cb623cca372a2b42b073121c7413cdaaf75besewardj      f64[7] = sign << 7;
13220c2cb623cca372a2b42b073121c7413cdaaf75besewardj      f64[6] = f64[5] = f64[4] = f64[3] = f64[2] = f64[1] = f64[0] = 0;
132314d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj
132414d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj      if (bexp < -52)
132514d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj         /* Too small even for a denormal. */
132614d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj         return;
132714d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj
132814d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj      /* Ok, let's make a denormal.  Note, this is SLOW. */
132914d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj      /* Copy bits 63, 62, 61, etc of the src mantissa into the dst,
133014d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj         indexes 52+bexp, 51+bexp, etc, until k+bexp < 0. */
133114d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj      /* bexp is in range -52 .. 0 inclusive */
133214d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj      for (i = 63; i >= 0; i--) {
133314d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj         j = i - 12 + bexp;
133414d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj         if (j < 0) break;
133514d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj         /* We shouldn't really call vassert from generated code. */
133614d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj         vassert(j >= 0 && j < 52);
133714d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj         write_bit_array ( f64,
133814d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj                           j,
133914d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj                           read_bit_array ( f80, i ) );
134014d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj      }
134114d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj      /* and now we might have to round ... */
134214d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj      if (read_bit_array(f80, 10+1 - bexp) == 1)
134314d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj         goto do_rounding;
134414d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj
13450c2cb623cca372a2b42b073121c7413cdaaf75besewardj      return;
13460c2cb623cca372a2b42b073121c7413cdaaf75besewardj   }
13470c2cb623cca372a2b42b073121c7413cdaaf75besewardj
13480c2cb623cca372a2b42b073121c7413cdaaf75besewardj   /* Ok, it's a normalised number which is representable as a double.
13490c2cb623cca372a2b42b073121c7413cdaaf75besewardj      Copy the exponent and mantissa into place. */
13500c2cb623cca372a2b42b073121c7413cdaaf75besewardj   /*
13510c2cb623cca372a2b42b073121c7413cdaaf75besewardj   for (i = 0; i < 52; i++)
13520c2cb623cca372a2b42b073121c7413cdaaf75besewardj      write_bit_array ( f64,
13530c2cb623cca372a2b42b073121c7413cdaaf75besewardj                        i,
13540c2cb623cca372a2b42b073121c7413cdaaf75besewardj                        read_bit_array ( f80, i+11 ) );
13550c2cb623cca372a2b42b073121c7413cdaaf75besewardj   */
13560c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f64[0] = (f80[1] >> 3) | (f80[2] << 5);
13570c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f64[1] = (f80[2] >> 3) | (f80[3] << 5);
13580c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f64[2] = (f80[3] >> 3) | (f80[4] << 5);
13590c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f64[3] = (f80[4] >> 3) | (f80[5] << 5);
13600c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f64[4] = (f80[5] >> 3) | (f80[6] << 5);
13610c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f64[5] = (f80[6] >> 3) | (f80[7] << 5);
13620c2cb623cca372a2b42b073121c7413cdaaf75besewardj
13630c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f64[6] = ((bexp << 4) & 0xF0) | ((f80[7] >> 3) & 0x0F);
13640c2cb623cca372a2b42b073121c7413cdaaf75besewardj
13650c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f64[7] = (sign << 7) | ((bexp >> 4) & 0x7F);
13660c2cb623cca372a2b42b073121c7413cdaaf75besewardj
13670c2cb623cca372a2b42b073121c7413cdaaf75besewardj   /* Now consider any rounding that needs to happen as a result of
13680c2cb623cca372a2b42b073121c7413cdaaf75besewardj      truncating the mantissa. */
13690c2cb623cca372a2b42b073121c7413cdaaf75besewardj   if (f80[1] & 4) /* read_bit_array(f80, 10) == 1) */ {
137014d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj
137114d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj      /* If the bottom bits of f80 are "100 0000 0000", then the
137214d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj         infinitely precise value is deemed to be mid-way between the
137314d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj         two closest representable values.  Since we're doing
137414d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj         round-to-nearest (the default mode), in that case it is the
137514d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj         bit immediately above which indicates whether we should round
137614d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj         upwards or not -- if 0, we don't.  All that is encapsulated
137714d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj         in the following simple test. */
137814d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj      if ((f80[1] & 0xF) == 4/*0100b*/ && f80[0] == 0)
137914d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj         return;
138014d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj
138114d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj      do_rounding:
138214d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj      /* Round upwards.  This is a kludge.  Once in every 2^24
138314d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj         roundings (statistically) the bottom three bytes are all 0xFF
13840c2cb623cca372a2b42b073121c7413cdaaf75besewardj         and so we don't round at all.  Could be improved. */
13850c2cb623cca372a2b42b073121c7413cdaaf75besewardj      if (f64[0] != 0xFF) {
13860c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f64[0]++;
13870c2cb623cca372a2b42b073121c7413cdaaf75besewardj      }
13880c2cb623cca372a2b42b073121c7413cdaaf75besewardj      else
13890c2cb623cca372a2b42b073121c7413cdaaf75besewardj      if (f64[0] == 0xFF && f64[1] != 0xFF) {
13900c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f64[0] = 0;
13910c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f64[1]++;
13920c2cb623cca372a2b42b073121c7413cdaaf75besewardj      }
139314d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj      else
139414d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj      if (f64[0] == 0xFF && f64[1] == 0xFF && f64[2] != 0xFF) {
139514d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj         f64[0] = 0;
139614d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj         f64[1] = 0;
139714d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj         f64[2]++;
139814d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj      }
13990c2cb623cca372a2b42b073121c7413cdaaf75besewardj      /* else we don't round, but we should. */
14000c2cb623cca372a2b42b073121c7413cdaaf75besewardj   }
14010c2cb623cca372a2b42b073121c7413cdaaf75besewardj}
14020c2cb623cca372a2b42b073121c7413cdaaf75besewardj
140314d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj
140417442fe8094d0f82266e5a05509f62cac8f7539esewardj/* CALLED FROM GENERATED CODE */
140517442fe8094d0f82266e5a05509f62cac8f7539esewardj/* DIRTY HELPER (reads guest memory) */
14062a9ad023890d3b34cf45e429df2a8ae88b419128sewardjULong x86g_loadF80le ( UInt addrU )
140717442fe8094d0f82266e5a05509f62cac8f7539esewardj{
140817442fe8094d0f82266e5a05509f62cac8f7539esewardj   ULong f64;
140917442fe8094d0f82266e5a05509f62cac8f7539esewardj   convert_f80le_to_f64le ( (UChar*)addrU, (UChar*)&f64 );
141017442fe8094d0f82266e5a05509f62cac8f7539esewardj   return f64;
141117442fe8094d0f82266e5a05509f62cac8f7539esewardj}
141217442fe8094d0f82266e5a05509f62cac8f7539esewardj
141317442fe8094d0f82266e5a05509f62cac8f7539esewardj/* CALLED FROM GENERATED CODE */
141417442fe8094d0f82266e5a05509f62cac8f7539esewardj/* DIRTY HELPER (writes guest memory) */
14152a9ad023890d3b34cf45e429df2a8ae88b419128sewardjvoid x86g_storeF80le ( UInt addrU, ULong f64 )
141617442fe8094d0f82266e5a05509f62cac8f7539esewardj{
141717442fe8094d0f82266e5a05509f62cac8f7539esewardj   convert_f64le_to_f80le( (UChar*)&f64, (UChar*)addrU );
141817442fe8094d0f82266e5a05509f62cac8f7539esewardj}
141917442fe8094d0f82266e5a05509f62cac8f7539esewardj
14200c2cb623cca372a2b42b073121c7413cdaaf75besewardj
14210c2cb623cca372a2b42b073121c7413cdaaf75besewardj/*----------------------------------------------*/
14220c2cb623cca372a2b42b073121c7413cdaaf75besewardj/*--- The exported fns ..                    ---*/
14230c2cb623cca372a2b42b073121c7413cdaaf75besewardj/*----------------------------------------------*/
14240c2cb623cca372a2b42b073121c7413cdaaf75besewardj
14250c2cb623cca372a2b42b073121c7413cdaaf75besewardj/* Layout of the real x87 state. */
14260c2cb623cca372a2b42b073121c7413cdaaf75besewardj
14270c2cb623cca372a2b42b073121c7413cdaaf75besewardjtypedef
14280c2cb623cca372a2b42b073121c7413cdaaf75besewardj   struct {
14290c2cb623cca372a2b42b073121c7413cdaaf75besewardj      UShort env[14];
14300c2cb623cca372a2b42b073121c7413cdaaf75besewardj      UChar  reg[80];
14310c2cb623cca372a2b42b073121c7413cdaaf75besewardj   }
14320c2cb623cca372a2b42b073121c7413cdaaf75besewardj   Fpu_State;
14330c2cb623cca372a2b42b073121c7413cdaaf75besewardj
14340c2cb623cca372a2b42b073121c7413cdaaf75besewardj/* Offsets, in 16-bit ints, into the FPU environment (env) area. */
14350c2cb623cca372a2b42b073121c7413cdaaf75besewardj#define FP_ENV_CTRL   0
14360c2cb623cca372a2b42b073121c7413cdaaf75besewardj#define FP_ENV_STAT   2
14370c2cb623cca372a2b42b073121c7413cdaaf75besewardj#define FP_ENV_TAG    4
14380c2cb623cca372a2b42b073121c7413cdaaf75besewardj#define FP_ENV_IP     6 /* and 7 */
14390c2cb623cca372a2b42b073121c7413cdaaf75besewardj#define FP_ENV_CS     8
14400c2cb623cca372a2b42b073121c7413cdaaf75besewardj#define FP_ENV_OPOFF  10 /* and 11 */
14410c2cb623cca372a2b42b073121c7413cdaaf75besewardj#define FP_ENV_OPSEL  12
14420c2cb623cca372a2b42b073121c7413cdaaf75besewardj#define FP_REG(ii)    (10*(7-(ii)))
14430c2cb623cca372a2b42b073121c7413cdaaf75besewardj
14440c2cb623cca372a2b42b073121c7413cdaaf75besewardj
14457df596b1e36840e2d74c90aa55589934add61ccfsewardj/* CLEAN HELPER */
1446a0e83b06f304527e3e9aec527c344e35e7023d76sewardj/* fpucw[15:0] contains a x87 native format FPU control word.
1447d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj   Extract from it the required FPROUND value and any resulting
1448d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj   emulation warning, and return (warn << 32) | fpround value.
1449d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj*/
14503bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardjULong x86g_check_fldcw ( UInt fpucw )
1451893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj{
1452d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj   /* Decide on a rounding mode.  fpucw[11:10] holds it. */
1453d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj   /* NOTE, encoded exactly as per enum IRRoundingMode. */
1454893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj   UInt rmode = (fpucw >> 10) & 3;
1455893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj
1456893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj   /* Detect any required emulation warnings. */
1457893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj   VexEmWarn ew = EmWarn_NONE;
1458893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj
1459893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj   if ((fpucw & 0x3F) != 0x3F) {
1460893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj      /* unmasked exceptions! */
1461893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj      ew = EmWarn_X86_x87exns;
1462893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj   }
1463893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj   else
1464893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj   if (((fpucw >> 8) & 3) != 3) {
1465893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj      /* unsupported precision */
1466893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj      ew = EmWarn_X86_x87precision;
1467893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj   }
1468893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj
1469d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj   return (((ULong)ew) << 32) | ((ULong)rmode);
1470893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj}
1471893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj
1472893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj/* CLEAN HELPER */
14737df596b1e36840e2d74c90aa55589934add61ccfsewardj/* Given fpround as an IRRoundingMode value, create a suitable x87
14747df596b1e36840e2d74c90aa55589934add61ccfsewardj   native format FPU control word. */
14753bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardjUInt x86g_create_fpucw ( UInt fpround )
1476893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj{
1477d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj   fpround &= 3;
1478d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj   return 0x037F | (fpround << 10);
1479893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj}
1480893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj
1481893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj
14827df596b1e36840e2d74c90aa55589934add61ccfsewardj/* CLEAN HELPER */
1483a0e83b06f304527e3e9aec527c344e35e7023d76sewardj/* mxcsr[15:0] contains a SSE native format MXCSR value.
14847df596b1e36840e2d74c90aa55589934add61ccfsewardj   Extract from it the required SSEROUND value and any resulting
14857df596b1e36840e2d74c90aa55589934add61ccfsewardj   emulation warning, and return (warn << 32) | sseround value.
14867df596b1e36840e2d74c90aa55589934add61ccfsewardj*/
14873bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardjULong x86g_check_ldmxcsr ( UInt mxcsr )
14887df596b1e36840e2d74c90aa55589934add61ccfsewardj{
14897df596b1e36840e2d74c90aa55589934add61ccfsewardj   /* Decide on a rounding mode.  mxcsr[14:13] holds it. */
14907df596b1e36840e2d74c90aa55589934add61ccfsewardj   /* NOTE, encoded exactly as per enum IRRoundingMode. */
14917df596b1e36840e2d74c90aa55589934add61ccfsewardj   UInt rmode = (mxcsr >> 13) & 3;
14927df596b1e36840e2d74c90aa55589934add61ccfsewardj
14937df596b1e36840e2d74c90aa55589934add61ccfsewardj   /* Detect any required emulation warnings. */
14947df596b1e36840e2d74c90aa55589934add61ccfsewardj   VexEmWarn ew = EmWarn_NONE;
14957df596b1e36840e2d74c90aa55589934add61ccfsewardj
14967df596b1e36840e2d74c90aa55589934add61ccfsewardj   if ((mxcsr & 0x1F80) != 0x1F80) {
14977df596b1e36840e2d74c90aa55589934add61ccfsewardj      /* unmasked exceptions! */
14987df596b1e36840e2d74c90aa55589934add61ccfsewardj      ew = EmWarn_X86_sseExns;
14997df596b1e36840e2d74c90aa55589934add61ccfsewardj   }
15007df596b1e36840e2d74c90aa55589934add61ccfsewardj   else
15015edfc26d72ca8ebea2aa0443a1ed4dd218343d04sewardj   if (mxcsr & (1<<15)) {
15025edfc26d72ca8ebea2aa0443a1ed4dd218343d04sewardj      /* FZ is set */
15035edfc26d72ca8ebea2aa0443a1ed4dd218343d04sewardj      ew = EmWarn_X86_fz;
15045edfc26d72ca8ebea2aa0443a1ed4dd218343d04sewardj   }
15055edfc26d72ca8ebea2aa0443a1ed4dd218343d04sewardj   else
15065edfc26d72ca8ebea2aa0443a1ed4dd218343d04sewardj   if (mxcsr & (1<<6)) {
15075edfc26d72ca8ebea2aa0443a1ed4dd218343d04sewardj      /* DAZ is set */
15085edfc26d72ca8ebea2aa0443a1ed4dd218343d04sewardj      ew = EmWarn_X86_daz;
15097df596b1e36840e2d74c90aa55589934add61ccfsewardj   }
15107df596b1e36840e2d74c90aa55589934add61ccfsewardj
15117df596b1e36840e2d74c90aa55589934add61ccfsewardj   return (((ULong)ew) << 32) | ((ULong)rmode);
15127df596b1e36840e2d74c90aa55589934add61ccfsewardj}
15137df596b1e36840e2d74c90aa55589934add61ccfsewardj
15147df596b1e36840e2d74c90aa55589934add61ccfsewardj
15157df596b1e36840e2d74c90aa55589934add61ccfsewardj/* CLEAN HELPER */
15167df596b1e36840e2d74c90aa55589934add61ccfsewardj/* Given sseround as an IRRoundingMode value, create a suitable SSE
15177df596b1e36840e2d74c90aa55589934add61ccfsewardj   native format MXCSR value. */
15183bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardjUInt x86g_create_mxcsr ( UInt sseround )
15197df596b1e36840e2d74c90aa55589934add61ccfsewardj{
15207df596b1e36840e2d74c90aa55589934add61ccfsewardj   sseround &= 3;
15217df596b1e36840e2d74c90aa55589934add61ccfsewardj   return 0x1F80 | (sseround << 13);
15227df596b1e36840e2d74c90aa55589934add61ccfsewardj}
15237df596b1e36840e2d74c90aa55589934add61ccfsewardj
15247df596b1e36840e2d74c90aa55589934add61ccfsewardj
1525a0e83b06f304527e3e9aec527c344e35e7023d76sewardj/* CALLED FROM GENERATED CODE */
1526a0e83b06f304527e3e9aec527c344e35e7023d76sewardj/* DIRTY HELPER (writes guest state) */
1527a0e83b06f304527e3e9aec527c344e35e7023d76sewardj/* Initialise the x87 FPU state as per 'finit'. */
1528a0e83b06f304527e3e9aec527c344e35e7023d76sewardjvoid x86g_dirtyhelper_FINIT ( VexGuestX86State* gst )
1529a0e83b06f304527e3e9aec527c344e35e7023d76sewardj{
1530a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   Int i;
1531a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   gst->guest_FTOP = 0;
1532a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   for (i = 0; i < 8; i++) {
1533a0e83b06f304527e3e9aec527c344e35e7023d76sewardj      gst->guest_FPTAG[i] = 0; /* empty */
1534a0e83b06f304527e3e9aec527c344e35e7023d76sewardj      gst->guest_FPREG[i] = 0; /* IEEE754 64-bit zero */
1535a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   }
1536a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   gst->guest_FPROUND = (UInt)Irrm_NEAREST;
1537a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   gst->guest_FC3210  = 0;
1538a0e83b06f304527e3e9aec527c344e35e7023d76sewardj}
1539a0e83b06f304527e3e9aec527c344e35e7023d76sewardj
1540a0e83b06f304527e3e9aec527c344e35e7023d76sewardj
15417df596b1e36840e2d74c90aa55589934add61ccfsewardj/* This is used to implement both 'frstor' and 'fldenv'.  The latter
15427df596b1e36840e2d74c90aa55589934add61ccfsewardj   appears to differ from the former only in that the 8 FP registers
15437df596b1e36840e2d74c90aa55589934add61ccfsewardj   themselves are not transferred into the guest state. */
15447df596b1e36840e2d74c90aa55589934add61ccfsewardjstatic
154538a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjVexEmWarn do_put_x87 ( Bool moveRegs,
154638a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj                       /*IN*/UChar* x87_state,
154738a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj                       /*OUT*/VexGuestX86State* vex_state )
15480c2cb623cca372a2b42b073121c7413cdaaf75besewardj{
1549a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   Int        stno, preg;
15500c2cb623cca372a2b42b073121c7413cdaaf75besewardj   UInt       tag;
1551f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj   Double*    vexRegs = (Double*)(&vex_state->guest_FPREG[0]);
1552f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj   UChar*     vexTags = (UChar*)(&vex_state->guest_FPTAG[0]);
15530c2cb623cca372a2b42b073121c7413cdaaf75besewardj   Fpu_State* x87     = (Fpu_State*)x87_state;
15540c2cb623cca372a2b42b073121c7413cdaaf75besewardj   UInt       ftop    = (x87->env[FP_ENV_STAT] >> 11) & 7;
15550c2cb623cca372a2b42b073121c7413cdaaf75besewardj   UInt       tagw    = x87->env[FP_ENV_TAG];
15566e0dbda4f7ea53dd29996d4d429d3c5c92ee3640sewardj   UInt       fpucw   = x87->env[FP_ENV_CTRL];
1557c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   UInt       c3210   = x87->env[FP_ENV_STAT] & 0x4700;
1558893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj   VexEmWarn  ew;
1559d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj   UInt       fpround;
1560893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj   ULong      pair;
15610c2cb623cca372a2b42b073121c7413cdaaf75besewardj
15620c2cb623cca372a2b42b073121c7413cdaaf75besewardj   /* Copy registers and tags */
1563a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   for (stno = 0; stno < 8; stno++) {
1564a0e83b06f304527e3e9aec527c344e35e7023d76sewardj      preg = (stno + ftop) & 7;
1565a0e83b06f304527e3e9aec527c344e35e7023d76sewardj      tag = (tagw >> (2*preg)) & 3;
15660c2cb623cca372a2b42b073121c7413cdaaf75besewardj      if (tag == 3) {
15670c2cb623cca372a2b42b073121c7413cdaaf75besewardj         /* register is empty */
1568a0e83b06f304527e3e9aec527c344e35e7023d76sewardj         /* hmm, if it's empty, does it still get written?  Probably
1569a0e83b06f304527e3e9aec527c344e35e7023d76sewardj            safer to say it does.  If we don't, memcheck could get out
1570a0e83b06f304527e3e9aec527c344e35e7023d76sewardj            of sync, in that it thinks all FP registers are defined by
1571a0e83b06f304527e3e9aec527c344e35e7023d76sewardj            this helper, but in reality some have not been updated. */
1572a0e83b06f304527e3e9aec527c344e35e7023d76sewardj         if (True || moveRegs)
1573a0e83b06f304527e3e9aec527c344e35e7023d76sewardj            vexRegs[preg] = 0.0;
1574a0e83b06f304527e3e9aec527c344e35e7023d76sewardj         vexTags[preg] = 0;
15750c2cb623cca372a2b42b073121c7413cdaaf75besewardj      } else {
15760c2cb623cca372a2b42b073121c7413cdaaf75besewardj         /* register is non-empty */
15777df596b1e36840e2d74c90aa55589934add61ccfsewardj         if (moveRegs)
1578a0e83b06f304527e3e9aec527c344e35e7023d76sewardj            convert_f80le_to_f64le( &x87->reg[10*stno],
1579a0e83b06f304527e3e9aec527c344e35e7023d76sewardj                                    (UChar*)&vexRegs[preg] );
1580a0e83b06f304527e3e9aec527c344e35e7023d76sewardj         vexTags[preg] = 1;
15810c2cb623cca372a2b42b073121c7413cdaaf75besewardj      }
15820c2cb623cca372a2b42b073121c7413cdaaf75besewardj   }
15830c2cb623cca372a2b42b073121c7413cdaaf75besewardj
15840c2cb623cca372a2b42b073121c7413cdaaf75besewardj   /* stack pointer */
1585f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj   vex_state->guest_FTOP = ftop;
15860c2cb623cca372a2b42b073121c7413cdaaf75besewardj
15873f868e5262a8d2488f41cc49058ba60c24843c3esewardj   /* status word */
1588f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj   vex_state->guest_FC3210 = c3210;
1589893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj
1590d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj   /* handle the control word, setting FPROUND and detecting any
1591893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj      emulation warnings. */
15923bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   pair    = x86g_check_fldcw ( (UInt)fpucw );
1593d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj   fpround = (UInt)pair;
1594d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj   ew      = (VexEmWarn)(pair >> 32);
1595893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj
1596d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj   vex_state->guest_FPROUND = fpround & 3;
1597893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj
1598893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj   /* emulation warnings --> caller */
1599893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj   return ew;
16000c2cb623cca372a2b42b073121c7413cdaaf75besewardj}
16010c2cb623cca372a2b42b073121c7413cdaaf75besewardj
16026e0dbda4f7ea53dd29996d4d429d3c5c92ee3640sewardj
1603a0e83b06f304527e3e9aec527c344e35e7023d76sewardj/* Create an x87 FPU state from the guest state, as close as
1604a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   we can approximate it. */
160538a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic
160638a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjvoid do_get_x87 ( /*IN*/VexGuestX86State* vex_state,
160738a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj                  /*OUT*/UChar* x87_state )
16080c2cb623cca372a2b42b073121c7413cdaaf75besewardj{
1609a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   Int        i, stno, preg;
16100c2cb623cca372a2b42b073121c7413cdaaf75besewardj   UInt       tagw;
1611f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj   Double*    vexRegs = (Double*)(&vex_state->guest_FPREG[0]);
1612f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj   UChar*     vexTags = (UChar*)(&vex_state->guest_FPTAG[0]);
16130c2cb623cca372a2b42b073121c7413cdaaf75besewardj   Fpu_State* x87     = (Fpu_State*)x87_state;
1614f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj   UInt       ftop    = vex_state->guest_FTOP;
1615f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj   UInt       c3210   = vex_state->guest_FC3210;
16160c2cb623cca372a2b42b073121c7413cdaaf75besewardj
16170c2cb623cca372a2b42b073121c7413cdaaf75besewardj   for (i = 0; i < 14; i++)
16180c2cb623cca372a2b42b073121c7413cdaaf75besewardj      x87->env[i] = 0;
16190c2cb623cca372a2b42b073121c7413cdaaf75besewardj
16200c2cb623cca372a2b42b073121c7413cdaaf75besewardj   x87->env[1] = x87->env[3] = x87->env[5] = x87->env[13] = 0xFFFF;
1621c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   x87->env[FP_ENV_STAT] = ((ftop & 7) << 11) | (c3210 & 0x4700);
1622893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj   x87->env[FP_ENV_CTRL]
16233bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      = (UShort)x86g_create_fpucw( vex_state->guest_FPROUND );
16240c2cb623cca372a2b42b073121c7413cdaaf75besewardj
1625a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   /* Dump the register stack in ST order. */
16260c2cb623cca372a2b42b073121c7413cdaaf75besewardj   tagw = 0;
1627a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   for (stno = 0; stno < 8; stno++) {
1628a0e83b06f304527e3e9aec527c344e35e7023d76sewardj      preg = (stno + ftop) & 7;
1629a0e83b06f304527e3e9aec527c344e35e7023d76sewardj      if (vexTags[preg] == 0) {
16300c2cb623cca372a2b42b073121c7413cdaaf75besewardj         /* register is empty */
1631a0e83b06f304527e3e9aec527c344e35e7023d76sewardj         tagw |= (3 << (2*preg));
1632a0e83b06f304527e3e9aec527c344e35e7023d76sewardj         convert_f64le_to_f80le( (UChar*)&vexRegs[preg],
1633a0e83b06f304527e3e9aec527c344e35e7023d76sewardj                                 &x87->reg[10*stno] );
16340c2cb623cca372a2b42b073121c7413cdaaf75besewardj      } else {
16350c2cb623cca372a2b42b073121c7413cdaaf75besewardj         /* register is full. */
1636a0e83b06f304527e3e9aec527c344e35e7023d76sewardj         tagw |= (0 << (2*preg));
1637a0e83b06f304527e3e9aec527c344e35e7023d76sewardj         convert_f64le_to_f80le( (UChar*)&vexRegs[preg],
1638a0e83b06f304527e3e9aec527c344e35e7023d76sewardj                                 &x87->reg[10*stno] );
16390c2cb623cca372a2b42b073121c7413cdaaf75besewardj      }
16400c2cb623cca372a2b42b073121c7413cdaaf75besewardj   }
16410c2cb623cca372a2b42b073121c7413cdaaf75besewardj   x87->env[FP_ENV_TAG] = tagw;
16420c2cb623cca372a2b42b073121c7413cdaaf75besewardj}
16430c2cb623cca372a2b42b073121c7413cdaaf75besewardj
16440c2cb623cca372a2b42b073121c7413cdaaf75besewardj
1645f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj/* VISIBLE TO LIBVEX CLIENT */
164676bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardjUInt LibVEX_GuestX86_get_eflags ( /*IN*/VexGuestX86State* vex_state )
1647f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj{
16482a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   UInt eflags = x86g_calculate_eflags_all(
1649f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj                    vex_state->guest_CC_OP,
16502a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj                    vex_state->guest_CC_DEP1,
16512a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj                    vex_state->guest_CC_DEP2,
16522a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj                    vex_state->guest_CC_NDEP
1653f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj                 );
1654f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj   UInt dflag = vex_state->guest_DFLAG;
1655f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj   vassert(dflag == 1 || dflag == 0xFFFFFFFF);
1656f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj   if (dflag == 0xFFFFFFFF)
1657f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj      eflags |= (1<<10);
1658006a6a2f15f48f705895a516d4883e8f8142e910sewardj   if (vex_state->guest_IDFLAG == 1)
1659006a6a2f15f48f705895a516d4883e8f8142e910sewardj      eflags |= (1<<21);
1660f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj
1661f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj   return eflags;
1662f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj}
1663f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj
1664dda7a4c98be4c7c6f11eab4e1cad6ab275aed79csewardj/* VISIBLE TO LIBVEX CLIENT */
166576bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardjvoid LibVEX_GuestX86_initialise ( /*OUT*/VexGuestX86State* vex_state )
1666dda7a4c98be4c7c6f11eab4e1cad6ab275aed79csewardj{
166776bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj   vex_state->guest_EAX = 0;
166876bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj   vex_state->guest_ECX = 0;
166976bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj   vex_state->guest_EDX = 0;
167076bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj   vex_state->guest_EBX = 0;
167176bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj   vex_state->guest_ESP = 0;
167276bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj   vex_state->guest_EBP = 0;
167376bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj   vex_state->guest_ESI = 0;
167476bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj   vex_state->guest_EDI = 0;
167576bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj
16762a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   vex_state->guest_CC_OP   = X86G_CC_OP_COPY;
16772a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj   vex_state->guest_CC_DEP1 = 0;
16782a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj   vex_state->guest_CC_DEP2 = 0;
16792a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj   vex_state->guest_CC_NDEP = 0;
16802a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj   vex_state->guest_DFLAG   = 1; /* forwards */
16812a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj   vex_state->guest_IDFLAG  = 0;
168276bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj
168376bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj   vex_state->guest_EIP = 0;
168476bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj
1685a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   /* Initialise the simulated FPU */
1686a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   x86g_dirtyhelper_FINIT( vex_state );
168776bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj
1688a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   /* Initialse the SSE state. */
1689c9a43665879a03886b27a65b68af2a2c11b04f59sewardj#  define SSEZERO(_xmm) _xmm[0]=_xmm[1]=_xmm[2]=_xmm[3] = 0;
1690c9a43665879a03886b27a65b68af2a2c11b04f59sewardj
1691c9a43665879a03886b27a65b68af2a2c11b04f59sewardj   vex_state->guest_SSEROUND = (UInt)Irrm_NEAREST;
1692c9a43665879a03886b27a65b68af2a2c11b04f59sewardj   SSEZERO(vex_state->guest_XMM0);
1693c9a43665879a03886b27a65b68af2a2c11b04f59sewardj   SSEZERO(vex_state->guest_XMM1);
1694c9a43665879a03886b27a65b68af2a2c11b04f59sewardj   SSEZERO(vex_state->guest_XMM2);
1695c9a43665879a03886b27a65b68af2a2c11b04f59sewardj   SSEZERO(vex_state->guest_XMM3);
1696c9a43665879a03886b27a65b68af2a2c11b04f59sewardj   SSEZERO(vex_state->guest_XMM4);
1697c9a43665879a03886b27a65b68af2a2c11b04f59sewardj   SSEZERO(vex_state->guest_XMM5);
1698c9a43665879a03886b27a65b68af2a2c11b04f59sewardj   SSEZERO(vex_state->guest_XMM6);
1699c9a43665879a03886b27a65b68af2a2c11b04f59sewardj   SSEZERO(vex_state->guest_XMM7);
1700c9a43665879a03886b27a65b68af2a2c11b04f59sewardj
1701c9a43665879a03886b27a65b68af2a2c11b04f59sewardj#  undef SSEZERO
1702c9a43665879a03886b27a65b68af2a2c11b04f59sewardj
17033bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   vex_state->guest_CS  = 0;
17043bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   vex_state->guest_DS  = 0;
17053bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   vex_state->guest_ES  = 0;
17063bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   vex_state->guest_FS  = 0;
17073bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   vex_state->guest_GS  = 0;
17083bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   vex_state->guest_SS  = 0;
17093bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   vex_state->guest_LDT = 0;
17103bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   vex_state->guest_GDT = 0;
1711893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj
1712893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj   vex_state->guest_EMWARN = EmWarn_NONE;
1713dda7a4c98be4c7c6f11eab4e1cad6ab275aed79csewardj}
1714f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj
1715f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj
17169aebb0c3f7a7f43313786826f31402f2b733badfsewardj/*----------------------------------------------*/
17179fc9e782027baafd8b94163778996d6f05109f62sewardj/*--- Misc integer/fp helpers                ---*/
17189aebb0c3f7a7f43313786826f31402f2b733badfsewardj/*----------------------------------------------*/
17199aebb0c3f7a7f43313786826f31402f2b733badfsewardj
17209aebb0c3f7a7f43313786826f31402f2b733badfsewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
17219aebb0c3f7a7f43313786826f31402f2b733badfsewardj/* Calculate both flags and value result for rotate right
17229aebb0c3f7a7f43313786826f31402f2b733badfsewardj   through the carry bit.  Result in low 32 bits,
17239aebb0c3f7a7f43313786826f31402f2b733badfsewardj   new flags (OSZACP) in high 32 bits.
17249aebb0c3f7a7f43313786826f31402f2b733badfsewardj*/
17252a9ad023890d3b34cf45e429df2a8ae88b419128sewardjULong x86g_calculate_RCR ( UInt arg, UInt rot_amt, UInt eflags_in, UInt sz )
17269aebb0c3f7a7f43313786826f31402f2b733badfsewardj{
17279aebb0c3f7a7f43313786826f31402f2b733badfsewardj   UInt tempCOUNT = rot_amt & 0x1F, cf=0, of=0, tempcf;
17289aebb0c3f7a7f43313786826f31402f2b733badfsewardj
17299aebb0c3f7a7f43313786826f31402f2b733badfsewardj   switch (sz) {
17309aebb0c3f7a7f43313786826f31402f2b733badfsewardj      case 4:
17312a9ad023890d3b34cf45e429df2a8ae88b419128sewardj         cf        = (eflags_in >> X86G_CC_SHIFT_C) & 1;
17329aebb0c3f7a7f43313786826f31402f2b733badfsewardj         of        = ((arg >> 31) ^ cf) & 1;
17339aebb0c3f7a7f43313786826f31402f2b733badfsewardj         while (tempCOUNT > 0) {
17349aebb0c3f7a7f43313786826f31402f2b733badfsewardj            tempcf = arg & 1;
17359aebb0c3f7a7f43313786826f31402f2b733badfsewardj            arg    = (arg >> 1) | (cf << 31);
17369aebb0c3f7a7f43313786826f31402f2b733badfsewardj            cf     = tempcf;
17379aebb0c3f7a7f43313786826f31402f2b733badfsewardj            tempCOUNT--;
17389aebb0c3f7a7f43313786826f31402f2b733badfsewardj         }
17399aebb0c3f7a7f43313786826f31402f2b733badfsewardj         break;
17409aebb0c3f7a7f43313786826f31402f2b733badfsewardj      case 2:
17419aebb0c3f7a7f43313786826f31402f2b733badfsewardj         while (tempCOUNT >= 17) tempCOUNT -= 17;
17422a9ad023890d3b34cf45e429df2a8ae88b419128sewardj         cf        = (eflags_in >> X86G_CC_SHIFT_C) & 1;
17439aebb0c3f7a7f43313786826f31402f2b733badfsewardj         of        = ((arg >> 15) ^ cf) & 1;
17449aebb0c3f7a7f43313786826f31402f2b733badfsewardj         while (tempCOUNT > 0) {
17459aebb0c3f7a7f43313786826f31402f2b733badfsewardj            tempcf = arg & 1;
17469aebb0c3f7a7f43313786826f31402f2b733badfsewardj            arg    = ((arg >> 1) & 0x7FFF) | (cf << 15);
17479aebb0c3f7a7f43313786826f31402f2b733badfsewardj            cf     = tempcf;
17489aebb0c3f7a7f43313786826f31402f2b733badfsewardj            tempCOUNT--;
17499aebb0c3f7a7f43313786826f31402f2b733badfsewardj         }
17509aebb0c3f7a7f43313786826f31402f2b733badfsewardj         break;
17519aebb0c3f7a7f43313786826f31402f2b733badfsewardj      case 1:
17529aebb0c3f7a7f43313786826f31402f2b733badfsewardj         while (tempCOUNT >= 9) tempCOUNT -= 9;
17532a9ad023890d3b34cf45e429df2a8ae88b419128sewardj         cf        = (eflags_in >> X86G_CC_SHIFT_C) & 1;
17549aebb0c3f7a7f43313786826f31402f2b733badfsewardj         of        = ((arg >> 7) ^ cf) & 1;
17559aebb0c3f7a7f43313786826f31402f2b733badfsewardj         while (tempCOUNT > 0) {
17569aebb0c3f7a7f43313786826f31402f2b733badfsewardj            tempcf = arg & 1;
17579aebb0c3f7a7f43313786826f31402f2b733badfsewardj            arg    = ((arg >> 1) & 0x7F) | (cf << 7);
17589aebb0c3f7a7f43313786826f31402f2b733badfsewardj            cf     = tempcf;
17599aebb0c3f7a7f43313786826f31402f2b733badfsewardj            tempCOUNT--;
17609aebb0c3f7a7f43313786826f31402f2b733badfsewardj         }
17619aebb0c3f7a7f43313786826f31402f2b733badfsewardj         break;
17629aebb0c3f7a7f43313786826f31402f2b733badfsewardj      default:
17639aebb0c3f7a7f43313786826f31402f2b733badfsewardj         vpanic("calculate_RCR: invalid size");
17649aebb0c3f7a7f43313786826f31402f2b733badfsewardj   }
17659aebb0c3f7a7f43313786826f31402f2b733badfsewardj
17669aebb0c3f7a7f43313786826f31402f2b733badfsewardj   cf &= 1;
17679aebb0c3f7a7f43313786826f31402f2b733badfsewardj   of &= 1;
17682a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   eflags_in &= ~(X86G_CC_MASK_C | X86G_CC_MASK_O);
17692a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   eflags_in |= (cf << X86G_CC_SHIFT_C) | (of << X86G_CC_SHIFT_O);
17709aebb0c3f7a7f43313786826f31402f2b733badfsewardj
17719aebb0c3f7a7f43313786826f31402f2b733badfsewardj   return (((ULong)eflags_in) << 32) | ((ULong)arg);
17729aebb0c3f7a7f43313786826f31402f2b733badfsewardj}
17739aebb0c3f7a7f43313786826f31402f2b733badfsewardj
17747cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardj
17757cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardj/* CALLED FROM GENERATED CODE */
17767cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardj/* DIRTY HELPER (modifies guest state) */
17774ba6ed0799fcf768e3fb9627fabc52fb1d6c2a6csewardj/* Claim to be a P55C (Intel Pentium/MMX) */
17789df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardjvoid x86g_dirtyhelper_CPUID_sse0 ( VexGuestX86State* st )
17797cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardj{
17809df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   switch (st->guest_EAX) {
17819df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj      case 0:
17829df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EAX = 0x1;
17839df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EBX = 0x756e6547;
17849df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_ECX = 0x6c65746e;
17859df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EDX = 0x49656e69;
17869df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         break;
17879df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj      default:
17889df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EAX = 0x543;
17899df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EBX = 0x0;
17909df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_ECX = 0x0;
17919df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EDX = 0x8001bf;
17929df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         break;
17939df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   }
17949df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj}
17959df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj
17969df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj/* CALLED FROM GENERATED CODE */
17979df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj/* DIRTY HELPER (modifies guest state) */
17989df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj/* Claim to be the following SSE1-capable CPU:
17999df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   vendor_id       : GenuineIntel
18009df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   cpu family      : 6
18019df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   model           : 11
18029df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   model name      : Intel(R) Pentium(R) III CPU family      1133MHz
18039df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   stepping        : 1
18049df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   cpu MHz         : 1131.013
18059df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   cache size      : 512 KB
18069df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj*/
18079df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardjvoid x86g_dirtyhelper_CPUID_sse1 ( VexGuestX86State* st )
18089df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj{
18099df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   switch (st->guest_EAX) {
18109df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj      case 0:
18119df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EAX = 0x00000002;
18129df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EBX = 0x756e6547;
18139df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_ECX = 0x6c65746e;
18149df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EDX = 0x49656e69;
18159df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         break;
18169df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj      case 1:
18179df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EAX = 0x000006b1;
18189df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EBX = 0x00000004;
18199df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_ECX = 0x00000000;
18209df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EDX = 0x0383fbff;
18219df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         break;
18229df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj      default:
18239df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EAX = 0x03020101;
18249df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EBX = 0x00000000;
18259df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_ECX = 0x00000000;
18269df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EDX = 0x0c040883;
18279df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         break;
18289df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   }
18299df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj}
18309df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj
18319df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj/* Claim to be the following SSE2-capable CPU:
18329df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   vendor_id       : GenuineIntel
18339df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   cpu family      : 15
18349df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   model           : 2
18359df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   model name      : Intel(R) Pentium(R) 4 CPU 2.40GHz
18369df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   stepping        : 7
18379df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   cpu MHz         : 2394.234
18389df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   cache size      : 512 KB
18399df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj*/
18409df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardjvoid x86g_dirtyhelper_CPUID_sse2 ( VexGuestX86State* st )
18419df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj{
18429df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   switch (st->guest_EAX) {
18439df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj      case 0:
18449df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EAX = 0x00000002;
18459df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EBX = 0x756e6547;
18469df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_ECX = 0x6c65746e;
18479df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EDX = 0x49656e69;
18489df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         break;
18499df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj      case 1:
18509df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EAX = 0x00000f27;
18519df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EBX = 0x00010809;
18529df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_ECX = 0x00004400;
18539df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EDX = 0xbfebfbff;
18549df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         break;
18559df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj      default:
18569df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EAX = 0x665b5101;
18579df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EBX = 0x00000000;
18589df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_ECX = 0x00000000;
18599df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EDX = 0x007b7040;
18609df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         break;
18617cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardj   }
18627cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardj}
18637cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardj
1864464efa446b2db97115d3e5f04af5db3464cc0e93sewardj
18659fc9e782027baafd8b94163778996d6f05109f62sewardj/* CALLED FROM GENERATED CODE */
18669fc9e782027baafd8b94163778996d6f05109f62sewardj/* DIRTY HELPER (reads guest state, writes guest mem) */
1867a0e83b06f304527e3e9aec527c344e35e7023d76sewardjvoid x86g_dirtyhelper_FXSAVE ( VexGuestX86State* gst, HWord addr )
1868a0e83b06f304527e3e9aec527c344e35e7023d76sewardj{
1869a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   /* Somewhat roundabout, but at least it's simple. */
1870a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   Fpu_State tmp;
1871a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   UShort*   addrS = (UShort*)addr;
1872a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   UChar*    addrC = (UChar*)addr;
1873a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   U128*     xmm   = (U128*)(addr + 160);
1874a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   UInt      mxcsr;
1875a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   UShort    fp_tags;
1876a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   UChar     summary_tags;
1877a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   Int       r, stno;
1878a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   UShort    *srcS, *dstS;
1879a0e83b06f304527e3e9aec527c344e35e7023d76sewardj
188038a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj   do_get_x87( gst, (UChar*)&tmp );
1881a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   mxcsr = x86g_create_mxcsr( gst->guest_SSEROUND );
1882a0e83b06f304527e3e9aec527c344e35e7023d76sewardj
1883a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   /* Now build the proper fxsave image from the x87 image we just
1884a0e83b06f304527e3e9aec527c344e35e7023d76sewardj      made. */
1885a0e83b06f304527e3e9aec527c344e35e7023d76sewardj
1886a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   addrS[0]  = tmp.env[FP_ENV_CTRL]; /* FCW: fpu control word */
1887a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   addrS[1]  = tmp.env[FP_ENV_STAT]; /* FCW: fpu status word */
1888a0e83b06f304527e3e9aec527c344e35e7023d76sewardj
1889a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   /* set addrS[2] in an endian-independent way */
1890a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   summary_tags = 0;
1891a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   fp_tags = tmp.env[FP_ENV_TAG];
1892a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   for (r = 0; r < 8; r++) {
1893a0e83b06f304527e3e9aec527c344e35e7023d76sewardj      if ( ((fp_tags >> (2*r)) & 3) != 3 )
1894a0e83b06f304527e3e9aec527c344e35e7023d76sewardj         summary_tags |= (1 << r);
1895a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   }
1896a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   addrC[4]  = summary_tags; /* FTW: tag summary byte */
1897a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   addrC[5]  = 0; /* pad */
1898a0e83b06f304527e3e9aec527c344e35e7023d76sewardj
1899a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   addrS[3]  = 0; /* FOP: fpu opcode (bogus) */
1900a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   addrS[4]  = 0;
1901a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   addrS[5]  = 0; /* FPU IP (bogus) */
1902a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   addrS[6]  = 0; /* FPU IP's segment selector (bogus) (although we
1903a0e83b06f304527e3e9aec527c344e35e7023d76sewardj                     could conceivably dump %CS here) */
1904a0e83b06f304527e3e9aec527c344e35e7023d76sewardj
1905a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   addrS[7]  = 0; /* Intel reserved */
1906a0e83b06f304527e3e9aec527c344e35e7023d76sewardj
1907a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   addrS[8]  = 0; /* FPU DP (operand pointer) (bogus) */
1908a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   addrS[9]  = 0; /* FPU DP (operand pointer) (bogus) */
1909a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   addrS[10] = 0; /* segment selector for above operand pointer; %DS
1910a0e83b06f304527e3e9aec527c344e35e7023d76sewardj                     perhaps? */
1911a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   addrS[11] = 0; /* Intel reserved */
1912a0e83b06f304527e3e9aec527c344e35e7023d76sewardj
1913a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   addrS[12] = (UShort)mxcsr;  /* MXCSR */
1914a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   addrS[13] = (UShort)(mxcsr >> 16);
1915a0e83b06f304527e3e9aec527c344e35e7023d76sewardj
1916a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   addrS[14] = 0xFFFF; /* MXCSR mask (lo16); who knows what for */
1917a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   addrS[15] = 0xFFFF; /* MXCSR mask (hi16); who knows what for */
1918a0e83b06f304527e3e9aec527c344e35e7023d76sewardj
1919a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   /* Copy in the FP registers, in ST order. */
1920a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   for (stno = 0; stno < 8; stno++) {
1921a0e83b06f304527e3e9aec527c344e35e7023d76sewardj      srcS = (UShort*)(&tmp.reg[10*stno]);
1922a0e83b06f304527e3e9aec527c344e35e7023d76sewardj      dstS = (UShort*)(&addrS[16 + 8*stno]);
1923a0e83b06f304527e3e9aec527c344e35e7023d76sewardj      dstS[0] = srcS[0];
1924a0e83b06f304527e3e9aec527c344e35e7023d76sewardj      dstS[1] = srcS[1];
1925a0e83b06f304527e3e9aec527c344e35e7023d76sewardj      dstS[2] = srcS[2];
1926a0e83b06f304527e3e9aec527c344e35e7023d76sewardj      dstS[3] = srcS[3];
1927a0e83b06f304527e3e9aec527c344e35e7023d76sewardj      dstS[4] = srcS[4];
1928a0e83b06f304527e3e9aec527c344e35e7023d76sewardj      dstS[5] = 0;
1929a0e83b06f304527e3e9aec527c344e35e7023d76sewardj      dstS[6] = 0;
1930a0e83b06f304527e3e9aec527c344e35e7023d76sewardj      dstS[7] = 0;
1931a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   }
1932a0e83b06f304527e3e9aec527c344e35e7023d76sewardj
1933a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   /* That's the first 160 bytes of the image done.  Now only %xmm0
1934a0e83b06f304527e3e9aec527c344e35e7023d76sewardj      .. %xmm7 remain to be copied.  If the host is big-endian, these
1935a0e83b06f304527e3e9aec527c344e35e7023d76sewardj      need to be byte-swapped. */
1936a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   vassert(host_is_little_endian());
1937a0e83b06f304527e3e9aec527c344e35e7023d76sewardj
1938a0e83b06f304527e3e9aec527c344e35e7023d76sewardj#  define COPY_U128(_dst,_src)                       \
1939a0e83b06f304527e3e9aec527c344e35e7023d76sewardj      do { _dst[0] = _src[0]; _dst[1] = _src[1];     \
1940a0e83b06f304527e3e9aec527c344e35e7023d76sewardj           _dst[2] = _src[2]; _dst[3] = _src[3]; }   \
1941a0e83b06f304527e3e9aec527c344e35e7023d76sewardj      while (0)
1942a0e83b06f304527e3e9aec527c344e35e7023d76sewardj
1943a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   COPY_U128( xmm[0], gst->guest_XMM0 );
1944a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   COPY_U128( xmm[1], gst->guest_XMM1 );
1945a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   COPY_U128( xmm[2], gst->guest_XMM2 );
1946a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   COPY_U128( xmm[3], gst->guest_XMM3 );
1947a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   COPY_U128( xmm[4], gst->guest_XMM4 );
1948a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   COPY_U128( xmm[5], gst->guest_XMM5 );
1949a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   COPY_U128( xmm[6], gst->guest_XMM6 );
1950a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   COPY_U128( xmm[7], gst->guest_XMM7 );
1951a0e83b06f304527e3e9aec527c344e35e7023d76sewardj
1952a0e83b06f304527e3e9aec527c344e35e7023d76sewardj#  undef COPY_U128
1953a0e83b06f304527e3e9aec527c344e35e7023d76sewardj}
1954a0e83b06f304527e3e9aec527c344e35e7023d76sewardj
1955a0e83b06f304527e3e9aec527c344e35e7023d76sewardj
1956a0e83b06f304527e3e9aec527c344e35e7023d76sewardj/* CALLED FROM GENERATED CODE */
1957a0e83b06f304527e3e9aec527c344e35e7023d76sewardj/* DIRTY HELPER (reads guest state, writes guest mem) */
19589fc9e782027baafd8b94163778996d6f05109f62sewardjvoid x86g_dirtyhelper_FSAVE ( VexGuestX86State* gst, HWord addr )
19599fc9e782027baafd8b94163778996d6f05109f62sewardj{
196038a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj   do_get_x87( gst, (UChar*)addr );
19619fc9e782027baafd8b94163778996d6f05109f62sewardj}
19629fc9e782027baafd8b94163778996d6f05109f62sewardj
19639fc9e782027baafd8b94163778996d6f05109f62sewardj/* CALLED FROM GENERATED CODE */
19649fc9e782027baafd8b94163778996d6f05109f62sewardj/* DIRTY HELPER (writes guest state, reads guest mem) */
19657df596b1e36840e2d74c90aa55589934add61ccfsewardjVexEmWarn x86g_dirtyhelper_FRSTOR ( VexGuestX86State* gst, HWord addr )
19667df596b1e36840e2d74c90aa55589934add61ccfsewardj{
196738a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj   return do_put_x87( True/*regs too*/, (UChar*)addr, gst );
19687df596b1e36840e2d74c90aa55589934add61ccfsewardj}
19697df596b1e36840e2d74c90aa55589934add61ccfsewardj
19707df596b1e36840e2d74c90aa55589934add61ccfsewardj/* CALLED FROM GENERATED CODE */
19717df596b1e36840e2d74c90aa55589934add61ccfsewardj/* DIRTY HELPER (reads guest state, writes guest mem) */
19727df596b1e36840e2d74c90aa55589934add61ccfsewardjvoid x86g_dirtyhelper_FSTENV ( VexGuestX86State* gst, HWord addr )
19737df596b1e36840e2d74c90aa55589934add61ccfsewardj{
19747df596b1e36840e2d74c90aa55589934add61ccfsewardj   /* Somewhat roundabout, but at least it's simple. */
19757df596b1e36840e2d74c90aa55589934add61ccfsewardj   Int       i;
19767df596b1e36840e2d74c90aa55589934add61ccfsewardj   UShort*   addrP = (UShort*)addr;
19777df596b1e36840e2d74c90aa55589934add61ccfsewardj   Fpu_State tmp;
197838a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj   do_get_x87( gst, (UChar*)&tmp );
19797df596b1e36840e2d74c90aa55589934add61ccfsewardj   for (i = 0; i < 14; i++)
19807df596b1e36840e2d74c90aa55589934add61ccfsewardj      addrP[i] = tmp.env[i];
19817df596b1e36840e2d74c90aa55589934add61ccfsewardj}
19827df596b1e36840e2d74c90aa55589934add61ccfsewardj
19837df596b1e36840e2d74c90aa55589934add61ccfsewardj/* CALLED FROM GENERATED CODE */
19847df596b1e36840e2d74c90aa55589934add61ccfsewardj/* DIRTY HELPER (writes guest state, reads guest mem) */
19857df596b1e36840e2d74c90aa55589934add61ccfsewardjVexEmWarn x86g_dirtyhelper_FLDENV ( VexGuestX86State* gst, HWord addr )
19869fc9e782027baafd8b94163778996d6f05109f62sewardj{
198738a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj   return do_put_x87( False/*don't move regs*/, (UChar*)addr, gst);
19889fc9e782027baafd8b94163778996d6f05109f62sewardj}
19899fc9e782027baafd8b94163778996d6f05109f62sewardj
1990464efa446b2db97115d3e5f04af5db3464cc0e93sewardj
1991464efa446b2db97115d3e5f04af5db3464cc0e93sewardj/*----------------------------------------------*/
199238a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj/*--- Helpers for MMX/SSE                    ---*/
1993464efa446b2db97115d3e5f04af5db3464cc0e93sewardj/*----------------------------------------------*/
1994464efa446b2db97115d3e5f04af5db3464cc0e93sewardj
199538a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UChar abdU8 ( UChar xx, UChar yy ) {
199638a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj   return xx>yy ? xx-yy : yy-xx;
199738a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj}
1998464efa446b2db97115d3e5f04af5db3464cc0e93sewardj
199938a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline ULong mk32x2 ( UInt w1, UInt w0 ) {
2000464efa446b2db97115d3e5f04af5db3464cc0e93sewardj   return (((ULong)w1) << 32) | ((ULong)w0);
2001464efa446b2db97115d3e5f04af5db3464cc0e93sewardj}
2002464efa446b2db97115d3e5f04af5db3464cc0e93sewardj
200338a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UShort sel16x4_3 ( ULong w64 ) {
2004464efa446b2db97115d3e5f04af5db3464cc0e93sewardj   UInt hi32 = (UInt)(w64 >> 32);
2005464efa446b2db97115d3e5f04af5db3464cc0e93sewardj   return 0xFFFF & (UShort)(hi32 >> 16);
2006464efa446b2db97115d3e5f04af5db3464cc0e93sewardj}
200738a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UShort sel16x4_2 ( ULong w64 ) {
2008464efa446b2db97115d3e5f04af5db3464cc0e93sewardj   UInt hi32 = (UInt)(w64 >> 32);
2009464efa446b2db97115d3e5f04af5db3464cc0e93sewardj   return 0xFFFF & (UShort)hi32;
2010464efa446b2db97115d3e5f04af5db3464cc0e93sewardj}
201138a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UShort sel16x4_1 ( ULong w64 ) {
2012464efa446b2db97115d3e5f04af5db3464cc0e93sewardj   UInt lo32 = (UInt)w64;
201363ba4091e2d4b049f9a81d878cb3f3c97d6e20bfsewardj   return 0xFFFF & (UShort)(lo32 >> 16);
2014464efa446b2db97115d3e5f04af5db3464cc0e93sewardj}
201538a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UShort sel16x4_0 ( ULong w64 ) {
2016464efa446b2db97115d3e5f04af5db3464cc0e93sewardj   UInt lo32 = (UInt)w64;
2017464efa446b2db97115d3e5f04af5db3464cc0e93sewardj   return 0xFFFF & (UShort)lo32;
2018464efa446b2db97115d3e5f04af5db3464cc0e93sewardj}
2019464efa446b2db97115d3e5f04af5db3464cc0e93sewardj
202038a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UChar sel8x8_7 ( ULong w64 ) {
2021464efa446b2db97115d3e5f04af5db3464cc0e93sewardj   UInt hi32 = (UInt)(w64 >> 32);
2022464efa446b2db97115d3e5f04af5db3464cc0e93sewardj   return 0xFF & (UChar)(hi32 >> 24);
2023464efa446b2db97115d3e5f04af5db3464cc0e93sewardj}
202438a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UChar sel8x8_6 ( ULong w64 ) {
2025464efa446b2db97115d3e5f04af5db3464cc0e93sewardj   UInt hi32 = (UInt)(w64 >> 32);
2026464efa446b2db97115d3e5f04af5db3464cc0e93sewardj   return 0xFF & (UChar)(hi32 >> 16);
2027464efa446b2db97115d3e5f04af5db3464cc0e93sewardj}
202838a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UChar sel8x8_5 ( ULong w64 ) {
2029464efa446b2db97115d3e5f04af5db3464cc0e93sewardj   UInt hi32 = (UInt)(w64 >> 32);
2030464efa446b2db97115d3e5f04af5db3464cc0e93sewardj   return 0xFF & (UChar)(hi32 >> 8);
2031464efa446b2db97115d3e5f04af5db3464cc0e93sewardj}
203238a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UChar sel8x8_4 ( ULong w64 ) {
2033464efa446b2db97115d3e5f04af5db3464cc0e93sewardj   UInt hi32 = (UInt)(w64 >> 32);
2034464efa446b2db97115d3e5f04af5db3464cc0e93sewardj   return 0xFF & (UChar)(hi32 >> 0);
2035464efa446b2db97115d3e5f04af5db3464cc0e93sewardj}
203638a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UChar sel8x8_3 ( ULong w64 ) {
2037464efa446b2db97115d3e5f04af5db3464cc0e93sewardj   UInt lo32 = (UInt)w64;
2038464efa446b2db97115d3e5f04af5db3464cc0e93sewardj   return 0xFF & (UChar)(lo32 >> 24);
2039464efa446b2db97115d3e5f04af5db3464cc0e93sewardj}
204038a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UChar sel8x8_2 ( ULong w64 ) {
2041464efa446b2db97115d3e5f04af5db3464cc0e93sewardj   UInt lo32 = (UInt)w64;
2042464efa446b2db97115d3e5f04af5db3464cc0e93sewardj   return 0xFF & (UChar)(lo32 >> 16);
2043464efa446b2db97115d3e5f04af5db3464cc0e93sewardj}
204438a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UChar sel8x8_1 ( ULong w64 ) {
2045464efa446b2db97115d3e5f04af5db3464cc0e93sewardj   UInt lo32 = (UInt)w64;
2046464efa446b2db97115d3e5f04af5db3464cc0e93sewardj   return 0xFF & (UChar)(lo32 >> 8);
2047464efa446b2db97115d3e5f04af5db3464cc0e93sewardj}
204838a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UChar sel8x8_0 ( ULong w64 ) {
2049464efa446b2db97115d3e5f04af5db3464cc0e93sewardj   UInt lo32 = (UInt)w64;
2050464efa446b2db97115d3e5f04af5db3464cc0e93sewardj   return 0xFF & (UChar)(lo32 >> 0);
2051464efa446b2db97115d3e5f04af5db3464cc0e93sewardj}
2052464efa446b2db97115d3e5f04af5db3464cc0e93sewardj
205338a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
205438a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjULong x86g_calculate_mmx_pmaddwd ( ULong xx, ULong yy )
20554340dac5c2cede4962868e6da5b73282da2bc465sewardj{
20564340dac5c2cede4962868e6da5b73282da2bc465sewardj   return
20574340dac5c2cede4962868e6da5b73282da2bc465sewardj      mk32x2(
20584340dac5c2cede4962868e6da5b73282da2bc465sewardj         (((Int)(Short)sel16x4_3(xx)) * ((Int)(Short)sel16x4_3(yy)))
20594340dac5c2cede4962868e6da5b73282da2bc465sewardj            + (((Int)(Short)sel16x4_2(xx)) * ((Int)(Short)sel16x4_2(yy))),
20604340dac5c2cede4962868e6da5b73282da2bc465sewardj         (((Int)(Short)sel16x4_1(xx)) * ((Int)(Short)sel16x4_1(yy)))
20614340dac5c2cede4962868e6da5b73282da2bc465sewardj            + (((Int)(Short)sel16x4_0(xx)) * ((Int)(Short)sel16x4_0(yy)))
20624340dac5c2cede4962868e6da5b73282da2bc465sewardj      );
20634340dac5c2cede4962868e6da5b73282da2bc465sewardj}
20644340dac5c2cede4962868e6da5b73282da2bc465sewardj
206538a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
206638a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjUInt x86g_calculate_mmx_pmovmskb ( ULong xx )
2067b54520819b40c3fe907725b56bcd8db5112c0b9asewardj{
2068b54520819b40c3fe907725b56bcd8db5112c0b9asewardj   UInt r = 0;
2069b54520819b40c3fe907725b56bcd8db5112c0b9asewardj   if (xx & (1ULL << (64-1))) r |= (1<<7);
2070b54520819b40c3fe907725b56bcd8db5112c0b9asewardj   if (xx & (1ULL << (56-1))) r |= (1<<6);
2071b54520819b40c3fe907725b56bcd8db5112c0b9asewardj   if (xx & (1ULL << (48-1))) r |= (1<<5);
2072b54520819b40c3fe907725b56bcd8db5112c0b9asewardj   if (xx & (1ULL << (40-1))) r |= (1<<4);
2073b54520819b40c3fe907725b56bcd8db5112c0b9asewardj   if (xx & (1ULL << (32-1))) r |= (1<<3);
2074b54520819b40c3fe907725b56bcd8db5112c0b9asewardj   if (xx & (1ULL << (24-1))) r |= (1<<2);
2075b54520819b40c3fe907725b56bcd8db5112c0b9asewardj   if (xx & (1ULL << (16-1))) r |= (1<<1);
2076b54520819b40c3fe907725b56bcd8db5112c0b9asewardj   if (xx & (1ULL << ( 8-1))) r |= (1<<0);
2077b54520819b40c3fe907725b56bcd8db5112c0b9asewardj   return r;
2078b54520819b40c3fe907725b56bcd8db5112c0b9asewardj}
2079b54520819b40c3fe907725b56bcd8db5112c0b9asewardj
208038a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
208138a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjULong x86g_calculate_mmx_psadbw ( ULong xx, ULong yy )
20820bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj{
20830bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj   UInt t = 0;
20840bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj   t += (UInt)abdU8( sel8x8_7(xx), sel8x8_7(yy) );
20850bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj   t += (UInt)abdU8( sel8x8_6(xx), sel8x8_6(yy) );
20860bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj   t += (UInt)abdU8( sel8x8_5(xx), sel8x8_5(yy) );
20870bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj   t += (UInt)abdU8( sel8x8_4(xx), sel8x8_4(yy) );
20880bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj   t += (UInt)abdU8( sel8x8_3(xx), sel8x8_3(yy) );
20890bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj   t += (UInt)abdU8( sel8x8_2(xx), sel8x8_2(yy) );
20900bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj   t += (UInt)abdU8( sel8x8_1(xx), sel8x8_1(yy) );
20910bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj   t += (UInt)abdU8( sel8x8_0(xx), sel8x8_0(yy) );
20920bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj   t &= 0xFFFF;
20930bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj   return (ULong)t;
20940bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj}
20950bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj
209638a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
2097e5854d6d470f21677ec84f71d09129434b044246sewardjUInt x86g_calculate_sse_pmovmskb ( ULong w64hi, ULong w64lo )
2098e5854d6d470f21677ec84f71d09129434b044246sewardj{
209938a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj   UInt rHi8 = x86g_calculate_mmx_pmovmskb ( w64hi );
210038a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj   UInt rLo8 = x86g_calculate_mmx_pmovmskb ( w64lo );
2101e5854d6d470f21677ec84f71d09129434b044246sewardj   return ((rHi8 & 0xFF) << 8) | (rLo8 & 0xFF);
2102e5854d6d470f21677ec84f71d09129434b044246sewardj}
2103e5854d6d470f21677ec84f71d09129434b044246sewardj
2104464efa446b2db97115d3e5f04af5db3464cc0e93sewardj
21053bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj/*----------------------------------------------*/
21063bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj/*--- Helpers for segment overrides          ---*/
21073bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj/*----------------------------------------------*/
21083bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
21093bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardjstatic inline
21103bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardjUInt get_segdescr_base ( VexGuestX86SegDescr* ent )
21113bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj{
21123bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   UInt lo  = 0xFFFF & (UInt)ent->LdtEnt.Bits.BaseLow;
21133bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   UInt mid =   0xFF & (UInt)ent->LdtEnt.Bits.BaseMid;
21143bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   UInt hi  =   0xFF & (UInt)ent->LdtEnt.Bits.BaseHi;
21153bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   return (hi << 24) | (mid << 16) | lo;
21163bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj}
21173bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
21183bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardjstatic inline
21193bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardjUInt get_segdescr_limit ( VexGuestX86SegDescr* ent )
21203bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj{
21213bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj    UInt lo    = 0xFFFF & (UInt)ent->LdtEnt.Bits.LimitLow;
21223bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj    UInt hi    =    0xF & (UInt)ent->LdtEnt.Bits.LimitHi;
21233bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj    UInt limit = (hi << 16) | lo;
21243bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj    if (ent->LdtEnt.Bits.Granularity)
21253bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj       limit = (limit << 12) | 0xFFF;
21263bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj    return limit;
21273bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj}
21283bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
212938a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
21303bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardjULong x86g_use_seg_selector ( HWord ldt, HWord gdt,
21313bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj                              UInt seg_selector, UInt virtual_addr )
21323bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj{
21333bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   UInt tiBit, base, limit;
21343bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   VexGuestX86SegDescr* the_descrs;
21353bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
21363bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   Bool verboze = False;
21373bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
21383bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   /* If this isn't true, we're in Big Trouble. */
21393bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   vassert(8 == sizeof(VexGuestX86SegDescr));
21403bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
21413bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   if (verboze)
21423bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      vex_printf("x86h_use_seg_selector: "
21433bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj                 "seg_selector = 0x%x, vaddr = 0x%x\n",
21443bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj                 seg_selector, virtual_addr);
21453bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
21463bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   /* Check for wildly invalid selector. */
21473bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   if (seg_selector & ~0xFFFF)
21483bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      goto bad;
21493bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
21503bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   seg_selector &= 0x0000FFFF;
21513bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
21523bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   /* Sanity check the segment selector.  Ensure that RPL=11b (least
21533bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      privilege).  This forms the bottom 2 bits of the selector. */
21543bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   if ((seg_selector & 3) != 3)
21553bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      goto bad;
21563bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
21573bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   /* Extract the TI bit (0 means GDT, 1 means LDT) */
21583bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   tiBit = (seg_selector >> 2) & 1;
21593bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
21603bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   /* Convert the segment selector onto a table index */
21613bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   seg_selector >>= 3;
21623bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   vassert(seg_selector >= 0 && seg_selector < 8192);
21633bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
21643bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   if (tiBit == 0) {
21653bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
21663bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      /* GDT access. */
21673bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      /* Do we actually have a GDT to look at? */
21683bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      if (gdt == 0)
21693bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj         goto bad;
21703bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
21713bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      /* Check for access to non-existent entry. */
21723bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      if (seg_selector >= VEX_GUEST_X86_GDT_NENT)
21733bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj         goto bad;
21743bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
21753bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      the_descrs = (VexGuestX86SegDescr*)gdt;
21763bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      base  = get_segdescr_base (&the_descrs[seg_selector]);
21773bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      limit = get_segdescr_limit(&the_descrs[seg_selector]);
21783bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
21793bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   } else {
21803bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
21813bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      /* All the same stuff, except for the LDT. */
21823bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      if (ldt == 0)
21833bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj         goto bad;
21843bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
21853bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      if (seg_selector >= VEX_GUEST_X86_LDT_NENT)
21863bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj         goto bad;
21873bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
21883bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      the_descrs = (VexGuestX86SegDescr*)ldt;
21893bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      base  = get_segdescr_base (&the_descrs[seg_selector]);
21903bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      limit = get_segdescr_limit(&the_descrs[seg_selector]);
21913bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
21923bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   }
21933bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
21943bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   /* Do the limit check.  Note, this check is just slightly too
21953bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      slack.  Really it should be "if (virtual_addr + size - 1 >=
21963bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      limit)," but we don't have the size info to hand.  Getting it
21973bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      could be significantly complex.  */
21983bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   if (virtual_addr >= limit)
21993bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      goto bad;
22003bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
22013bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   if (verboze)
22023bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      vex_printf("x86h_use_seg_selector: "
22033bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj                 "base = 0x%x, addr = 0x%x\n",
22043bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj                 base, base + virtual_addr);
22053bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
22063bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   /* High 32 bits are zero, indicating success. */
22073bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   return (ULong)( ((UInt)virtual_addr) + base );
22083bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
22093bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj bad:
22103bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   return 1ULL << 32;
22113bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj}
22123bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
22133bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
22148d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj/*-----------------------------------------------------------*/
22158d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj/*--- Describing the x86 guest state, for the benefit     ---*/
22168d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj/*--- of iropt and instrumenters.                         ---*/
22178d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj/*-----------------------------------------------------------*/
22188d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj
22198d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj/* Figure out if any part of the guest state contained in minoff
22208d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   .. maxoff requires precise memory exceptions.  If in doubt return
22218d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   True (but this is generates significantly slower code).
22228d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj
22238d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   We enforce precise exns for guest %ESP and %EIP only.
22248d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj*/
22258d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardjBool guest_x86_state_requires_precise_mem_exns ( Int minoff,
22268d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj                                                 Int maxoff)
22278d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj{
22288d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   Int esp_min = offsetof(VexGuestX86State, guest_ESP);
22298d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   Int esp_max = esp_min + 4 - 1;
22308d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   Int eip_min = offsetof(VexGuestX86State, guest_EIP);
22318d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   Int eip_max = eip_min + 4 - 1;
22328d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj
22338d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   if (maxoff < esp_min || minoff > esp_max) {
2234eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj      /* no overlap with esp */
22358d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   } else {
2236eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj      return True;
22378d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   }
22388d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj
22398d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   if (maxoff < eip_min || minoff > eip_max) {
2240eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj      /* no overlap with eip */
22418d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   } else {
2242eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj      return True;
22438d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   }
22448d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj
22458d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   return False;
22468d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj}
22478d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj
22488d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj
2249eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj#define ALWAYSDEFD(field)                           \
2250eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj    { offsetof(VexGuestX86State, field),            \
2251eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj      (sizeof ((VexGuestX86State*)0)->field) }
2252eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj
2253eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardjVexGuestLayout
225449651f4b59b1ab7e0e70cccd34001630eafbe957sewardj   x86guest_layout
2255eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj      = {
2256eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj          /* Total size of the guest state, in bytes. */
2257eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj          .total_sizeB = sizeof(VexGuestX86State),
2258eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj
2259eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj          /* Describe the stack pointer. */
2260eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj          .offset_SP = offsetof(VexGuestX86State,guest_ESP),
2261eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj          .sizeof_SP = 4,
2262eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj
2263cf7879021370aabcccb1a9347244fcc7d5680141sewardj          /* Describe the instruction pointer. */
2264cf7879021370aabcccb1a9347244fcc7d5680141sewardj          .offset_IP = offsetof(VexGuestX86State,guest_EIP),
2265cf7879021370aabcccb1a9347244fcc7d5680141sewardj          .sizeof_IP = 4,
2266eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj
2267eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj          /* Describe any sections to be regarded by Memcheck as
2268eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj             'always-defined'. */
22693bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj          .n_alwaysDefd = 18,
22703bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
22712a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj          /* flags thunk: OP and NDEP are always defd, whereas DEP1
22722a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj             and DEP2 have to be tracked.  See detailed comment in
22732a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj             gdefs.h on meaning of thunk fields. */
22748fc937421c954ff9f707254f028b1fa0410c473dsewardj          .alwaysDefd
22758fc937421c954ff9f707254f028b1fa0410c473dsewardj             = { /*  0 */ ALWAYSDEFD(guest_CC_OP),
22768fc937421c954ff9f707254f028b1fa0410c473dsewardj                 /*  1 */ ALWAYSDEFD(guest_CC_NDEP),
22778fc937421c954ff9f707254f028b1fa0410c473dsewardj                 /*  2 */ ALWAYSDEFD(guest_DFLAG),
22788fc937421c954ff9f707254f028b1fa0410c473dsewardj                 /*  3 */ ALWAYSDEFD(guest_IDFLAG),
22798fc937421c954ff9f707254f028b1fa0410c473dsewardj                 /*  4 */ ALWAYSDEFD(guest_EIP),
22808fc937421c954ff9f707254f028b1fa0410c473dsewardj                 /*  5 */ ALWAYSDEFD(guest_FTOP),
22818fc937421c954ff9f707254f028b1fa0410c473dsewardj                 /*  6 */ ALWAYSDEFD(guest_FPTAG),
2282d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj                 /*  7 */ ALWAYSDEFD(guest_FPROUND),
22838fc937421c954ff9f707254f028b1fa0410c473dsewardj                 /*  8 */ ALWAYSDEFD(guest_FC3210),
22848fc937421c954ff9f707254f028b1fa0410c473dsewardj                 /*  9 */ ALWAYSDEFD(guest_CS),
22858fc937421c954ff9f707254f028b1fa0410c473dsewardj                 /* 10 */ ALWAYSDEFD(guest_DS),
22868fc937421c954ff9f707254f028b1fa0410c473dsewardj                 /* 11 */ ALWAYSDEFD(guest_ES),
22878fc937421c954ff9f707254f028b1fa0410c473dsewardj                 /* 12 */ ALWAYSDEFD(guest_FS),
22888fc937421c954ff9f707254f028b1fa0410c473dsewardj                 /* 13 */ ALWAYSDEFD(guest_GS),
22893bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj                 /* 14 */ ALWAYSDEFD(guest_SS),
22903bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj                 /* 15 */ ALWAYSDEFD(guest_LDT),
22913bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj                 /* 16 */ ALWAYSDEFD(guest_GDT),
22923bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj                 /* 17 */ ALWAYSDEFD(guest_EMWARN)
22938fc937421c954ff9f707254f028b1fa0410c473dsewardj               }
2294eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj        };
229549651f4b59b1ab7e0e70cccd34001630eafbe957sewardj
229649651f4b59b1ab7e0e70cccd34001630eafbe957sewardj
229736ca51378f8851635df814230fa23f2c409b9eddsewardj/*---------------------------------------------------------------*/
2298c0ee2edb4563c90bc8f1a83a09984a1fda86d1d3sewardj/*--- end                                guest-x86/ghelpers.c ---*/
229936ca51378f8851635df814230fa23f2c409b9eddsewardj/*---------------------------------------------------------------*/
2300