136ca51378f8851635df814230fa23f2c409b9eddsewardj
236ca51378f8851635df814230fa23f2c409b9eddsewardj/*---------------------------------------------------------------*/
3752f90673ebbb6b2f55fc5e46606dea371313713sewardj/*--- begin                               guest_x86_helpers.c ---*/
436ca51378f8851635df814230fa23f2c409b9eddsewardj/*---------------------------------------------------------------*/
536ca51378f8851635df814230fa23f2c409b9eddsewardj
6f8ed9d874a7b8651654591c68c6d431c758d787csewardj/*
7752f90673ebbb6b2f55fc5e46606dea371313713sewardj   This file is part of Valgrind, a dynamic binary instrumentation
8752f90673ebbb6b2f55fc5e46606dea371313713sewardj   framework.
9f8ed9d874a7b8651654591c68c6d431c758d787csewardj
1089ae8477745fd2a15453557d729a50e627325ee2sewardj   Copyright (C) 2004-2013 OpenWorks LLP
11752f90673ebbb6b2f55fc5e46606dea371313713sewardj      info@open-works.net
127bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj
13752f90673ebbb6b2f55fc5e46606dea371313713sewardj   This program is free software; you can redistribute it and/or
14752f90673ebbb6b2f55fc5e46606dea371313713sewardj   modify it under the terms of the GNU General Public License as
15752f90673ebbb6b2f55fc5e46606dea371313713sewardj   published by the Free Software Foundation; either version 2 of the
16752f90673ebbb6b2f55fc5e46606dea371313713sewardj   License, or (at your option) any later version.
177bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj
18752f90673ebbb6b2f55fc5e46606dea371313713sewardj   This program is distributed in the hope that it will be useful, but
19752f90673ebbb6b2f55fc5e46606dea371313713sewardj   WITHOUT ANY WARRANTY; without even the implied warranty of
20752f90673ebbb6b2f55fc5e46606dea371313713sewardj   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21752f90673ebbb6b2f55fc5e46606dea371313713sewardj   General Public License for more details.
22752f90673ebbb6b2f55fc5e46606dea371313713sewardj
23752f90673ebbb6b2f55fc5e46606dea371313713sewardj   You should have received a copy of the GNU General Public License
24752f90673ebbb6b2f55fc5e46606dea371313713sewardj   along with this program; if not, write to the Free Software
25752f90673ebbb6b2f55fc5e46606dea371313713sewardj   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
267bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj   02110-1301, USA.
277bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj
28752f90673ebbb6b2f55fc5e46606dea371313713sewardj   The GNU General Public License is contained in the file COPYING.
29f8ed9d874a7b8651654591c68c6d431c758d787csewardj
30f8ed9d874a7b8651654591c68c6d431c758d787csewardj   Neither the names of the U.S. Department of Energy nor the
31f8ed9d874a7b8651654591c68c6d431c758d787csewardj   University of California nor the names of its contributors may be
32f8ed9d874a7b8651654591c68c6d431c758d787csewardj   used to endorse or promote products derived from this software
33f8ed9d874a7b8651654591c68c6d431c758d787csewardj   without prior written permission.
34f8ed9d874a7b8651654591c68c6d431c758d787csewardj*/
35f8ed9d874a7b8651654591c68c6d431c758d787csewardj
3636ca51378f8851635df814230fa23f2c409b9eddsewardj#include "libvex_basictypes.h"
3733b024301d2311965cc68dc4cc900f3d0fdd8085florian#include "libvex_emnote.h"
380c2cb623cca372a2b42b073121c7413cdaaf75besewardj#include "libvex_guest_x86.h"
3936ca51378f8851635df814230fa23f2c409b9eddsewardj#include "libvex_ir.h"
4049651f4b59b1ab7e0e70cccd34001630eafbe957sewardj#include "libvex.h"
41c0ee2edb4563c90bc8f1a83a09984a1fda86d1d3sewardj
42cef7d3e3df4796e35b4521158d9dc058f034aa87sewardj#include "main_util.h"
436c46befd9eb90c1b6e739926c1fa335cba75bf46philippe#include "main_globals.h"
44cef7d3e3df4796e35b4521158d9dc058f034aa87sewardj#include "guest_generic_bb_to_IR.h"
45cef7d3e3df4796e35b4521158d9dc058f034aa87sewardj#include "guest_x86_defs.h"
46cef7d3e3df4796e35b4521158d9dc058f034aa87sewardj#include "guest_generic_x87.h"
47c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
48893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
4936ca51378f8851635df814230fa23f2c409b9eddsewardj/* This file contains helper functions for x86 guest code.
5036ca51378f8851635df814230fa23f2c409b9eddsewardj   Calls to these functions are generated by the back end.
5136ca51378f8851635df814230fa23f2c409b9eddsewardj   These calls are of course in the host machine code and
5236ca51378f8851635df814230fa23f2c409b9eddsewardj   this file will be compiled to host machine code, so that
5336ca51378f8851635df814230fa23f2c409b9eddsewardj   all makes sense.
5436ca51378f8851635df814230fa23f2c409b9eddsewardj
5536ca51378f8851635df814230fa23f2c409b9eddsewardj   Only change the signatures of these helper functions very
5636ca51378f8851635df814230fa23f2c409b9eddsewardj   carefully.  If you change the signature here, you'll have to change
5736ca51378f8851635df814230fa23f2c409b9eddsewardj   the parameters passed to it in the IR calls constructed by
582a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   guest-x86/toIR.c.
5989050e58e7bee40892662fe94231aefc33768cf5sewardj
60893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   The convention used is that all functions called from generated
61893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   code are named x86g_<something>, and any function whose name lacks
62893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   that prefix is not called from generated code.  Note that some
63893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   LibVEX_* functions can however be called by VEX's client, but that
64893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   is not the same as calling them from VEX-generated code.
6536ca51378f8851635df814230fa23f2c409b9eddsewardj*/
6636ca51378f8851635df814230fa23f2c409b9eddsewardj
67893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
6884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj/* Set to 1 to get detailed profiling info about use of the flag
6984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   machinery. */
7084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#define PROFILE_EFLAGS 0
7184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
7284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
73893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/*---------------------------------------------------------------*/
74893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/*--- %eflags run-time helpers.                               ---*/
75893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/*---------------------------------------------------------------*/
76893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
77d44bc6e6692dfb0881dcc249bd4ba3d8f8e97fcasewardjstatic const UChar parity_table[256] = {
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    0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
812a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
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    X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
852a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
862a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
872a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
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    X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
912a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
922a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
932a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
942a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    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    X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
972a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
982a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
992a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
1002a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
1012a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
1022a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
1032a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
1042a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
1052a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
1062a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
1072a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
1082a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0,
1092a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P,
11014731f22bf7759d6d23383ca870ac89d9581f1e9sewardj};
11114731f22bf7759d6d23383ca870ac89d9581f1e9sewardj
1124a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj/* generalised left-shifter */
113df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardjinline static Int lshift ( Int x, Int n )
11414731f22bf7759d6d23383ca870ac89d9581f1e9sewardj{
115df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   if (n >= 0)
116108e03fcb0a4ef42164235b1988aa540aa1e5298florian      return (UInt)x << n;
117df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   else
118df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj      return x >> (-n);
11914731f22bf7759d6d23383ca870ac89d9581f1e9sewardj}
12014731f22bf7759d6d23383ca870ac89d9581f1e9sewardj
1214a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj/* identity on ULong */
1224a6f3844a29aebc9774ab0d71418421c14ba9c41sewardjstatic inline ULong idULong ( ULong x )
1234a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj{
1244a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj   return x;
1254a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj}
1264a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj
12714731f22bf7759d6d23383ca870ac89d9581f1e9sewardj
128b9c5cf639b3b21b972599d27207a033afc76ef67sewardj#define PREAMBLE(__data_bits)					\
129df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   /* const */ UInt DATA_MASK 					\
130b9c5cf639b3b21b972599d27207a033afc76ef67sewardj      = __data_bits==8 ? 0xFF 					\
131b9c5cf639b3b21b972599d27207a033afc76ef67sewardj                       : (__data_bits==16 ? 0xFFFF 		\
132b9c5cf639b3b21b972599d27207a033afc76ef67sewardj                                          : 0xFFFFFFFF); 	\
133108e03fcb0a4ef42164235b1988aa540aa1e5298florian   /* const */ UInt SIGN_MASK = 1u << (__data_bits - 1);	\
1342a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj   /* const */ UInt CC_DEP1 = cc_dep1_formal;			\
1352a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj   /* const */ UInt CC_DEP2 = cc_dep2_formal;			\
1362a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj   /* const */ UInt CC_NDEP = cc_ndep_formal;			\
1372a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj   /* Four bogus assignments, which hopefully gcc can     */	\
138df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   /* optimise away, and which stop it complaining about  */	\
139df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   /* unused variables.                                   */	\
140df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   SIGN_MASK = SIGN_MASK;					\
141df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   DATA_MASK = DATA_MASK;					\
1422a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj   CC_DEP2 = CC_DEP2;						\
1432a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj   CC_NDEP = CC_NDEP;
144df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj
14514731f22bf7759d6d23383ca870ac89d9581f1e9sewardj
146b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
147b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
148df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_ADD(DATA_BITS,DATA_UTYPE)			\
149b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
150b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
151108e03fcb0a4ef42164235b1988aa540aa1e5298florian   { UInt cf, pf, af, zf, sf, of;				\
152108e03fcb0a4ef42164235b1988aa540aa1e5298florian     UInt argL, argR, res;					\
1538fc937421c954ff9f707254f028b1fa0410c473dsewardj     argL = CC_DEP1;						\
1548fc937421c954ff9f707254f028b1fa0410c473dsewardj     argR = CC_DEP2;						\
1558fc937421c954ff9f707254f028b1fa0410c473dsewardj     res  = argL + argR;					\
1568fc937421c954ff9f707254f028b1fa0410c473dsewardj     cf = (DATA_UTYPE)res < (DATA_UTYPE)argL;			\
1578fc937421c954ff9f707254f028b1fa0410c473dsewardj     pf = parity_table[(UChar)res];				\
1588fc937421c954ff9f707254f028b1fa0410c473dsewardj     af = (res ^ argL ^ argR) & 0x10;				\
1598fc937421c954ff9f707254f028b1fa0410c473dsewardj     zf = ((DATA_UTYPE)res == 0) << 6;				\
1608fc937421c954ff9f707254f028b1fa0410c473dsewardj     sf = lshift(res, 8 - DATA_BITS) & 0x80;			\
1618fc937421c954ff9f707254f028b1fa0410c473dsewardj     of = lshift((argL ^ argR ^ -1) & (argL ^ res), 		\
1622a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                 12 - DATA_BITS) & X86G_CC_MASK_O;		\
1638fc937421c954ff9f707254f028b1fa0410c473dsewardj     return cf | pf | af | zf | sf | of;			\
1648fc937421c954ff9f707254f028b1fa0410c473dsewardj   }								\
1652ef5f2a829433c4ca17f33e1bf993cf16b9e347dsewardj}
1662ef5f2a829433c4ca17f33e1bf993cf16b9e347dsewardj
167b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
168b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
1692a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj#define ACTIONS_SUB(DATA_BITS,DATA_UTYPE)			\
170b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
171b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
172108e03fcb0a4ef42164235b1988aa540aa1e5298florian   { UInt cf, pf, af, zf, sf, of;				\
173108e03fcb0a4ef42164235b1988aa540aa1e5298florian     UInt argL, argR, res;					\
1748fc937421c954ff9f707254f028b1fa0410c473dsewardj     argL = CC_DEP1;						\
1758fc937421c954ff9f707254f028b1fa0410c473dsewardj     argR = CC_DEP2;						\
1768fc937421c954ff9f707254f028b1fa0410c473dsewardj     res  = argL - argR;					\
1778fc937421c954ff9f707254f028b1fa0410c473dsewardj     cf = (DATA_UTYPE)argL < (DATA_UTYPE)argR;			\
1788fc937421c954ff9f707254f028b1fa0410c473dsewardj     pf = parity_table[(UChar)res];				\
1798fc937421c954ff9f707254f028b1fa0410c473dsewardj     af = (res ^ argL ^ argR) & 0x10;				\
1808fc937421c954ff9f707254f028b1fa0410c473dsewardj     zf = ((DATA_UTYPE)res == 0) << 6;				\
1818fc937421c954ff9f707254f028b1fa0410c473dsewardj     sf = lshift(res, 8 - DATA_BITS) & 0x80;			\
1828fc937421c954ff9f707254f028b1fa0410c473dsewardj     of = lshift((argL ^ argR) & (argL ^ res),	 		\
1832a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                 12 - DATA_BITS) & X86G_CC_MASK_O; 		\
1848fc937421c954ff9f707254f028b1fa0410c473dsewardj     return cf | pf | af | zf | sf | of;			\
1858fc937421c954ff9f707254f028b1fa0410c473dsewardj   }								\
1862ef5f2a829433c4ca17f33e1bf993cf16b9e347dsewardj}
1872ef5f2a829433c4ca17f33e1bf993cf16b9e347dsewardj
188b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
189b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
1902a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj#define ACTIONS_ADC(DATA_BITS,DATA_UTYPE)			\
191b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
192b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
193108e03fcb0a4ef42164235b1988aa540aa1e5298florian   { UInt cf, pf, af, zf, sf, of;				\
194108e03fcb0a4ef42164235b1988aa540aa1e5298florian     UInt argL, argR, oldC, res;		       		\
1952a9ad023890d3b34cf45e429df2a8ae88b419128sewardj     oldC = CC_NDEP & X86G_CC_MASK_C;				\
1968fc937421c954ff9f707254f028b1fa0410c473dsewardj     argL = CC_DEP1;						\
1978fc937421c954ff9f707254f028b1fa0410c473dsewardj     argR = CC_DEP2 ^ oldC;	       				\
1988fc937421c954ff9f707254f028b1fa0410c473dsewardj     res  = (argL + argR) + oldC;				\
1998fc937421c954ff9f707254f028b1fa0410c473dsewardj     if (oldC)							\
2008fc937421c954ff9f707254f028b1fa0410c473dsewardj        cf = (DATA_UTYPE)res <= (DATA_UTYPE)argL;		\
2018fc937421c954ff9f707254f028b1fa0410c473dsewardj     else							\
2028fc937421c954ff9f707254f028b1fa0410c473dsewardj        cf = (DATA_UTYPE)res < (DATA_UTYPE)argL;		\
2038fc937421c954ff9f707254f028b1fa0410c473dsewardj     pf = parity_table[(UChar)res];				\
2048fc937421c954ff9f707254f028b1fa0410c473dsewardj     af = (res ^ argL ^ argR) & 0x10;				\
2058fc937421c954ff9f707254f028b1fa0410c473dsewardj     zf = ((DATA_UTYPE)res == 0) << 6;				\
2068fc937421c954ff9f707254f028b1fa0410c473dsewardj     sf = lshift(res, 8 - DATA_BITS) & 0x80;			\
2078fc937421c954ff9f707254f028b1fa0410c473dsewardj     of = lshift((argL ^ argR ^ -1) & (argL ^ res), 		\
2082a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                  12 - DATA_BITS) & X86G_CC_MASK_O;		\
2098fc937421c954ff9f707254f028b1fa0410c473dsewardj     return cf | pf | af | zf | sf | of;			\
2108fc937421c954ff9f707254f028b1fa0410c473dsewardj   }								\
2112ef5f2a829433c4ca17f33e1bf993cf16b9e347dsewardj}
2122ef5f2a829433c4ca17f33e1bf993cf16b9e347dsewardj
213b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
214b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
215df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_SBB(DATA_BITS,DATA_UTYPE)			\
216b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
217b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
218108e03fcb0a4ef42164235b1988aa540aa1e5298florian   { UInt cf, pf, af, zf, sf, of;				\
219108e03fcb0a4ef42164235b1988aa540aa1e5298florian     UInt argL, argR, oldC, res;		       		\
2202a9ad023890d3b34cf45e429df2a8ae88b419128sewardj     oldC = CC_NDEP & X86G_CC_MASK_C;				\
2218fc937421c954ff9f707254f028b1fa0410c473dsewardj     argL = CC_DEP1;						\
2228fc937421c954ff9f707254f028b1fa0410c473dsewardj     argR = CC_DEP2 ^ oldC;	       				\
2238fc937421c954ff9f707254f028b1fa0410c473dsewardj     res  = (argL - argR) - oldC;				\
2248fc937421c954ff9f707254f028b1fa0410c473dsewardj     if (oldC)							\
2258fc937421c954ff9f707254f028b1fa0410c473dsewardj        cf = (DATA_UTYPE)argL <= (DATA_UTYPE)argR;		\
2268fc937421c954ff9f707254f028b1fa0410c473dsewardj     else							\
2278fc937421c954ff9f707254f028b1fa0410c473dsewardj        cf = (DATA_UTYPE)argL < (DATA_UTYPE)argR;		\
2288fc937421c954ff9f707254f028b1fa0410c473dsewardj     pf = parity_table[(UChar)res];				\
2298fc937421c954ff9f707254f028b1fa0410c473dsewardj     af = (res ^ argL ^ argR) & 0x10;				\
2308fc937421c954ff9f707254f028b1fa0410c473dsewardj     zf = ((DATA_UTYPE)res == 0) << 6;				\
2318fc937421c954ff9f707254f028b1fa0410c473dsewardj     sf = lshift(res, 8 - DATA_BITS) & 0x80;			\
2328fc937421c954ff9f707254f028b1fa0410c473dsewardj     of = lshift((argL ^ argR) & (argL ^ res), 			\
2332a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                 12 - DATA_BITS) & X86G_CC_MASK_O;		\
2348fc937421c954ff9f707254f028b1fa0410c473dsewardj     return cf | pf | af | zf | sf | of;			\
2358fc937421c954ff9f707254f028b1fa0410c473dsewardj   }								\
236a238471814bd386aeb58a76718b41e68b1a794b2sewardj}
237a238471814bd386aeb58a76718b41e68b1a794b2sewardj
238b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
239b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
240df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_LOGIC(DATA_BITS,DATA_UTYPE)			\
241b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
242b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
243108e03fcb0a4ef42164235b1988aa540aa1e5298florian   { UInt cf, pf, af, zf, sf, of;				\
2448fc937421c954ff9f707254f028b1fa0410c473dsewardj     cf = 0;							\
2458fc937421c954ff9f707254f028b1fa0410c473dsewardj     pf = parity_table[(UChar)CC_DEP1];				\
2468fc937421c954ff9f707254f028b1fa0410c473dsewardj     af = 0;							\
2478fc937421c954ff9f707254f028b1fa0410c473dsewardj     zf = ((DATA_UTYPE)CC_DEP1 == 0) << 6;			\
2488fc937421c954ff9f707254f028b1fa0410c473dsewardj     sf = lshift(CC_DEP1, 8 - DATA_BITS) & 0x80;		\
2498fc937421c954ff9f707254f028b1fa0410c473dsewardj     of = 0;							\
2508fc937421c954ff9f707254f028b1fa0410c473dsewardj     return cf | pf | af | zf | sf | of;			\
2518fc937421c954ff9f707254f028b1fa0410c473dsewardj   }								\
252a238471814bd386aeb58a76718b41e68b1a794b2sewardj}
253a238471814bd386aeb58a76718b41e68b1a794b2sewardj
254b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
255b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
256df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_INC(DATA_BITS,DATA_UTYPE)			\
257b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
258b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
259108e03fcb0a4ef42164235b1988aa540aa1e5298florian   { UInt cf, pf, af, zf, sf, of;				\
260108e03fcb0a4ef42164235b1988aa540aa1e5298florian     UInt argL, argR, res;					\
2618fc937421c954ff9f707254f028b1fa0410c473dsewardj     res  = CC_DEP1;						\
2628fc937421c954ff9f707254f028b1fa0410c473dsewardj     argL = res - 1;						\
2638fc937421c954ff9f707254f028b1fa0410c473dsewardj     argR = 1;							\
2642a9ad023890d3b34cf45e429df2a8ae88b419128sewardj     cf = CC_NDEP & X86G_CC_MASK_C;				\
2658fc937421c954ff9f707254f028b1fa0410c473dsewardj     pf = parity_table[(UChar)res];				\
2668fc937421c954ff9f707254f028b1fa0410c473dsewardj     af = (res ^ argL ^ argR) & 0x10;				\
2678fc937421c954ff9f707254f028b1fa0410c473dsewardj     zf = ((DATA_UTYPE)res == 0) << 6;				\
2688fc937421c954ff9f707254f028b1fa0410c473dsewardj     sf = lshift(res, 8 - DATA_BITS) & 0x80;			\
2698fc937421c954ff9f707254f028b1fa0410c473dsewardj     of = ((res & DATA_MASK) == SIGN_MASK) << 11;		\
2708fc937421c954ff9f707254f028b1fa0410c473dsewardj     return cf | pf | af | zf | sf | of;			\
2718fc937421c954ff9f707254f028b1fa0410c473dsewardj   }								\
27289050e58e7bee40892662fe94231aefc33768cf5sewardj}
27389050e58e7bee40892662fe94231aefc33768cf5sewardj
274b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
275b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
276df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_DEC(DATA_BITS,DATA_UTYPE)			\
277b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
278b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
279108e03fcb0a4ef42164235b1988aa540aa1e5298florian   { UInt cf, pf, af, zf, sf, of;				\
280108e03fcb0a4ef42164235b1988aa540aa1e5298florian     UInt argL, argR, res;					\
2818fc937421c954ff9f707254f028b1fa0410c473dsewardj     res  = CC_DEP1;						\
2828fc937421c954ff9f707254f028b1fa0410c473dsewardj     argL = res + 1;						\
2838fc937421c954ff9f707254f028b1fa0410c473dsewardj     argR = 1;							\
2842a9ad023890d3b34cf45e429df2a8ae88b419128sewardj     cf = CC_NDEP & X86G_CC_MASK_C;				\
2858fc937421c954ff9f707254f028b1fa0410c473dsewardj     pf = parity_table[(UChar)res];				\
2868fc937421c954ff9f707254f028b1fa0410c473dsewardj     af = (res ^ argL ^ argR) & 0x10;				\
2878fc937421c954ff9f707254f028b1fa0410c473dsewardj     zf = ((DATA_UTYPE)res == 0) << 6;				\
2888fc937421c954ff9f707254f028b1fa0410c473dsewardj     sf = lshift(res, 8 - DATA_BITS) & 0x80;			\
2898fc937421c954ff9f707254f028b1fa0410c473dsewardj     of = ((res & DATA_MASK) 					\
2908fc937421c954ff9f707254f028b1fa0410c473dsewardj          == ((UInt)SIGN_MASK - 1)) << 11;			\
2918fc937421c954ff9f707254f028b1fa0410c473dsewardj     return cf | pf | af | zf | sf | of;			\
2928fc937421c954ff9f707254f028b1fa0410c473dsewardj   }								\
29389050e58e7bee40892662fe94231aefc33768cf5sewardj}
29489050e58e7bee40892662fe94231aefc33768cf5sewardj
295b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
296b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
297df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_SHL(DATA_BITS,DATA_UTYPE)			\
298b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
299b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
300108e03fcb0a4ef42164235b1988aa540aa1e5298florian   { UInt cf, pf, af, zf, sf, of;				\
3012a9ad023890d3b34cf45e429df2a8ae88b419128sewardj     cf = (CC_DEP2 >> (DATA_BITS - 1)) & X86G_CC_MASK_C;	\
3028fc937421c954ff9f707254f028b1fa0410c473dsewardj     pf = parity_table[(UChar)CC_DEP1];				\
3038fc937421c954ff9f707254f028b1fa0410c473dsewardj     af = 0; /* undefined */					\
3048fc937421c954ff9f707254f028b1fa0410c473dsewardj     zf = ((DATA_UTYPE)CC_DEP1 == 0) << 6;			\
3058fc937421c954ff9f707254f028b1fa0410c473dsewardj     sf = lshift(CC_DEP1, 8 - DATA_BITS) & 0x80;		\
3068fc937421c954ff9f707254f028b1fa0410c473dsewardj     /* of is defined if shift count == 1 */			\
3072a9ad023890d3b34cf45e429df2a8ae88b419128sewardj     of = lshift(CC_DEP2 ^ CC_DEP1, 12 - DATA_BITS) 		\
3082a9ad023890d3b34cf45e429df2a8ae88b419128sewardj          & X86G_CC_MASK_O;					\
3098fc937421c954ff9f707254f028b1fa0410c473dsewardj     return cf | pf | af | zf | sf | of;			\
3108fc937421c954ff9f707254f028b1fa0410c473dsewardj   }								\
3115f6303579435ddb8315e11c2f02c904b978782a0sewardj}
3125f6303579435ddb8315e11c2f02c904b978782a0sewardj
313b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
314b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
3152a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj#define ACTIONS_SHR(DATA_BITS,DATA_UTYPE)			\
316b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
317b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);  					\
318108e03fcb0a4ef42164235b1988aa540aa1e5298florian   { UInt cf, pf, af, zf, sf, of;				\
3198fc937421c954ff9f707254f028b1fa0410c473dsewardj     cf = CC_DEP2 & 1;						\
3208fc937421c954ff9f707254f028b1fa0410c473dsewardj     pf = parity_table[(UChar)CC_DEP1];				\
3218fc937421c954ff9f707254f028b1fa0410c473dsewardj     af = 0; /* undefined */					\
3228fc937421c954ff9f707254f028b1fa0410c473dsewardj     zf = ((DATA_UTYPE)CC_DEP1 == 0) << 6;			\
3238fc937421c954ff9f707254f028b1fa0410c473dsewardj     sf = lshift(CC_DEP1, 8 - DATA_BITS) & 0x80;		\
3248fc937421c954ff9f707254f028b1fa0410c473dsewardj     /* of is defined if shift count == 1 */			\
3252a9ad023890d3b34cf45e429df2a8ae88b419128sewardj     of = lshift(CC_DEP2 ^ CC_DEP1, 12 - DATA_BITS)		\
3262a9ad023890d3b34cf45e429df2a8ae88b419128sewardj          & X86G_CC_MASK_O;					\
3278fc937421c954ff9f707254f028b1fa0410c473dsewardj     return cf | pf | af | zf | sf | of;			\
3288fc937421c954ff9f707254f028b1fa0410c473dsewardj   }								\
3295f6303579435ddb8315e11c2f02c904b978782a0sewardj}
3305f6303579435ddb8315e11c2f02c904b978782a0sewardj
331b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
332b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
3338ee2de1f5f72c13120f59c0ca6ac8291219123dfsewardj/* ROL: cf' = lsb(result).  of' = msb(result) ^ lsb(result). */
3342a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj/* DEP1 = result, NDEP = old flags */
335df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_ROL(DATA_BITS,DATA_UTYPE)			\
336b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
337b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
338108e03fcb0a4ef42164235b1988aa540aa1e5298florian   { UInt fl 							\
3392a9ad023890d3b34cf45e429df2a8ae88b419128sewardj        = (CC_NDEP & ~(X86G_CC_MASK_O | X86G_CC_MASK_C))	\
3402a9ad023890d3b34cf45e429df2a8ae88b419128sewardj          | (X86G_CC_MASK_C & CC_DEP1)				\
3412a9ad023890d3b34cf45e429df2a8ae88b419128sewardj          | (X86G_CC_MASK_O & (lshift(CC_DEP1,  		\
3422a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                                      11-(DATA_BITS-1)) 	\
3438fc937421c954ff9f707254f028b1fa0410c473dsewardj                     ^ lshift(CC_DEP1, 11)));			\
3448fc937421c954ff9f707254f028b1fa0410c473dsewardj     return fl;							\
3458fc937421c954ff9f707254f028b1fa0410c473dsewardj   }								\
3468c7f1abe9e022f6382634efea09c9cac89ec6336sewardj}
3478c7f1abe9e022f6382634efea09c9cac89ec6336sewardj
348b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
349b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
3501813dbeb912870e9a544cae17a3fadbf8d2b0d55sewardj/* ROR: cf' = msb(result).  of' = msb(result) ^ msb-1(result). */
3512a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj/* DEP1 = result, NDEP = old flags */
352df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_ROR(DATA_BITS,DATA_UTYPE)			\
353b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
354b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
355108e03fcb0a4ef42164235b1988aa540aa1e5298florian   { UInt fl 							\
3562a9ad023890d3b34cf45e429df2a8ae88b419128sewardj        = (CC_NDEP & ~(X86G_CC_MASK_O | X86G_CC_MASK_C))	\
3572a9ad023890d3b34cf45e429df2a8ae88b419128sewardj          | (X86G_CC_MASK_C & (CC_DEP1 >> (DATA_BITS-1)))	\
3582a9ad023890d3b34cf45e429df2a8ae88b419128sewardj          | (X86G_CC_MASK_O & (lshift(CC_DEP1, 			\
3592a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                                      11-(DATA_BITS-1)) 	\
3608fc937421c954ff9f707254f028b1fa0410c473dsewardj                     ^ lshift(CC_DEP1, 11-(DATA_BITS-1)+1)));	\
3618fc937421c954ff9f707254f028b1fa0410c473dsewardj     return fl;							\
3628fc937421c954ff9f707254f028b1fa0410c473dsewardj   }								\
3631813dbeb912870e9a544cae17a3fadbf8d2b0d55sewardj}
3641813dbeb912870e9a544cae17a3fadbf8d2b0d55sewardj
365b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
366b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
3674a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj#define ACTIONS_UMUL(DATA_BITS, DATA_UTYPE,  NARROWtoU,         \
3684a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj                                DATA_U2TYPE, NARROWto2U)        \
3692a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj{                                                               \
3702a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj   PREAMBLE(DATA_BITS);                                         \
371108e03fcb0a4ef42164235b1988aa540aa1e5298florian   { UInt cf, pf, af, zf, sf, of;                               \
3728fc937421c954ff9f707254f028b1fa0410c473dsewardj     DATA_UTYPE  hi;                                            \
3734a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj     DATA_UTYPE  lo                                             \
3744a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj        = NARROWtoU( ((DATA_UTYPE)CC_DEP1)                      \
3754a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj                     * ((DATA_UTYPE)CC_DEP2) );                 \
3764a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj     DATA_U2TYPE rr                                             \
3774a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj        = NARROWto2U(                                           \
3784a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj             ((DATA_U2TYPE)((DATA_UTYPE)CC_DEP1))               \
3794a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj             * ((DATA_U2TYPE)((DATA_UTYPE)CC_DEP2)) );          \
3804a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj     hi = NARROWtoU(rr >>/*u*/ DATA_BITS);                      \
3818fc937421c954ff9f707254f028b1fa0410c473dsewardj     cf = (hi != 0);                                            \
3828fc937421c954ff9f707254f028b1fa0410c473dsewardj     pf = parity_table[(UChar)lo];                              \
3838fc937421c954ff9f707254f028b1fa0410c473dsewardj     af = 0; /* undefined */                                    \
3848fc937421c954ff9f707254f028b1fa0410c473dsewardj     zf = (lo == 0) << 6;                                       \
3858fc937421c954ff9f707254f028b1fa0410c473dsewardj     sf = lshift(lo, 8 - DATA_BITS) & 0x80;                     \
3868fc937421c954ff9f707254f028b1fa0410c473dsewardj     of = cf << 11;                                             \
3878fc937421c954ff9f707254f028b1fa0410c473dsewardj     return cf | pf | af | zf | sf | of;                        \
3888fc937421c954ff9f707254f028b1fa0410c473dsewardj   }								\
38956296d80c9e15ec59eebecf1c3aea9ebd4dac115sewardj}
39056296d80c9e15ec59eebecf1c3aea9ebd4dac115sewardj
391b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
392b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
3934a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj#define ACTIONS_SMUL(DATA_BITS, DATA_STYPE,  NARROWtoS,         \
3944a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj                                DATA_S2TYPE, NARROWto2S)        \
3952a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj{                                                               \
3962a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj   PREAMBLE(DATA_BITS);                                         \
397108e03fcb0a4ef42164235b1988aa540aa1e5298florian   { UInt cf, pf, af, zf, sf, of;                               \
3988fc937421c954ff9f707254f028b1fa0410c473dsewardj     DATA_STYPE  hi;                                            \
3994a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj     DATA_STYPE  lo                                             \
40045f8de626643cea67d0741f2b8a0b33dc69cbf84florian        = NARROWtoS( ((DATA_S2TYPE)(DATA_STYPE)CC_DEP1)         \
40145f8de626643cea67d0741f2b8a0b33dc69cbf84florian                     * ((DATA_S2TYPE)(DATA_STYPE)CC_DEP2) );    \
4024a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj     DATA_S2TYPE rr                                             \
4034a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj        = NARROWto2S(                                           \
4044a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj             ((DATA_S2TYPE)((DATA_STYPE)CC_DEP1))               \
4054a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj             * ((DATA_S2TYPE)((DATA_STYPE)CC_DEP2)) );          \
4064a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj     hi = NARROWtoS(rr >>/*s*/ DATA_BITS);                      \
4078fc937421c954ff9f707254f028b1fa0410c473dsewardj     cf = (hi != (lo >>/*s*/ (DATA_BITS-1)));                   \
4088fc937421c954ff9f707254f028b1fa0410c473dsewardj     pf = parity_table[(UChar)lo];                              \
4098fc937421c954ff9f707254f028b1fa0410c473dsewardj     af = 0; /* undefined */                                    \
4108fc937421c954ff9f707254f028b1fa0410c473dsewardj     zf = (lo == 0) << 6;                                       \
4118fc937421c954ff9f707254f028b1fa0410c473dsewardj     sf = lshift(lo, 8 - DATA_BITS) & 0x80;                     \
4128fc937421c954ff9f707254f028b1fa0410c473dsewardj     of = cf << 11;                                             \
4138fc937421c954ff9f707254f028b1fa0410c473dsewardj     return cf | pf | af | zf | sf | of;                        \
4148fc937421c954ff9f707254f028b1fa0410c473dsewardj   }								\
4157ed2295459ac5e788a98dd5570fef0d4645c27d4sewardj}
416741153c4301023a420ab45b8a10b8e1bac968822sewardj
41736ca51378f8851635df814230fa23f2c409b9eddsewardj
41884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#if PROFILE_EFLAGS
41984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
4209eab588e223e52b1e7b710ff1c0da7b032ab2837sewardjstatic Bool initted     = False;
421893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
422893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/* C flag, fast route */
423893a3302cc943e2ad1db421a8e6a753f82f532a7sewardjstatic UInt tabc_fast[X86G_CC_OP_NUMBER];
424893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/* C flag, slow route */
425893a3302cc943e2ad1db421a8e6a753f82f532a7sewardjstatic UInt tabc_slow[X86G_CC_OP_NUMBER];
426893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/* table for calculate_cond */
427893a3302cc943e2ad1db421a8e6a753f82f532a7sewardjstatic UInt tab_cond[X86G_CC_OP_NUMBER][16];
428893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/* total entry counts for calc_all, calc_c, calc_cond. */
42984ff0657940e62f38e618ea18bac6f27ce0e741fsewardjstatic UInt n_calc_all  = 0;
43084ff0657940e62f38e618ea18bac6f27ce0e741fsewardjstatic UInt n_calc_c    = 0;
431893a3302cc943e2ad1db421a8e6a753f82f532a7sewardjstatic UInt n_calc_cond = 0;
432893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
433893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj#define SHOW_COUNTS_NOW (0 == (0x3FFFFF & (n_calc_all+n_calc_c+n_calc_cond)))
434893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
43584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
43684ff0657940e62f38e618ea18bac6f27ce0e741fsewardjstatic void showCounts ( void )
43784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj{
43884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   Int op, co;
4395df8ab0739ec95e8de9d9f43fa0e68b3e7125554florian   HChar ch;
440a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   vex_printf("\nTotal calls: calc_all=%u   calc_cond=%u   calc_c=%u\n",
441893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj              n_calc_all, n_calc_cond, n_calc_c);
442893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
443893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_printf("      cSLOW  cFAST    O   NO    B   NB    Z   NZ   BE  NBE"
44484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj              "    S   NS    P   NP    L   NL   LE  NLE\n");
445893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_printf("     -----------------------------------------------------"
44684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj              "----------------------------------------\n");
4472a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   for (op = 0; op < X86G_CC_OP_NUMBER; op++) {
44884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
44984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      ch = ' ';
45093d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj      if (op > 0 && (op-1) % 3 == 0)
45193d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj         ch = 'B';
45293d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj      if (op > 0 && (op-1) % 3 == 1)
45393d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj         ch = 'W';
45484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      if (op > 0 && (op-1) % 3 == 2)
45584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         ch = 'L';
45684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
45784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      vex_printf("%2d%c: ", op, ch);
458a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj      vex_printf("%6u ", tabc_slow[op]);
459a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj      vex_printf("%6u ", tabc_fast[op]);
46084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      for (co = 0; co < 16; co++) {
461893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj         Int n = tab_cond[op][co];
46284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         if (n >= 1000) {
46384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj            vex_printf(" %3dK", n / 1000);
46484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         } else
46584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         if (n >= 0) {
466893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj            vex_printf(" %3d ", n );
46784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         } else {
46884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj            vex_printf("     ");
46984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         }
47084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
47184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      vex_printf("\n");
47284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   }
47384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   vex_printf("\n");
47484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj}
47584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
47684ff0657940e62f38e618ea18bac6f27ce0e741fsewardjstatic void initCounts ( void )
47784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj{
47884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   Int op, co;
47984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   initted = True;
4802a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   for (op = 0; op < X86G_CC_OP_NUMBER; op++) {
481893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      tabc_fast[op] = tabc_slow[op] = 0;
48284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      for (co = 0; co < 16; co++)
483893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj         tab_cond[op][co] = 0;
48484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   }
48584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj}
48684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
48784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#endif /* PROFILE_EFLAGS */
48884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
489893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
4909aebb0c3f7a7f43313786826f31402f2b733badfsewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
491893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/* Calculate all the 6 flags from the supplied thunk parameters.
492893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   Worker function, not directly called from generated code. */
493893a3302cc943e2ad1db421a8e6a753f82f532a7sewardjstatic
494893a3302cc943e2ad1db421a8e6a753f82f532a7sewardjUInt x86g_calculate_eflags_all_WRK ( UInt cc_op,
495893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj                                     UInt cc_dep1_formal,
496893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj                                     UInt cc_dep2_formal,
497893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj                                     UInt cc_ndep_formal )
49836ca51378f8851635df814230fa23f2c409b9eddsewardj{
49936ca51378f8851635df814230fa23f2c409b9eddsewardj   switch (cc_op) {
5002a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_COPY:
5012a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj         return cc_dep1_formal
5022a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                & (X86G_CC_MASK_O | X86G_CC_MASK_S | X86G_CC_MASK_Z
5032a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                   | X86G_CC_MASK_A | X86G_CC_MASK_C | X86G_CC_MASK_P);
50414731f22bf7759d6d23383ca870ac89d9581f1e9sewardj
5052a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_ADDB:   ACTIONS_ADD( 8,  UChar  );
5062a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_ADDW:   ACTIONS_ADD( 16, UShort );
5072a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_ADDL:   ACTIONS_ADD( 32, UInt   );
508a238471814bd386aeb58a76718b41e68b1a794b2sewardj
5092a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_ADCB:   ACTIONS_ADC( 8,  UChar  );
5102a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_ADCW:   ACTIONS_ADC( 16, UShort );
5112a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_ADCL:   ACTIONS_ADC( 32, UInt   );
512a238471814bd386aeb58a76718b41e68b1a794b2sewardj
5132a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_SUBB:   ACTIONS_SUB(  8, UChar  );
5142a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_SUBW:   ACTIONS_SUB( 16, UShort );
5152a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_SUBL:   ACTIONS_SUB( 32, UInt   );
516afc5787e1c4b8e9678669577cf57ac509c6cd6b5sewardj
5172a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_SBBB:   ACTIONS_SBB(  8, UChar  );
5182a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_SBBW:   ACTIONS_SBB( 16, UShort );
5192a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_SBBL:   ACTIONS_SBB( 32, UInt   );
520741153c4301023a420ab45b8a10b8e1bac968822sewardj
5212a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_LOGICB: ACTIONS_LOGIC(  8, UChar  );
5222a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_LOGICW: ACTIONS_LOGIC( 16, UShort );
5232a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_LOGICL: ACTIONS_LOGIC( 32, UInt   );
5245f6303579435ddb8315e11c2f02c904b978782a0sewardj
5252a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_INCB:   ACTIONS_INC(  8, UChar  );
5262a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_INCW:   ACTIONS_INC( 16, UShort );
5272a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_INCL:   ACTIONS_INC( 32, UInt   );
5281813dbeb912870e9a544cae17a3fadbf8d2b0d55sewardj
5292a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_DECB:   ACTIONS_DEC(  8, UChar  );
5302a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_DECW:   ACTIONS_DEC( 16, UShort );
5312a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_DECL:   ACTIONS_DEC( 32, UInt   );
5328c7f1abe9e022f6382634efea09c9cac89ec6336sewardj
5332a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_SHLB:   ACTIONS_SHL(  8, UChar  );
5342a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_SHLW:   ACTIONS_SHL( 16, UShort );
5352a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_SHLL:   ACTIONS_SHL( 32, UInt   );
5368c7f1abe9e022f6382634efea09c9cac89ec6336sewardj
5372a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_SHRB:   ACTIONS_SHR(  8, UChar  );
5382a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_SHRW:   ACTIONS_SHR( 16, UShort );
5392a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_SHRL:   ACTIONS_SHR( 32, UInt   );
5401813dbeb912870e9a544cae17a3fadbf8d2b0d55sewardj
5412a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_ROLB:   ACTIONS_ROL(  8, UChar  );
5422a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_ROLW:   ACTIONS_ROL( 16, UShort );
5432a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_ROLL:   ACTIONS_ROL( 32, UInt   );
544750f407b6be1aac303964a219acf0a6de8b8c4dasewardj
5452a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_RORB:   ACTIONS_ROR(  8, UChar  );
5462a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_RORW:   ACTIONS_ROR( 16, UShort );
5472a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_RORL:   ACTIONS_ROR( 32, UInt   );
5487ed2295459ac5e788a98dd5570fef0d4645c27d4sewardj
5494a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj      case X86G_CC_OP_UMULB:  ACTIONS_UMUL(  8, UChar,  toUChar,
5504a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj                                                UShort, toUShort );
5514a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj      case X86G_CC_OP_UMULW:  ACTIONS_UMUL( 16, UShort, toUShort,
5524a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj                                                UInt,   toUInt );
5534a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj      case X86G_CC_OP_UMULL:  ACTIONS_UMUL( 32, UInt,   toUInt,
5544a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj                                                ULong,  idULong );
5554a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj
5564a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj      case X86G_CC_OP_SMULB:  ACTIONS_SMUL(  8, Char,   toUChar,
5574a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj                                                Short,  toUShort );
5584a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj      case X86G_CC_OP_SMULW:  ACTIONS_SMUL( 16, Short,  toUShort,
5594a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj                                                Int,    toUInt   );
5604a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj      case X86G_CC_OP_SMULL:  ACTIONS_SMUL( 32, Int,    toUInt,
5614a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj                                                Long,   idULong );
562741153c4301023a420ab45b8a10b8e1bac968822sewardj
56336ca51378f8851635df814230fa23f2c409b9eddsewardj      default:
56436ca51378f8851635df814230fa23f2c409b9eddsewardj         /* shouldn't really make these calls from generated code */
565893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj         vex_printf("x86g_calculate_eflags_all_WRK(X86)"
566a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj                    "( %u, 0x%x, 0x%x, 0x%x )\n",
5672a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj                    cc_op, cc_dep1_formal, cc_dep2_formal, cc_ndep_formal );
568893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj         vpanic("x86g_calculate_eflags_all_WRK(X86)");
56936ca51378f8851635df814230fa23f2c409b9eddsewardj   }
57036ca51378f8851635df814230fa23f2c409b9eddsewardj}
57136ca51378f8851635df814230fa23f2c409b9eddsewardj
572b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
5739aebb0c3f7a7f43313786826f31402f2b733badfsewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
574893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/* Calculate all the 6 flags from the supplied thunk parameters. */
575893a3302cc943e2ad1db421a8e6a753f82f532a7sewardjUInt x86g_calculate_eflags_all ( UInt cc_op,
576893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj                                 UInt cc_dep1,
577893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj                                 UInt cc_dep2,
578893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj                                 UInt cc_ndep )
579893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj{
580893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj#  if PROFILE_EFLAGS
581893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   if (!initted) initCounts();
582893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   n_calc_all++;
583893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   if (SHOW_COUNTS_NOW) showCounts();
584893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj#  endif
585893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   return
586893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      x86g_calculate_eflags_all_WRK ( cc_op, cc_dep1, cc_dep2, cc_ndep );
587893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj}
588893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
589893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
590893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
591b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/* Calculate just the carry flag from the supplied thunk parameters. */
59203d91140809def2f5afc04b0cc9beb0f4f0a1b13sewardjVEX_REGPARM(3)
5932a9ad023890d3b34cf45e429df2a8ae88b419128sewardjUInt x86g_calculate_eflags_c ( UInt cc_op,
5942a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                               UInt cc_dep1,
5952a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                               UInt cc_dep2,
5962a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                               UInt cc_ndep )
59736ca51378f8851635df814230fa23f2c409b9eddsewardj{
598893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj#  if PROFILE_EFLAGS
599893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   if (!initted) initCounts();
600893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   n_calc_c++;
601893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   tabc_fast[cc_op]++;
602893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   if (SHOW_COUNTS_NOW) showCounts();
603893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj#  endif
604893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
6059eab588e223e52b1e7b710ff1c0da7b032ab2837sewardj   /* Fast-case some common ones. */
60643c46951628d616290f7245c3af2f9a652180806sewardj   switch (cc_op) {
6072a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_LOGICL:
6082a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_LOGICW:
6092a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_LOGICB:
61043c46951628d616290f7245c3af2f9a652180806sewardj         return 0;
6112a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_SUBL:
61293d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj         return ((UInt)cc_dep1) < ((UInt)cc_dep2)
6132a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                   ? X86G_CC_MASK_C : 0;
614893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      case X86G_CC_OP_SUBW:
615893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj         return ((UInt)(cc_dep1 & 0xFFFF)) < ((UInt)(cc_dep2 & 0xFFFF))
616893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj                   ? X86G_CC_MASK_C : 0;
6172a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_SUBB:
61893d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj         return ((UInt)(cc_dep1 & 0xFF)) < ((UInt)(cc_dep2 & 0xFF))
6192a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                   ? X86G_CC_MASK_C : 0;
620e9ba4328f2afb94bc8474e9a7205e50ed9ac73fcsewardj      case X86G_CC_OP_INCL:
6212a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86G_CC_OP_DECL:
622e9ba4328f2afb94bc8474e9a7205e50ed9ac73fcsewardj         return cc_ndep & X86G_CC_MASK_C;
62343c46951628d616290f7245c3af2f9a652180806sewardj      default:
62443c46951628d616290f7245c3af2f9a652180806sewardj         break;
62543c46951628d616290f7245c3af2f9a652180806sewardj   }
6269eab588e223e52b1e7b710ff1c0da7b032ab2837sewardj
62784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  if PROFILE_EFLAGS
628893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   tabc_fast[cc_op]--;
629893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   tabc_slow[cc_op]++;
63084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  endif
631893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
632893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   return x86g_calculate_eflags_all_WRK(cc_op,cc_dep1,cc_dep2,cc_ndep)
6332a9ad023890d3b34cf45e429df2a8ae88b419128sewardj          & X86G_CC_MASK_C;
63436ca51378f8851635df814230fa23f2c409b9eddsewardj}
63536ca51378f8851635df814230fa23f2c409b9eddsewardj
63636ca51378f8851635df814230fa23f2c409b9eddsewardj
6379aebb0c3f7a7f43313786826f31402f2b733badfsewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
63884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj/* returns 1 or 0 */
6392a9ad023890d3b34cf45e429df2a8ae88b419128sewardjUInt x86g_calculate_condition ( UInt/*X86Condcode*/ cond,
6402a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                                UInt cc_op,
6412a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                                UInt cc_dep1,
6422a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                                UInt cc_dep2,
6432a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                                UInt cc_ndep )
6442a9ad023890d3b34cf45e429df2a8ae88b419128sewardj{
645893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   UInt eflags = x86g_calculate_eflags_all_WRK(cc_op, cc_dep1,
646893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj                                               cc_dep2, cc_ndep);
64784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   UInt of,sf,zf,cf,pf;
64884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   UInt inv = cond & 1;
64984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
65084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  if PROFILE_EFLAGS
651893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   if (!initted) initCounts();
652893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   tab_cond[cc_op][cond]++;
65384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   n_calc_cond++;
654893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   if (SHOW_COUNTS_NOW) showCounts();
65584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  endif
65684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
65784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   switch (cond) {
6582a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86CondNO:
6592a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86CondO: /* OF == 1 */
6602a9ad023890d3b34cf45e429df2a8ae88b419128sewardj         of = eflags >> X86G_CC_SHIFT_O;
66184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return 1 & (inv ^ of);
66284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
6632a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86CondNZ:
6642a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86CondZ: /* ZF == 1 */
6652a9ad023890d3b34cf45e429df2a8ae88b419128sewardj         zf = eflags >> X86G_CC_SHIFT_Z;
66684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return 1 & (inv ^ zf);
66784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
6682a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86CondNB:
6692a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86CondB: /* CF == 1 */
6702a9ad023890d3b34cf45e429df2a8ae88b419128sewardj         cf = eflags >> X86G_CC_SHIFT_C;
67184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return 1 & (inv ^ cf);
67284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         break;
67384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
6742a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86CondNBE:
6752a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86CondBE: /* (CF or ZF) == 1 */
6762a9ad023890d3b34cf45e429df2a8ae88b419128sewardj         cf = eflags >> X86G_CC_SHIFT_C;
6772a9ad023890d3b34cf45e429df2a8ae88b419128sewardj         zf = eflags >> X86G_CC_SHIFT_Z;
67884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return 1 & (inv ^ (cf | zf));
67984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         break;
68084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
6812a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86CondNS:
6822a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86CondS: /* SF == 1 */
6832a9ad023890d3b34cf45e429df2a8ae88b419128sewardj         sf = eflags >> X86G_CC_SHIFT_S;
68484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return 1 & (inv ^ sf);
68584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
6862a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86CondNP:
6872a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86CondP: /* PF == 1 */
6882a9ad023890d3b34cf45e429df2a8ae88b419128sewardj         pf = eflags >> X86G_CC_SHIFT_P;
68984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return 1 & (inv ^ pf);
69084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
6912a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86CondNL:
6922a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86CondL: /* (SF xor OF) == 1 */
6932a9ad023890d3b34cf45e429df2a8ae88b419128sewardj         sf = eflags >> X86G_CC_SHIFT_S;
6942a9ad023890d3b34cf45e429df2a8ae88b419128sewardj         of = eflags >> X86G_CC_SHIFT_O;
69584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return 1 & (inv ^ (sf ^ of));
69684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         break;
69784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
6982a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86CondNLE:
6992a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      case X86CondLE: /* ((SF xor OF) or ZF)  == 1 */
7002a9ad023890d3b34cf45e429df2a8ae88b419128sewardj         sf = eflags >> X86G_CC_SHIFT_S;
7012a9ad023890d3b34cf45e429df2a8ae88b419128sewardj         of = eflags >> X86G_CC_SHIFT_O;
7022a9ad023890d3b34cf45e429df2a8ae88b419128sewardj         zf = eflags >> X86G_CC_SHIFT_Z;
70384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return 1 & (inv ^ ((sf ^ of) | zf));
70484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         break;
70584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
70684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      default:
70784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         /* shouldn't really make these calls from generated code */
708a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj         vex_printf("x86g_calculate_condition( %u, %u, 0x%x, 0x%x, 0x%x )\n",
7092a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj                    cond, cc_op, cc_dep1, cc_dep2, cc_ndep );
710893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj         vpanic("x86g_calculate_condition");
71184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   }
71284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj}
71384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
71484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
715893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/* VISIBLE TO LIBVEX CLIENT */
716efa834abaded25c8aff2f3923e476ef7cc1d0396florianUInt LibVEX_GuestX86_get_eflags ( /*IN*/const VexGuestX86State* vex_state )
717893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj{
718893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   UInt eflags = x86g_calculate_eflags_all_WRK(
719893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj                    vex_state->guest_CC_OP,
720893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj                    vex_state->guest_CC_DEP1,
721893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj                    vex_state->guest_CC_DEP2,
722893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj                    vex_state->guest_CC_NDEP
723893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj                 );
724893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   UInt dflag = vex_state->guest_DFLAG;
725893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vassert(dflag == 1 || dflag == 0xFFFFFFFF);
726893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   if (dflag == 0xFFFFFFFF)
727893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      eflags |= (1<<10);
728893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   if (vex_state->guest_IDFLAG == 1)
729893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      eflags |= (1<<21);
7306d26984a0df6a7d20b658bac6edf869eb872cca3sewardj   if (vex_state->guest_ACFLAG == 1)
7316d26984a0df6a7d20b658bac6edf869eb872cca3sewardj      eflags |= (1<<18);
732893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
733893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   return eflags;
734893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj}
735893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
736f32d5a5dd44a6d490c901949114d86441c24ef92sewardj/* VISIBLE TO LIBVEX CLIENT */
737f32d5a5dd44a6d490c901949114d86441c24ef92sewardjvoid
738f32d5a5dd44a6d490c901949114d86441c24ef92sewardjLibVEX_GuestX86_put_eflag_c ( UInt new_carry_flag,
739f32d5a5dd44a6d490c901949114d86441c24ef92sewardj                              /*MOD*/VexGuestX86State* vex_state )
740f32d5a5dd44a6d490c901949114d86441c24ef92sewardj{
741f32d5a5dd44a6d490c901949114d86441c24ef92sewardj   UInt oszacp = x86g_calculate_eflags_all_WRK(
742f32d5a5dd44a6d490c901949114d86441c24ef92sewardj                    vex_state->guest_CC_OP,
743f32d5a5dd44a6d490c901949114d86441c24ef92sewardj                    vex_state->guest_CC_DEP1,
744f32d5a5dd44a6d490c901949114d86441c24ef92sewardj                    vex_state->guest_CC_DEP2,
745f32d5a5dd44a6d490c901949114d86441c24ef92sewardj                    vex_state->guest_CC_NDEP
746f32d5a5dd44a6d490c901949114d86441c24ef92sewardj                 );
747f32d5a5dd44a6d490c901949114d86441c24ef92sewardj   if (new_carry_flag & 1) {
748f32d5a5dd44a6d490c901949114d86441c24ef92sewardj      oszacp |= X86G_CC_MASK_C;
749f32d5a5dd44a6d490c901949114d86441c24ef92sewardj   } else {
750f32d5a5dd44a6d490c901949114d86441c24ef92sewardj      oszacp &= ~X86G_CC_MASK_C;
751f32d5a5dd44a6d490c901949114d86441c24ef92sewardj   }
752f32d5a5dd44a6d490c901949114d86441c24ef92sewardj   vex_state->guest_CC_OP   = X86G_CC_OP_COPY;
753f32d5a5dd44a6d490c901949114d86441c24ef92sewardj   vex_state->guest_CC_DEP1 = oszacp;
754f32d5a5dd44a6d490c901949114d86441c24ef92sewardj   vex_state->guest_CC_DEP2 = 0;
755f32d5a5dd44a6d490c901949114d86441c24ef92sewardj   vex_state->guest_CC_NDEP = 0;
756f32d5a5dd44a6d490c901949114d86441c24ef92sewardj}
757f32d5a5dd44a6d490c901949114d86441c24ef92sewardj
758893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
759893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/*---------------------------------------------------------------*/
760893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/*--- %eflags translation-time function specialisers.         ---*/
761893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/*--- These help iropt specialise calls the above run-time    ---*/
762893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/*--- %eflags functions.                                      ---*/
763893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/*---------------------------------------------------------------*/
764893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
76584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj/* Used by the optimiser to try specialisations.  Returns an
76684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   equivalent expression, or NULL if none. */
76784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
768908854045e8ebf1495663bb50801c32d6f729bbesewardjstatic inline Bool isU32 ( IRExpr* e, UInt n )
76984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj{
770a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   return
771a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj      toBool( e->tag == Iex_Const
772a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj              && e->Iex.Const.con->tag == Ico_U32
773a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj              && e->Iex.Const.con->Ico.U32 == n );
77484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj}
77584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
7761ff4756e1731485e6bf3cd96717cd8398daec1f2florianIRExpr* guest_x86_spechelper ( const HChar* function_name,
777be9179130bdfb61d0e03ecb32eced8dd5c7bfc74sewardj                               IRExpr** args,
778be9179130bdfb61d0e03ecb32eced8dd5c7bfc74sewardj                               IRStmt** precedingStmts,
779be9179130bdfb61d0e03ecb32eced8dd5c7bfc74sewardj                               Int      n_precedingStmts )
78084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj{
78184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  define unop(_op,_a1) IRExpr_Unop((_op),(_a1))
78284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  define binop(_op,_a1,_a2) IRExpr_Binop((_op),(_a1),(_a2))
78384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  define mkU32(_n) IRExpr_Const(IRConst_U32(_n))
7844afab82eb869f21ccabc3efb5b93f31a5c343956sewardj#  define mkU8(_n)  IRExpr_Const(IRConst_U8(_n))
78584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
78684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   Int i, arity = 0;
78784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   for (i = 0; args[i]; i++)
78884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      arity++;
78984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  if 0
79084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   vex_printf("spec request:\n");
79184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   vex_printf("   %s  ", function_name);
79284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   for (i = 0; i < arity; i++) {
79384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      vex_printf("  ");
79484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      ppIRExpr(args[i]);
79584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   }
79684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   vex_printf("\n");
79784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  endif
79893d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj
7993835288ac63bb755c0e1d2f3142a13416dcb64c6sewardj   /* --------- specialising "x86g_calculate_condition" --------- */
80093d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj
8013835288ac63bb755c0e1d2f3142a13416dcb64c6sewardj   if (vex_streq(function_name, "x86g_calculate_condition")) {
80284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      /* specialise calls to above "calculate condition" function */
803a8415ffe6c6f0e73519301a55026a4071c701fd1sewardj      IRExpr *cond, *cc_op, *cc_dep1, *cc_dep2;
80493d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj      vassert(arity == 5);
80593d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj      cond    = args[0];
80693d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj      cc_op   = args[1];
80793d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj      cc_dep1 = args[2];
80893d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj      cc_dep2 = args[3];
80984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
810d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj      /*---------------- ADDL ----------------*/
811d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj
8122a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_ADDL) && isU32(cond, X86CondZ)) {
813d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj         /* long add, then Z --> test (dst+src == 0) */
814d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj         return unop(Iop_1Uto32,
815d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj                     binop(Iop_CmpEQ32,
816d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj                           binop(Iop_Add32, cc_dep1, cc_dep2),
817d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj                           mkU32(0)));
818d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj      }
819d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj
82046ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      /*---------------- SUBL ----------------*/
82146ccb51aff085d180120d310c0be2fe6c86e1b65sewardj
8222a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_SUBL) && isU32(cond, X86CondZ)) {
82346ccb51aff085d180120d310c0be2fe6c86e1b65sewardj         /* long sub/cmp, then Z --> test dst==src */
82484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return unop(Iop_1Uto32,
82593d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj                     binop(Iop_CmpEQ32, cc_dep1, cc_dep2));
82646ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      }
82766f7a54d5425853debcb5fe77be1021f0c2b6620sewardj      if (isU32(cc_op, X86G_CC_OP_SUBL) && isU32(cond, X86CondNZ)) {
82866f7a54d5425853debcb5fe77be1021f0c2b6620sewardj         /* long sub/cmp, then NZ --> test dst!=src */
82966f7a54d5425853debcb5fe77be1021f0c2b6620sewardj         return unop(Iop_1Uto32,
83066f7a54d5425853debcb5fe77be1021f0c2b6620sewardj                     binop(Iop_CmpNE32, cc_dep1, cc_dep2));
83166f7a54d5425853debcb5fe77be1021f0c2b6620sewardj      }
83266f7a54d5425853debcb5fe77be1021f0c2b6620sewardj
8332a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_SUBL) && isU32(cond, X86CondL)) {
83446ccb51aff085d180120d310c0be2fe6c86e1b65sewardj         /* long sub/cmp, then L (signed less than)
83546ccb51aff085d180120d310c0be2fe6c86e1b65sewardj            --> test dst <s src */
83646ccb51aff085d180120d310c0be2fe6c86e1b65sewardj         return unop(Iop_1Uto32,
83793d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj                     binop(Iop_CmpLT32S, cc_dep1, cc_dep2));
83846ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      }
8398a81970fd71af3fa5725b85c65c7540a441071bfsewardj      if (isU32(cc_op, X86G_CC_OP_SUBL) && isU32(cond, X86CondNL)) {
8408a81970fd71af3fa5725b85c65c7540a441071bfsewardj         /* long sub/cmp, then NL (signed greater than or equal)
8418a81970fd71af3fa5725b85c65c7540a441071bfsewardj            --> test !(dst <s src) */
8428a81970fd71af3fa5725b85c65c7540a441071bfsewardj         return binop(Iop_Xor32,
8438a81970fd71af3fa5725b85c65c7540a441071bfsewardj                      unop(Iop_1Uto32,
8448a81970fd71af3fa5725b85c65c7540a441071bfsewardj                           binop(Iop_CmpLT32S, cc_dep1, cc_dep2)),
8458a81970fd71af3fa5725b85c65c7540a441071bfsewardj                      mkU32(1));
8468a81970fd71af3fa5725b85c65c7540a441071bfsewardj      }
8478a81970fd71af3fa5725b85c65c7540a441071bfsewardj
8482a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_SUBL) && isU32(cond, X86CondLE)) {
84946ccb51aff085d180120d310c0be2fe6c86e1b65sewardj         /* long sub/cmp, then LE (signed less than or equal)
85046ccb51aff085d180120d310c0be2fe6c86e1b65sewardj            --> test dst <=s src */
85146ccb51aff085d180120d310c0be2fe6c86e1b65sewardj         return unop(Iop_1Uto32,
85293d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj                     binop(Iop_CmpLE32S, cc_dep1, cc_dep2));
85346ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      }
8542eb9ffadd7f9dd2b0273ee6c4554615df8502e2fsewardj      if (isU32(cc_op, X86G_CC_OP_SUBL) && isU32(cond, X86CondNLE)) {
855c7be3eb57d2dc65ee00c6011d0ea8c8a1dc57b79sewardj         /* long sub/cmp, then NLE (signed not less than or equal)
8562eb9ffadd7f9dd2b0273ee6c4554615df8502e2fsewardj            --> test dst >s src
8572eb9ffadd7f9dd2b0273ee6c4554615df8502e2fsewardj            --> test !(dst <=s src) */
8582eb9ffadd7f9dd2b0273ee6c4554615df8502e2fsewardj         return binop(Iop_Xor32,
8592eb9ffadd7f9dd2b0273ee6c4554615df8502e2fsewardj                      unop(Iop_1Uto32,
8602eb9ffadd7f9dd2b0273ee6c4554615df8502e2fsewardj                           binop(Iop_CmpLE32S, cc_dep1, cc_dep2)),
8612eb9ffadd7f9dd2b0273ee6c4554615df8502e2fsewardj                      mkU32(1));
8622eb9ffadd7f9dd2b0273ee6c4554615df8502e2fsewardj      }
8632eb9ffadd7f9dd2b0273ee6c4554615df8502e2fsewardj
8642a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_SUBL) && isU32(cond, X86CondBE)) {
86546ccb51aff085d180120d310c0be2fe6c86e1b65sewardj         /* long sub/cmp, then BE (unsigned less than or equal)
86646ccb51aff085d180120d310c0be2fe6c86e1b65sewardj            --> test dst <=u src */
86746ccb51aff085d180120d310c0be2fe6c86e1b65sewardj         return unop(Iop_1Uto32,
86893d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj                     binop(Iop_CmpLE32U, cc_dep1, cc_dep2));
86946ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      }
8708a81970fd71af3fa5725b85c65c7540a441071bfsewardj      if (isU32(cc_op, X86G_CC_OP_SUBL) && isU32(cond, X86CondNBE)) {
8718a81970fd71af3fa5725b85c65c7540a441071bfsewardj         /* long sub/cmp, then BE (unsigned greater than)
8728a81970fd71af3fa5725b85c65c7540a441071bfsewardj            --> test !(dst <=u src) */
8738a81970fd71af3fa5725b85c65c7540a441071bfsewardj         return binop(Iop_Xor32,
8748a81970fd71af3fa5725b85c65c7540a441071bfsewardj                      unop(Iop_1Uto32,
8758a81970fd71af3fa5725b85c65c7540a441071bfsewardj                           binop(Iop_CmpLE32U, cc_dep1, cc_dep2)),
8768a81970fd71af3fa5725b85c65c7540a441071bfsewardj                      mkU32(1));
8778a81970fd71af3fa5725b85c65c7540a441071bfsewardj      }
8788a81970fd71af3fa5725b85c65c7540a441071bfsewardj
8792a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_SUBL) && isU32(cond, X86CondB)) {
88046ccb51aff085d180120d310c0be2fe6c86e1b65sewardj         /* long sub/cmp, then B (unsigned less than)
88146ccb51aff085d180120d310c0be2fe6c86e1b65sewardj            --> test dst <u src */
88246ccb51aff085d180120d310c0be2fe6c86e1b65sewardj         return unop(Iop_1Uto32,
883e664ec4b9f27ed7d7ca87a2d4188fd479059351csewardj                     binop(Iop_CmpLT32U, cc_dep1, cc_dep2));
88484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
8858a81970fd71af3fa5725b85c65c7540a441071bfsewardj      if (isU32(cc_op, X86G_CC_OP_SUBL) && isU32(cond, X86CondNB)) {
8868a81970fd71af3fa5725b85c65c7540a441071bfsewardj         /* long sub/cmp, then NB (unsigned greater than or equal)
8878a81970fd71af3fa5725b85c65c7540a441071bfsewardj            --> test !(dst <u src) */
8888a81970fd71af3fa5725b85c65c7540a441071bfsewardj         return binop(Iop_Xor32,
8898a81970fd71af3fa5725b85c65c7540a441071bfsewardj                      unop(Iop_1Uto32,
8908a81970fd71af3fa5725b85c65c7540a441071bfsewardj                           binop(Iop_CmpLT32U, cc_dep1, cc_dep2)),
8918a81970fd71af3fa5725b85c65c7540a441071bfsewardj                      mkU32(1));
8928a81970fd71af3fa5725b85c65c7540a441071bfsewardj      }
8938a81970fd71af3fa5725b85c65c7540a441071bfsewardj
894e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj      if (isU32(cc_op, X86G_CC_OP_SUBL) && isU32(cond, X86CondS)) {
8958a81970fd71af3fa5725b85c65c7540a441071bfsewardj         /* long sub/cmp, then S (negative) --> test (dst-src <s 0) */
896e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj         return unop(Iop_1Uto32,
897e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj                     binop(Iop_CmpLT32S,
898e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj                           binop(Iop_Sub32, cc_dep1, cc_dep2),
899e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj                           mkU32(0)));
900e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj      }
9011ee3e18f5fed89dd9c07c7362aabead931c1ea19sewardj      if (isU32(cc_op, X86G_CC_OP_SUBL) && isU32(cond, X86CondNS)) {
9028a81970fd71af3fa5725b85c65c7540a441071bfsewardj         /* long sub/cmp, then NS (not negative) --> test !(dst-src <s 0) */
9038a81970fd71af3fa5725b85c65c7540a441071bfsewardj         return binop(Iop_Xor32,
9048a81970fd71af3fa5725b85c65c7540a441071bfsewardj                      unop(Iop_1Uto32,
9058a81970fd71af3fa5725b85c65c7540a441071bfsewardj                           binop(Iop_CmpLT32S,
9068a81970fd71af3fa5725b85c65c7540a441071bfsewardj                                 binop(Iop_Sub32, cc_dep1, cc_dep2),
9078a81970fd71af3fa5725b85c65c7540a441071bfsewardj                                 mkU32(0))),
9088a81970fd71af3fa5725b85c65c7540a441071bfsewardj                      mkU32(1));
9091ee3e18f5fed89dd9c07c7362aabead931c1ea19sewardj      }
9101ee3e18f5fed89dd9c07c7362aabead931c1ea19sewardj
91146ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      /*---------------- SUBW ----------------*/
91246ccb51aff085d180120d310c0be2fe6c86e1b65sewardj
9132a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_SUBW) && isU32(cond, X86CondZ)) {
914c5fd97216fa0f530828d517a5db46b64f5ae986fsewardj         /* word sub/cmp, then Z --> test dst==src */
915b9c5cf639b3b21b972599d27207a033afc76ef67sewardj         return unop(Iop_1Uto32,
916b9c5cf639b3b21b972599d27207a033afc76ef67sewardj                     binop(Iop_CmpEQ16,
9177e6644c38b3e0148ff95c2f6f4667f54148b611esewardj                           unop(Iop_32to16,cc_dep1),
9187e6644c38b3e0148ff95c2f6f4667f54148b611esewardj                           unop(Iop_32to16,cc_dep2)));
919b9c5cf639b3b21b972599d27207a033afc76ef67sewardj      }
920beb5291313fcd91543dd19c76a9e04d8b0e94af9sewardj      if (isU32(cc_op, X86G_CC_OP_SUBW) && isU32(cond, X86CondNZ)) {
921beb5291313fcd91543dd19c76a9e04d8b0e94af9sewardj         /* word sub/cmp, then NZ --> test dst!=src */
922beb5291313fcd91543dd19c76a9e04d8b0e94af9sewardj         return unop(Iop_1Uto32,
923beb5291313fcd91543dd19c76a9e04d8b0e94af9sewardj                     binop(Iop_CmpNE16,
924beb5291313fcd91543dd19c76a9e04d8b0e94af9sewardj                           unop(Iop_32to16,cc_dep1),
925beb5291313fcd91543dd19c76a9e04d8b0e94af9sewardj                           unop(Iop_32to16,cc_dep2)));
926beb5291313fcd91543dd19c76a9e04d8b0e94af9sewardj      }
927b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
92846ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      /*---------------- SUBB ----------------*/
9297e6644c38b3e0148ff95c2f6f4667f54148b611esewardj
9302a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_SUBB) && isU32(cond, X86CondZ)) {
931b9c5cf639b3b21b972599d27207a033afc76ef67sewardj         /* byte sub/cmp, then Z --> test dst==src */
93284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return unop(Iop_1Uto32,
933b9c5cf639b3b21b972599d27207a033afc76ef67sewardj                     binop(Iop_CmpEQ8,
93493d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj                           unop(Iop_32to8,cc_dep1),
93593d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj                           unop(Iop_32to8,cc_dep2)));
93684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
9372a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_SUBB) && isU32(cond, X86CondNZ)) {
9387e5b7cdbfa65376488d58e4e6d8f13d974f7a8bcsewardj         /* byte sub/cmp, then NZ --> test dst!=src */
93984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return unop(Iop_1Uto32,
940b9c5cf639b3b21b972599d27207a033afc76ef67sewardj                     binop(Iop_CmpNE8,
94193d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj                           unop(Iop_32to8,cc_dep1),
94293d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj                           unop(Iop_32to8,cc_dep2)));
943b9c5cf639b3b21b972599d27207a033afc76ef67sewardj      }
94422419b8f4f2c0104549ca9954f68e190b911d1a0sewardj
9452a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_SUBB) && isU32(cond, X86CondNBE)) {
946c5fd97216fa0f530828d517a5db46b64f5ae986fsewardj         /* byte sub/cmp, then NBE (unsigned greater than)
947dc12d39f7112dd57bae91b1f87963d0acaa2e71asewardj            --> test src <u dst */
9487e5b7cdbfa65376488d58e4e6d8f13d974f7a8bcsewardj         /* Note, args are opposite way round from the usual */
949b9c5cf639b3b21b972599d27207a033afc76ef67sewardj         return unop(Iop_1Uto32,
950b9c5cf639b3b21b972599d27207a033afc76ef67sewardj                     binop(Iop_CmpLT32U,
9517e5b7cdbfa65376488d58e4e6d8f13d974f7a8bcsewardj                           binop(Iop_And32,cc_dep2,mkU32(0xFF)),
9527e5b7cdbfa65376488d58e4e6d8f13d974f7a8bcsewardj			   binop(Iop_And32,cc_dep1,mkU32(0xFF))));
95384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
95484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
955908854045e8ebf1495663bb50801c32d6f729bbesewardj      if (isU32(cc_op, X86G_CC_OP_SUBB) && isU32(cond, X86CondS)
956908854045e8ebf1495663bb50801c32d6f729bbesewardj                                        && isU32(cc_dep2, 0)) {
957c5fd97216fa0f530828d517a5db46b64f5ae986fsewardj         /* byte sub/cmp of zero, then S --> test (dst-0 <s 0)
958c5fd97216fa0f530828d517a5db46b64f5ae986fsewardj                                         --> test dst <s 0
959c5fd97216fa0f530828d517a5db46b64f5ae986fsewardj                                         --> (UInt)dst[7]
960908854045e8ebf1495663bb50801c32d6f729bbesewardj            This is yet another scheme by which gcc figures out if the
961908854045e8ebf1495663bb50801c32d6f729bbesewardj            top bit of a byte is 1 or 0.  See also LOGICB/CondS below. */
962908854045e8ebf1495663bb50801c32d6f729bbesewardj         /* Note: isU32(cc_dep2, 0) is correct, even though this is
963908854045e8ebf1495663bb50801c32d6f729bbesewardj            for an 8-bit comparison, since the args to the helper
964908854045e8ebf1495663bb50801c32d6f729bbesewardj            function are always U32s. */
965908854045e8ebf1495663bb50801c32d6f729bbesewardj         return binop(Iop_And32,
966908854045e8ebf1495663bb50801c32d6f729bbesewardj                      binop(Iop_Shr32,cc_dep1,mkU8(7)),
967908854045e8ebf1495663bb50801c32d6f729bbesewardj                      mkU32(1));
968908854045e8ebf1495663bb50801c32d6f729bbesewardj      }
9699a3431c38a2e435c58a5e027943f50fa35c2369csewardj      if (isU32(cc_op, X86G_CC_OP_SUBB) && isU32(cond, X86CondNS)
9709a3431c38a2e435c58a5e027943f50fa35c2369csewardj                                        && isU32(cc_dep2, 0)) {
9719a3431c38a2e435c58a5e027943f50fa35c2369csewardj         /* byte sub/cmp of zero, then NS --> test !(dst-0 <s 0)
9729a3431c38a2e435c58a5e027943f50fa35c2369csewardj                                          --> test !(dst <s 0)
9739a3431c38a2e435c58a5e027943f50fa35c2369csewardj                                          --> (UInt) !dst[7]
9749a3431c38a2e435c58a5e027943f50fa35c2369csewardj         */
9759a3431c38a2e435c58a5e027943f50fa35c2369csewardj         return binop(Iop_Xor32,
9769a3431c38a2e435c58a5e027943f50fa35c2369csewardj                      binop(Iop_And32,
9779a3431c38a2e435c58a5e027943f50fa35c2369csewardj                            binop(Iop_Shr32,cc_dep1,mkU8(7)),
9789a3431c38a2e435c58a5e027943f50fa35c2369csewardj                            mkU32(1)),
9799a3431c38a2e435c58a5e027943f50fa35c2369csewardj                mkU32(1));
9809a3431c38a2e435c58a5e027943f50fa35c2369csewardj      }
9819a3431c38a2e435c58a5e027943f50fa35c2369csewardj
98246ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      /*---------------- LOGICL ----------------*/
98346ccb51aff085d180120d310c0be2fe6c86e1b65sewardj
9842a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_LOGICL) && isU32(cond, X86CondZ)) {
98584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         /* long and/or/xor, then Z --> test dst==0 */
98693d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj         return unop(Iop_1Uto32,binop(Iop_CmpEQ32, cc_dep1, mkU32(0)));
98784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
988b83767e0691bcd985a0f4986e42e013585db3e55sewardj      if (isU32(cc_op, X86G_CC_OP_LOGICL) && isU32(cond, X86CondNZ)) {
989b83767e0691bcd985a0f4986e42e013585db3e55sewardj         /* long and/or/xor, then NZ --> test dst!=0 */
990b83767e0691bcd985a0f4986e42e013585db3e55sewardj         return unop(Iop_1Uto32,binop(Iop_CmpNE32, cc_dep1, mkU32(0)));
991b83767e0691bcd985a0f4986e42e013585db3e55sewardj      }
992b83767e0691bcd985a0f4986e42e013585db3e55sewardj
9932a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_LOGICL) && isU32(cond, X86CondLE)) {
99484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         /* long and/or/xor, then LE
99584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj            This is pretty subtle.  LOGIC sets SF and ZF according to the
99684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj            result and makes OF be zero.  LE computes (SZ ^ OF) | ZF, but
99784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj            OF is zero, so this reduces to SZ | ZF -- which will be 1 iff
99884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj            the result is <=signed 0.  Hence ...
99984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         */
100093d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj         return unop(Iop_1Uto32,binop(Iop_CmpLE32S, cc_dep1, mkU32(0)));
100184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
100284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
100366f7a54d5425853debcb5fe77be1021f0c2b6620sewardj      if (isU32(cc_op, X86G_CC_OP_LOGICL) && isU32(cond, X86CondBE)) {
100466f7a54d5425853debcb5fe77be1021f0c2b6620sewardj         /* long and/or/xor, then BE
100566f7a54d5425853debcb5fe77be1021f0c2b6620sewardj            LOGIC sets ZF according to the result and makes CF be zero.
100666f7a54d5425853debcb5fe77be1021f0c2b6620sewardj            BE computes (CF | ZF), but CF is zero, so this reduces ZF
100766f7a54d5425853debcb5fe77be1021f0c2b6620sewardj            -- which will be 1 iff the result is zero.  Hence ...
100866f7a54d5425853debcb5fe77be1021f0c2b6620sewardj         */
100966f7a54d5425853debcb5fe77be1021f0c2b6620sewardj         return unop(Iop_1Uto32,binop(Iop_CmpEQ32, cc_dep1, mkU32(0)));
101066f7a54d5425853debcb5fe77be1021f0c2b6620sewardj      }
101166f7a54d5425853debcb5fe77be1021f0c2b6620sewardj
101254be8dd43bc6a509a1aab87a5d77cec8a61cd894sewardj      if (isU32(cc_op, X86G_CC_OP_LOGICL) && isU32(cond, X86CondS)) {
101354be8dd43bc6a509a1aab87a5d77cec8a61cd894sewardj         /* see comment below for (LOGICB, CondS) */
101454be8dd43bc6a509a1aab87a5d77cec8a61cd894sewardj         /* long and/or/xor, then S --> (UInt)result[31] */
101554be8dd43bc6a509a1aab87a5d77cec8a61cd894sewardj         return binop(Iop_And32,
101654be8dd43bc6a509a1aab87a5d77cec8a61cd894sewardj                      binop(Iop_Shr32,cc_dep1,mkU8(31)),
101754be8dd43bc6a509a1aab87a5d77cec8a61cd894sewardj                      mkU32(1));
101854be8dd43bc6a509a1aab87a5d77cec8a61cd894sewardj      }
1019275ccdf49c33fc3efb2cbebe2bb74c8dff30fcddsewardj      if (isU32(cc_op, X86G_CC_OP_LOGICL) && isU32(cond, X86CondNS)) {
1020275ccdf49c33fc3efb2cbebe2bb74c8dff30fcddsewardj         /* see comment below for (LOGICB, CondNS) */
1021275ccdf49c33fc3efb2cbebe2bb74c8dff30fcddsewardj         /* long and/or/xor, then S --> (UInt) ~ result[31] */
1022275ccdf49c33fc3efb2cbebe2bb74c8dff30fcddsewardj         return binop(Iop_Xor32,
1023275ccdf49c33fc3efb2cbebe2bb74c8dff30fcddsewardj                binop(Iop_And32,
1024275ccdf49c33fc3efb2cbebe2bb74c8dff30fcddsewardj                      binop(Iop_Shr32,cc_dep1,mkU8(31)),
1025275ccdf49c33fc3efb2cbebe2bb74c8dff30fcddsewardj                      mkU32(1)),
1026275ccdf49c33fc3efb2cbebe2bb74c8dff30fcddsewardj                mkU32(1));
1027275ccdf49c33fc3efb2cbebe2bb74c8dff30fcddsewardj      }
102854be8dd43bc6a509a1aab87a5d77cec8a61cd894sewardj
1029d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj      /*---------------- LOGICW ----------------*/
1030d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj
10312a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_LOGICW) && isU32(cond, X86CondZ)) {
1032c5fd97216fa0f530828d517a5db46b64f5ae986fsewardj         /* word and/or/xor, then Z --> test dst==0 */
1033d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj         return unop(Iop_1Uto32,
1034d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj                     binop(Iop_CmpEQ32, binop(Iop_And32,cc_dep1,mkU32(0xFFFF)),
1035d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj                                        mkU32(0)));
1036d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj      }
1037d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj
103854be8dd43bc6a509a1aab87a5d77cec8a61cd894sewardj      if (isU32(cc_op, X86G_CC_OP_LOGICW) && isU32(cond, X86CondS)) {
103954be8dd43bc6a509a1aab87a5d77cec8a61cd894sewardj         /* see comment below for (LOGICB, CondS) */
104054be8dd43bc6a509a1aab87a5d77cec8a61cd894sewardj         /* word and/or/xor, then S --> (UInt)result[15] */
104154be8dd43bc6a509a1aab87a5d77cec8a61cd894sewardj         return binop(Iop_And32,
104254be8dd43bc6a509a1aab87a5d77cec8a61cd894sewardj                      binop(Iop_Shr32,cc_dep1,mkU8(15)),
104354be8dd43bc6a509a1aab87a5d77cec8a61cd894sewardj                      mkU32(1));
104454be8dd43bc6a509a1aab87a5d77cec8a61cd894sewardj      }
104554be8dd43bc6a509a1aab87a5d77cec8a61cd894sewardj
104646ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      /*---------------- LOGICB ----------------*/
104784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
10482a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_LOGICB) && isU32(cond, X86CondZ)) {
104946ccb51aff085d180120d310c0be2fe6c86e1b65sewardj         /* byte and/or/xor, then Z --> test dst==0 */
105084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return unop(Iop_1Uto32,
105193d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj                     binop(Iop_CmpEQ32, binop(Iop_And32,cc_dep1,mkU32(255)),
105246ccb51aff085d180120d310c0be2fe6c86e1b65sewardj                                        mkU32(0)));
105384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
1054275ccdf49c33fc3efb2cbebe2bb74c8dff30fcddsewardj      if (isU32(cc_op, X86G_CC_OP_LOGICB) && isU32(cond, X86CondNZ)) {
1055275ccdf49c33fc3efb2cbebe2bb74c8dff30fcddsewardj         /* byte and/or/xor, then Z --> test dst!=0 */
1056275ccdf49c33fc3efb2cbebe2bb74c8dff30fcddsewardj         /* b9ac9:       84 c0                   test   %al,%al
1057275ccdf49c33fc3efb2cbebe2bb74c8dff30fcddsewardj            b9acb:       75 0d                   jne    b9ada */
1058275ccdf49c33fc3efb2cbebe2bb74c8dff30fcddsewardj         return unop(Iop_1Uto32,
1059275ccdf49c33fc3efb2cbebe2bb74c8dff30fcddsewardj                     binop(Iop_CmpNE32, binop(Iop_And32,cc_dep1,mkU32(255)),
1060275ccdf49c33fc3efb2cbebe2bb74c8dff30fcddsewardj                                        mkU32(0)));
1061275ccdf49c33fc3efb2cbebe2bb74c8dff30fcddsewardj      }
1062275ccdf49c33fc3efb2cbebe2bb74c8dff30fcddsewardj
106354be8dd43bc6a509a1aab87a5d77cec8a61cd894sewardj      if (isU32(cc_op, X86G_CC_OP_LOGICB) && isU32(cond, X86CondS)) {
106454be8dd43bc6a509a1aab87a5d77cec8a61cd894sewardj         /* this is an idiom gcc sometimes uses to find out if the top
106554be8dd43bc6a509a1aab87a5d77cec8a61cd894sewardj            bit of a byte register is set: eg testb %al,%al; js ..
106654be8dd43bc6a509a1aab87a5d77cec8a61cd894sewardj            Since it just depends on the top bit of the byte, extract
106754be8dd43bc6a509a1aab87a5d77cec8a61cd894sewardj            that bit and explicitly get rid of all the rest.  This
106854be8dd43bc6a509a1aab87a5d77cec8a61cd894sewardj            helps memcheck avoid false positives in the case where any
106954be8dd43bc6a509a1aab87a5d77cec8a61cd894sewardj            of the other bits in the byte are undefined. */
107054be8dd43bc6a509a1aab87a5d77cec8a61cd894sewardj         /* byte and/or/xor, then S --> (UInt)result[7] */
107154be8dd43bc6a509a1aab87a5d77cec8a61cd894sewardj         return binop(Iop_And32,
107254be8dd43bc6a509a1aab87a5d77cec8a61cd894sewardj                      binop(Iop_Shr32,cc_dep1,mkU8(7)),
107354be8dd43bc6a509a1aab87a5d77cec8a61cd894sewardj                      mkU32(1));
107454be8dd43bc6a509a1aab87a5d77cec8a61cd894sewardj      }
1075275ccdf49c33fc3efb2cbebe2bb74c8dff30fcddsewardj      if (isU32(cc_op, X86G_CC_OP_LOGICB) && isU32(cond, X86CondNS)) {
1076275ccdf49c33fc3efb2cbebe2bb74c8dff30fcddsewardj         /* ditto, for negation-of-S. */
1077275ccdf49c33fc3efb2cbebe2bb74c8dff30fcddsewardj         /* byte and/or/xor, then S --> (UInt) ~ result[7] */
1078275ccdf49c33fc3efb2cbebe2bb74c8dff30fcddsewardj         return binop(Iop_Xor32,
1079275ccdf49c33fc3efb2cbebe2bb74c8dff30fcddsewardj                binop(Iop_And32,
1080275ccdf49c33fc3efb2cbebe2bb74c8dff30fcddsewardj                      binop(Iop_Shr32,cc_dep1,mkU8(7)),
1081275ccdf49c33fc3efb2cbebe2bb74c8dff30fcddsewardj                      mkU32(1)),
1082275ccdf49c33fc3efb2cbebe2bb74c8dff30fcddsewardj                mkU32(1));
1083275ccdf49c33fc3efb2cbebe2bb74c8dff30fcddsewardj      }
108454be8dd43bc6a509a1aab87a5d77cec8a61cd894sewardj
108546ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      /*---------------- DECL ----------------*/
1086af991dede2815b7570828b9d9174cf989e636254sewardj
10872a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_DECL) && isU32(cond, X86CondZ)) {
108884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         /* dec L, then Z --> test dst == 0 */
108993d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj         return unop(Iop_1Uto32,binop(Iop_CmpEQ32, cc_dep1, mkU32(0)));
109084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
109122419b8f4f2c0104549ca9954f68e190b911d1a0sewardj
10922a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_DECL) && isU32(cond, X86CondS)) {
1093fae2ca7ef81549a4b28235618317d4352ca32ac2sewardj         /* dec L, then S --> compare DST <s 0 */
10947e6644c38b3e0148ff95c2f6f4667f54148b611esewardj         return unop(Iop_1Uto32,binop(Iop_CmpLT32S, cc_dep1, mkU32(0)));
1095fae2ca7ef81549a4b28235618317d4352ca32ac2sewardj      }
1096275ccdf49c33fc3efb2cbebe2bb74c8dff30fcddsewardj
109732d615b76c65938d815fe529e690a7f79a24a4ecsewardj      /*---------------- DECW ----------------*/
109832d615b76c65938d815fe529e690a7f79a24a4ecsewardj
109932d615b76c65938d815fe529e690a7f79a24a4ecsewardj      if (isU32(cc_op, X86G_CC_OP_DECW) && isU32(cond, X86CondZ)) {
110032d615b76c65938d815fe529e690a7f79a24a4ecsewardj         /* dec W, then Z --> test dst == 0 */
110132d615b76c65938d815fe529e690a7f79a24a4ecsewardj         return unop(Iop_1Uto32,
110232d615b76c65938d815fe529e690a7f79a24a4ecsewardj                     binop(Iop_CmpEQ32,
110332d615b76c65938d815fe529e690a7f79a24a4ecsewardj                           binop(Iop_Shl32,cc_dep1,mkU8(16)),
110432d615b76c65938d815fe529e690a7f79a24a4ecsewardj                           mkU32(0)));
110532d615b76c65938d815fe529e690a7f79a24a4ecsewardj      }
110632d615b76c65938d815fe529e690a7f79a24a4ecsewardj
1107275ccdf49c33fc3efb2cbebe2bb74c8dff30fcddsewardj      /*---------------- INCW ----------------*/
1108275ccdf49c33fc3efb2cbebe2bb74c8dff30fcddsewardj
1109275ccdf49c33fc3efb2cbebe2bb74c8dff30fcddsewardj      if (isU32(cc_op, X86G_CC_OP_INCW) && isU32(cond, X86CondZ)) {
1110275ccdf49c33fc3efb2cbebe2bb74c8dff30fcddsewardj         /* This rewrite helps memcheck on 'incw %ax ; je ...'. */
1111275ccdf49c33fc3efb2cbebe2bb74c8dff30fcddsewardj         /* inc W, then Z --> test dst == 0 */
1112275ccdf49c33fc3efb2cbebe2bb74c8dff30fcddsewardj         return unop(Iop_1Uto32,
1113275ccdf49c33fc3efb2cbebe2bb74c8dff30fcddsewardj                     binop(Iop_CmpEQ32,
1114275ccdf49c33fc3efb2cbebe2bb74c8dff30fcddsewardj                           binop(Iop_Shl32,cc_dep1,mkU8(16)),
1115275ccdf49c33fc3efb2cbebe2bb74c8dff30fcddsewardj                           mkU32(0)));
1116275ccdf49c33fc3efb2cbebe2bb74c8dff30fcddsewardj      }
1117fae2ca7ef81549a4b28235618317d4352ca32ac2sewardj
1118d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj      /*---------------- SHRL ----------------*/
1119d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj
11202a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      if (isU32(cc_op, X86G_CC_OP_SHRL) && isU32(cond, X86CondZ)) {
1121d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj         /* SHRL, then Z --> test dep1 == 0 */
1122d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj         return unop(Iop_1Uto32,binop(Iop_CmpEQ32, cc_dep1, mkU32(0)));
1123d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj      }
1124d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj
11254afab82eb869f21ccabc3efb5b93f31a5c343956sewardj      /*---------------- COPY ----------------*/
11264afab82eb869f21ccabc3efb5b93f31a5c343956sewardj      /* This can happen, as a result of x87 FP compares: "fcom ... ;
11274afab82eb869f21ccabc3efb5b93f31a5c343956sewardj         fnstsw %ax ; sahf ; jbe" for example. */
11284afab82eb869f21ccabc3efb5b93f31a5c343956sewardj
112966f7a54d5425853debcb5fe77be1021f0c2b6620sewardj      if (isU32(cc_op, X86G_CC_OP_COPY) &&
113066f7a54d5425853debcb5fe77be1021f0c2b6620sewardj          (isU32(cond, X86CondBE) || isU32(cond, X86CondNBE))) {
1131c7be3eb57d2dc65ee00c6011d0ea8c8a1dc57b79sewardj         /* COPY, then BE --> extract C and Z from dep1, and test
1132c7be3eb57d2dc65ee00c6011d0ea8c8a1dc57b79sewardj            (C or Z) == 1. */
1133c7be3eb57d2dc65ee00c6011d0ea8c8a1dc57b79sewardj         /* COPY, then NBE --> extract C and Z from dep1, and test
1134c7be3eb57d2dc65ee00c6011d0ea8c8a1dc57b79sewardj            (C or Z) == 0. */
113566f7a54d5425853debcb5fe77be1021f0c2b6620sewardj         UInt nnn = isU32(cond, X86CondBE) ? 1 : 0;
11364afab82eb869f21ccabc3efb5b93f31a5c343956sewardj         return
11374afab82eb869f21ccabc3efb5b93f31a5c343956sewardj            unop(
11384afab82eb869f21ccabc3efb5b93f31a5c343956sewardj               Iop_1Uto32,
11394afab82eb869f21ccabc3efb5b93f31a5c343956sewardj               binop(
114066f7a54d5425853debcb5fe77be1021f0c2b6620sewardj                  Iop_CmpEQ32,
11414afab82eb869f21ccabc3efb5b93f31a5c343956sewardj                  binop(
11424afab82eb869f21ccabc3efb5b93f31a5c343956sewardj                     Iop_And32,
11434afab82eb869f21ccabc3efb5b93f31a5c343956sewardj                     binop(
11444afab82eb869f21ccabc3efb5b93f31a5c343956sewardj                        Iop_Or32,
11454afab82eb869f21ccabc3efb5b93f31a5c343956sewardj                        binop(Iop_Shr32, cc_dep1, mkU8(X86G_CC_SHIFT_C)),
11464afab82eb869f21ccabc3efb5b93f31a5c343956sewardj                        binop(Iop_Shr32, cc_dep1, mkU8(X86G_CC_SHIFT_Z))
11474afab82eb869f21ccabc3efb5b93f31a5c343956sewardj                     ),
11484afab82eb869f21ccabc3efb5b93f31a5c343956sewardj                     mkU32(1)
11494afab82eb869f21ccabc3efb5b93f31a5c343956sewardj                  ),
115066f7a54d5425853debcb5fe77be1021f0c2b6620sewardj                  mkU32(nnn)
11514afab82eb869f21ccabc3efb5b93f31a5c343956sewardj               )
11524afab82eb869f21ccabc3efb5b93f31a5c343956sewardj            );
11534afab82eb869f21ccabc3efb5b93f31a5c343956sewardj      }
11544afab82eb869f21ccabc3efb5b93f31a5c343956sewardj
11551ee3e18f5fed89dd9c07c7362aabead931c1ea19sewardj      if (isU32(cc_op, X86G_CC_OP_COPY)
11561ee3e18f5fed89dd9c07c7362aabead931c1ea19sewardj          && (isU32(cond, X86CondB) || isU32(cond, X86CondNB))) {
1157e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj         /* COPY, then B --> extract C from dep1, and test (C == 1). */
1158e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj         /* COPY, then NB --> extract C from dep1, and test (C == 0). */
1159e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj         UInt nnn = isU32(cond, X86CondB) ? 1 : 0;
11604afab82eb869f21ccabc3efb5b93f31a5c343956sewardj         return
11614afab82eb869f21ccabc3efb5b93f31a5c343956sewardj            unop(
11624afab82eb869f21ccabc3efb5b93f31a5c343956sewardj               Iop_1Uto32,
11634afab82eb869f21ccabc3efb5b93f31a5c343956sewardj               binop(
1164e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj                  Iop_CmpEQ32,
11654afab82eb869f21ccabc3efb5b93f31a5c343956sewardj                  binop(
11664afab82eb869f21ccabc3efb5b93f31a5c343956sewardj                     Iop_And32,
11674afab82eb869f21ccabc3efb5b93f31a5c343956sewardj                     binop(Iop_Shr32, cc_dep1, mkU8(X86G_CC_SHIFT_C)),
11684afab82eb869f21ccabc3efb5b93f31a5c343956sewardj                     mkU32(1)
11694afab82eb869f21ccabc3efb5b93f31a5c343956sewardj                  ),
1170e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj                  mkU32(nnn)
1171e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj               )
1172e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj            );
1173e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj      }
1174e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj
11751ee3e18f5fed89dd9c07c7362aabead931c1ea19sewardj      if (isU32(cc_op, X86G_CC_OP_COPY)
11761ee3e18f5fed89dd9c07c7362aabead931c1ea19sewardj          && (isU32(cond, X86CondZ) || isU32(cond, X86CondNZ))) {
1177e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj         /* COPY, then Z --> extract Z from dep1, and test (Z == 1). */
11781ee3e18f5fed89dd9c07c7362aabead931c1ea19sewardj         /* COPY, then NZ --> extract Z from dep1, and test (Z == 0). */
11791ee3e18f5fed89dd9c07c7362aabead931c1ea19sewardj         UInt nnn = isU32(cond, X86CondZ) ? 1 : 0;
1180e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj         return
1181e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj            unop(
1182e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj               Iop_1Uto32,
1183e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj               binop(
11841ee3e18f5fed89dd9c07c7362aabead931c1ea19sewardj                  Iop_CmpEQ32,
1185e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj                  binop(
1186e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj                     Iop_And32,
1187e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj                     binop(Iop_Shr32, cc_dep1, mkU8(X86G_CC_SHIFT_Z)),
1188e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj                     mkU32(1)
1189e51ae9f5a25e952d0e98bd90c26a9ed74770215esewardj                  ),
11901ee3e18f5fed89dd9c07c7362aabead931c1ea19sewardj                  mkU32(nnn)
11914afab82eb869f21ccabc3efb5b93f31a5c343956sewardj               )
11924afab82eb869f21ccabc3efb5b93f31a5c343956sewardj            );
11934afab82eb869f21ccabc3efb5b93f31a5c343956sewardj      }
11944afab82eb869f21ccabc3efb5b93f31a5c343956sewardj
1195c7be3eb57d2dc65ee00c6011d0ea8c8a1dc57b79sewardj      if (isU32(cc_op, X86G_CC_OP_COPY)
1196c7be3eb57d2dc65ee00c6011d0ea8c8a1dc57b79sewardj          && (isU32(cond, X86CondP) || isU32(cond, X86CondNP))) {
1197c45aa52e4f9bf0ba1ac748cd761c4bdc3051e408sewardj         /* COPY, then P --> extract P from dep1, and test (P == 1). */
1198c7be3eb57d2dc65ee00c6011d0ea8c8a1dc57b79sewardj         /* COPY, then NP --> extract P from dep1, and test (P == 0). */
1199c7be3eb57d2dc65ee00c6011d0ea8c8a1dc57b79sewardj         UInt nnn = isU32(cond, X86CondP) ? 1 : 0;
1200c45aa52e4f9bf0ba1ac748cd761c4bdc3051e408sewardj         return
1201c45aa52e4f9bf0ba1ac748cd761c4bdc3051e408sewardj            unop(
1202c45aa52e4f9bf0ba1ac748cd761c4bdc3051e408sewardj               Iop_1Uto32,
1203c45aa52e4f9bf0ba1ac748cd761c4bdc3051e408sewardj               binop(
1204c7be3eb57d2dc65ee00c6011d0ea8c8a1dc57b79sewardj                  Iop_CmpEQ32,
1205c45aa52e4f9bf0ba1ac748cd761c4bdc3051e408sewardj                  binop(
1206c45aa52e4f9bf0ba1ac748cd761c4bdc3051e408sewardj                     Iop_And32,
1207c45aa52e4f9bf0ba1ac748cd761c4bdc3051e408sewardj                     binop(Iop_Shr32, cc_dep1, mkU8(X86G_CC_SHIFT_P)),
1208c45aa52e4f9bf0ba1ac748cd761c4bdc3051e408sewardj                     mkU32(1)
1209c45aa52e4f9bf0ba1ac748cd761c4bdc3051e408sewardj                  ),
1210c7be3eb57d2dc65ee00c6011d0ea8c8a1dc57b79sewardj                  mkU32(nnn)
1211c45aa52e4f9bf0ba1ac748cd761c4bdc3051e408sewardj               )
1212c45aa52e4f9bf0ba1ac748cd761c4bdc3051e408sewardj            );
1213c45aa52e4f9bf0ba1ac748cd761c4bdc3051e408sewardj      }
1214c45aa52e4f9bf0ba1ac748cd761c4bdc3051e408sewardj
121584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      return NULL;
121684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   }
121784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
1218893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   /* --------- specialising "x86g_calculate_eflags_c" --------- */
1219893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
1220893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   if (vex_streq(function_name, "x86g_calculate_eflags_c")) {
1221893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      /* specialise calls to above "calculate_eflags_c" function */
1222893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      IRExpr *cc_op, *cc_dep1, *cc_dep2, *cc_ndep;
1223893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      vassert(arity == 4);
1224893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      cc_op   = args[0];
1225893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      cc_dep1 = args[1];
1226893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      cc_dep2 = args[2];
1227893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      cc_ndep = args[3];
1228893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
1229893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      if (isU32(cc_op, X86G_CC_OP_SUBL)) {
1230893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj         /* C after sub denotes unsigned less than */
1231893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj         return unop(Iop_1Uto32,
1232893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj                     binop(Iop_CmpLT32U, cc_dep1, cc_dep2));
1233893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      }
1234893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      if (isU32(cc_op, X86G_CC_OP_SUBB)) {
1235893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj         /* C after sub denotes unsigned less than */
1236893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj         return unop(Iop_1Uto32,
1237893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj                     binop(Iop_CmpLT32U,
1238893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj                           binop(Iop_And32,cc_dep1,mkU32(0xFF)),
1239893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj                           binop(Iop_And32,cc_dep2,mkU32(0xFF))));
1240893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      }
1241893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      if (isU32(cc_op, X86G_CC_OP_LOGICL)
1242893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj          || isU32(cc_op, X86G_CC_OP_LOGICW)
1243893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj          || isU32(cc_op, X86G_CC_OP_LOGICB)) {
1244893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj         /* cflag after logic is zero */
1245893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj         return mkU32(0);
1246893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      }
1247893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      if (isU32(cc_op, X86G_CC_OP_DECL) || isU32(cc_op, X86G_CC_OP_INCL)) {
1248893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj         /* If the thunk is dec or inc, the cflag is supplied as CC_NDEP. */
1249893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj         return cc_ndep;
1250893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      }
1251893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      if (isU32(cc_op, X86G_CC_OP_COPY)) {
1252893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj         /* cflag after COPY is stored in DEP1. */
1253893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj         return
1254893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj            binop(
1255893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj               Iop_And32,
1256893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj               binop(Iop_Shr32, cc_dep1, mkU8(X86G_CC_SHIFT_C)),
1257893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj               mkU32(1)
1258893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj            );
1259893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      }
1260174c7709cb81c9358d4264a8109e37404338445fsewardj      if (isU32(cc_op, X86G_CC_OP_ADDL)) {
1261174c7709cb81c9358d4264a8109e37404338445fsewardj         /* C after add denotes sum <u either arg */
1262174c7709cb81c9358d4264a8109e37404338445fsewardj         return unop(Iop_1Uto32,
1263174c7709cb81c9358d4264a8109e37404338445fsewardj                     binop(Iop_CmpLT32U,
1264174c7709cb81c9358d4264a8109e37404338445fsewardj                           binop(Iop_Add32, cc_dep1, cc_dep2),
1265174c7709cb81c9358d4264a8109e37404338445fsewardj                           cc_dep1));
1266174c7709cb81c9358d4264a8109e37404338445fsewardj      }
1267ff6b34ac26070c47e55803e61f8ae5554ddcac27sewardj      // ATC, requires verification, no test case known
1268ff6b34ac26070c47e55803e61f8ae5554ddcac27sewardj      //if (isU32(cc_op, X86G_CC_OP_SMULL)) {
1269ff6b34ac26070c47e55803e61f8ae5554ddcac27sewardj      //   /* C after signed widening multiply denotes the case where
1270ff6b34ac26070c47e55803e61f8ae5554ddcac27sewardj      //      the top half of the result isn't simply the sign extension
1271ff6b34ac26070c47e55803e61f8ae5554ddcac27sewardj      //      of the bottom half (iow the result doesn't fit completely
1272ff6b34ac26070c47e55803e61f8ae5554ddcac27sewardj      //      in the bottom half).  Hence:
1273ff6b34ac26070c47e55803e61f8ae5554ddcac27sewardj      //        C = hi-half(dep1 x dep2) != lo-half(dep1 x dep2) >>s 31
1274ff6b34ac26070c47e55803e61f8ae5554ddcac27sewardj      //      where 'x' denotes signed widening multiply.*/
1275ff6b34ac26070c47e55803e61f8ae5554ddcac27sewardj      //   return
1276ff6b34ac26070c47e55803e61f8ae5554ddcac27sewardj      //      unop(Iop_1Uto32,
1277ff6b34ac26070c47e55803e61f8ae5554ddcac27sewardj      //           binop(Iop_CmpNE32,
1278ff6b34ac26070c47e55803e61f8ae5554ddcac27sewardj      //                 unop(Iop_64HIto32,
1279ff6b34ac26070c47e55803e61f8ae5554ddcac27sewardj      //                      binop(Iop_MullS32, cc_dep1, cc_dep2)),
1280ff6b34ac26070c47e55803e61f8ae5554ddcac27sewardj      //                 binop(Iop_Sar32,
1281ff6b34ac26070c47e55803e61f8ae5554ddcac27sewardj      //                       binop(Iop_Mul32, cc_dep1, cc_dep2), mkU8(31)) ));
1282ff6b34ac26070c47e55803e61f8ae5554ddcac27sewardj      //}
1283893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj#     if 0
1284893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      if (cc_op->tag == Iex_Const) {
1285893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj         vex_printf("CFLAG "); ppIRExpr(cc_op); vex_printf("\n");
1286893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      }
1287893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj#     endif
1288893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
1289893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      return NULL;
1290893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   }
1291893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
1292893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   /* --------- specialising "x86g_calculate_eflags_all" --------- */
1293893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
1294893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   if (vex_streq(function_name, "x86g_calculate_eflags_all")) {
1295893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      /* specialise calls to above "calculate_eflags_all" function */
129640e144d3c4b155ab30c71f5abc90ff67391e7a87sewardj      IRExpr *cc_op, *cc_dep1; /*, *cc_dep2, *cc_ndep; */
1297893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      vassert(arity == 4);
1298893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      cc_op   = args[0];
1299893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      cc_dep1 = args[1];
130040e144d3c4b155ab30c71f5abc90ff67391e7a87sewardj      /* cc_dep2 = args[2]; */
130140e144d3c4b155ab30c71f5abc90ff67391e7a87sewardj      /* cc_ndep = args[3]; */
1302893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
1303893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      if (isU32(cc_op, X86G_CC_OP_COPY)) {
1304893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj         /* eflags after COPY are stored in DEP1. */
1305893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj         return
1306893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj            binop(
1307893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj               Iop_And32,
1308893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj               cc_dep1,
1309893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj               mkU32(X86G_CC_MASK_O | X86G_CC_MASK_S | X86G_CC_MASK_Z
1310893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj                     | X86G_CC_MASK_A | X86G_CC_MASK_C | X86G_CC_MASK_P)
1311893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj            );
1312893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      }
1313893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      return NULL;
1314893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   }
1315893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
131684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  undef unop
131784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  undef binop
131884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  undef mkU32
13194afab82eb869f21ccabc3efb5b93f31a5c343956sewardj#  undef mkU8
132084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
132184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   return NULL;
132284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj}
132384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
132436ca51378f8851635df814230fa23f2c409b9eddsewardj
1325893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/*---------------------------------------------------------------*/
1326893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/*--- Supporting functions for x87 FPU activities.            ---*/
1327893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/*---------------------------------------------------------------*/
1328893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
1329893a3302cc943e2ad1db421a8e6a753f82f532a7sewardjstatic inline Bool host_is_little_endian ( void )
1330893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj{
1331893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   UInt x = 0x76543210;
1332893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   UChar* p = (UChar*)(&x);
1333a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   return toBool(*p == 0x10);
1334893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj}
1335893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
13360c2cb623cca372a2b42b073121c7413cdaaf75besewardj/* 80 and 64-bit floating point formats:
13370c2cb623cca372a2b42b073121c7413cdaaf75besewardj
13380c2cb623cca372a2b42b073121c7413cdaaf75besewardj   80-bit:
13390c2cb623cca372a2b42b073121c7413cdaaf75besewardj
13400c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  0       0-------0      zero
13410c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  0       0X------X      denormals
13420c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  1-7FFE  1X------X      normals (all normals have leading 1)
13430c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  7FFF    10------0      infinity
13440c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  7FFF    10X-----X      snan
13450c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  7FFF    11X-----X      qnan
13460c2cb623cca372a2b42b073121c7413cdaaf75besewardj
13470c2cb623cca372a2b42b073121c7413cdaaf75besewardj   S is the sign bit.  For runs X----X, at least one of the Xs must be
13480c2cb623cca372a2b42b073121c7413cdaaf75besewardj   nonzero.  Exponent is 15 bits, fractional part is 63 bits, and
13490c2cb623cca372a2b42b073121c7413cdaaf75besewardj   there is an explicitly represented leading 1, and a sign bit,
13500c2cb623cca372a2b42b073121c7413cdaaf75besewardj   giving 80 in total.
13510c2cb623cca372a2b42b073121c7413cdaaf75besewardj
13520c2cb623cca372a2b42b073121c7413cdaaf75besewardj   64-bit avoids the confusion of an explicitly represented leading 1
13530c2cb623cca372a2b42b073121c7413cdaaf75besewardj   and so is simpler:
13540c2cb623cca372a2b42b073121c7413cdaaf75besewardj
13550c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  0      0------0   zero
13560c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  0      X------X   denormals
13570c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  1-7FE  any        normals
13580c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  7FF    0------0   infinity
13590c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  7FF    0X-----X   snan
13600c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  7FF    1X-----X   qnan
13610c2cb623cca372a2b42b073121c7413cdaaf75besewardj
13620c2cb623cca372a2b42b073121c7413cdaaf75besewardj   Exponent is 11 bits, fractional part is 52 bits, and there is a
13630c2cb623cca372a2b42b073121c7413cdaaf75besewardj   sign bit, giving 64 in total.
13640c2cb623cca372a2b42b073121c7413cdaaf75besewardj*/
13650c2cb623cca372a2b42b073121c7413cdaaf75besewardj
1366893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/* Inspect a value and its tag, as per the x87 'FXAM' instruction. */
13679aebb0c3f7a7f43313786826f31402f2b733badfsewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
13682a9ad023890d3b34cf45e429df2a8ae88b419128sewardjUInt x86g_calculate_FXAM ( UInt tag, ULong dbl )
1369c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj{
1370c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   Bool   mantissaIsZero;
1371c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   Int    bexp;
1372c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   UChar  sign;
1373c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   UChar* f64;
1374c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
1375a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   vassert(host_is_little_endian());
1376c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
1377c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   /* vex_printf("calculate_FXAM ( %d, %llx ) .. ", tag, dbl ); */
1378c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
1379c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   f64  = (UChar*)(&dbl);
1380a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   sign = toUChar( (f64[7] >> 7) & 1 );
1381c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
1382c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   /* First off, if the tag indicates the register was empty,
1383c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      return 1,0,sign,1 */
1384c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   if (tag == 0) {
1385c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      /* vex_printf("Empty\n"); */
1386e128ea174ede77daa2edadb3bde0b40dde06f95esewardj      return X86G_FC_MASK_C3 | 0 | (sign << X86G_FC_SHIFT_C1)
1387e128ea174ede77daa2edadb3bde0b40dde06f95esewardj                                 | X86G_FC_MASK_C0;
1388c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   }
1389c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
1390c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   bexp = (f64[7] << 4) | ((f64[6] >> 4) & 0x0F);
1391c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   bexp &= 0x7FF;
1392c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
1393c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   mantissaIsZero
1394a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj      = toBool(
1395a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj           (f64[6] & 0x0F) == 0
1396a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj           && (f64[5] | f64[4] | f64[3] | f64[2] | f64[1] | f64[0]) == 0
1397a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj        );
1398c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
1399c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   /* If both exponent and mantissa are zero, the value is zero.
1400c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      Return 1,0,sign,0. */
1401c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   if (bexp == 0 && mantissaIsZero) {
1402c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      /* vex_printf("Zero\n"); */
1403e128ea174ede77daa2edadb3bde0b40dde06f95esewardj      return X86G_FC_MASK_C3 | 0
1404e128ea174ede77daa2edadb3bde0b40dde06f95esewardj                             | (sign << X86G_FC_SHIFT_C1) | 0;
1405c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   }
1406c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
1407c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   /* If exponent is zero but mantissa isn't, it's a denormal.
1408c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      Return 1,1,sign,0. */
1409c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   if (bexp == 0 && !mantissaIsZero) {
1410c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      /* vex_printf("Denormal\n"); */
1411e128ea174ede77daa2edadb3bde0b40dde06f95esewardj      return X86G_FC_MASK_C3 | X86G_FC_MASK_C2
1412e128ea174ede77daa2edadb3bde0b40dde06f95esewardj                             | (sign << X86G_FC_SHIFT_C1) | 0;
1413c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   }
1414c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
1415c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   /* If the exponent is 7FF and the mantissa is zero, this is an infinity.
1416c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      Return 0,1,sign,1. */
1417c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   if (bexp == 0x7FF && mantissaIsZero) {
1418c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      /* vex_printf("Inf\n"); */
1419e128ea174ede77daa2edadb3bde0b40dde06f95esewardj      return 0 | X86G_FC_MASK_C2 | (sign << X86G_FC_SHIFT_C1)
1420e128ea174ede77daa2edadb3bde0b40dde06f95esewardj                                 | X86G_FC_MASK_C0;
1421c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   }
1422c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
1423c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   /* If the exponent is 7FF and the mantissa isn't zero, this is a NaN.
1424c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      Return 0,0,sign,1. */
1425c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   if (bexp == 0x7FF && !mantissaIsZero) {
1426c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      /* vex_printf("NaN\n"); */
1427e128ea174ede77daa2edadb3bde0b40dde06f95esewardj      return 0 | 0 | (sign << X86G_FC_SHIFT_C1) | X86G_FC_MASK_C0;
1428c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   }
1429c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
1430c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   /* Uh, ok, we give up.  It must be a normal finite number.
1431c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      Return 0,1,sign,0.
1432c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   */
1433c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   /* vex_printf("normal\n"); */
1434e128ea174ede77daa2edadb3bde0b40dde06f95esewardj   return 0 | X86G_FC_MASK_C2 | (sign << X86G_FC_SHIFT_C1) | 0;
1435c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj}
1436c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
14370c2cb623cca372a2b42b073121c7413cdaaf75besewardj
143817442fe8094d0f82266e5a05509f62cac8f7539esewardj/* CALLED FROM GENERATED CODE */
143917442fe8094d0f82266e5a05509f62cac8f7539esewardj/* DIRTY HELPER (reads guest memory) */
1440bdf99f06a5f44fd617c51ac80861ff07da09a50fflorianULong x86g_dirtyhelper_loadF80le ( Addr addrU )
144117442fe8094d0f82266e5a05509f62cac8f7539esewardj{
144217442fe8094d0f82266e5a05509f62cac8f7539esewardj   ULong f64;
1443bdf99f06a5f44fd617c51ac80861ff07da09a50fflorian   convert_f80le_to_f64le ( (UChar*)addrU, (UChar*)&f64 );
144417442fe8094d0f82266e5a05509f62cac8f7539esewardj   return f64;
144517442fe8094d0f82266e5a05509f62cac8f7539esewardj}
144617442fe8094d0f82266e5a05509f62cac8f7539esewardj
144717442fe8094d0f82266e5a05509f62cac8f7539esewardj/* CALLED FROM GENERATED CODE */
144817442fe8094d0f82266e5a05509f62cac8f7539esewardj/* DIRTY HELPER (writes guest memory) */
1449bdf99f06a5f44fd617c51ac80861ff07da09a50fflorianvoid x86g_dirtyhelper_storeF80le ( Addr addrU, ULong f64 )
145017442fe8094d0f82266e5a05509f62cac8f7539esewardj{
1451bdf99f06a5f44fd617c51ac80861ff07da09a50fflorian   convert_f64le_to_f80le( (UChar*)&f64, (UChar*)addrU );
145217442fe8094d0f82266e5a05509f62cac8f7539esewardj}
145317442fe8094d0f82266e5a05509f62cac8f7539esewardj
14540c2cb623cca372a2b42b073121c7413cdaaf75besewardj
14550c2cb623cca372a2b42b073121c7413cdaaf75besewardj/*----------------------------------------------*/
14560c2cb623cca372a2b42b073121c7413cdaaf75besewardj/*--- The exported fns ..                    ---*/
14570c2cb623cca372a2b42b073121c7413cdaaf75besewardj/*----------------------------------------------*/
14580c2cb623cca372a2b42b073121c7413cdaaf75besewardj
14590c2cb623cca372a2b42b073121c7413cdaaf75besewardj/* Layout of the real x87 state. */
14604017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj/* 13 June 05: Fpu_State and auxiliary constants was moved to
14614017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj   g_generic_x87.h */
14620c2cb623cca372a2b42b073121c7413cdaaf75besewardj
14630c2cb623cca372a2b42b073121c7413cdaaf75besewardj
14647df596b1e36840e2d74c90aa55589934add61ccfsewardj/* CLEAN HELPER */
1465a0e83b06f304527e3e9aec527c344e35e7023d76sewardj/* fpucw[15:0] contains a x87 native format FPU control word.
1466d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj   Extract from it the required FPROUND value and any resulting
1467d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj   emulation warning, and return (warn << 32) | fpround value.
1468d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj*/
14693bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardjULong x86g_check_fldcw ( UInt fpucw )
1470893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj{
1471d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj   /* Decide on a rounding mode.  fpucw[11:10] holds it. */
1472d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj   /* NOTE, encoded exactly as per enum IRRoundingMode. */
1473893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj   UInt rmode = (fpucw >> 10) & 3;
1474893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj
1475893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj   /* Detect any required emulation warnings. */
14766ef84bed9bb3af22060eb1759788034602bbcc88florian   VexEmNote ew = EmNote_NONE;
1477893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj
1478893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj   if ((fpucw & 0x3F) != 0x3F) {
1479893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj      /* unmasked exceptions! */
1480893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj      ew = EmWarn_X86_x87exns;
1481893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj   }
1482893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj   else
1483893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj   if (((fpucw >> 8) & 3) != 3) {
1484893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj      /* unsupported precision */
1485893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj      ew = EmWarn_X86_x87precision;
1486893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj   }
1487893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj
1488d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj   return (((ULong)ew) << 32) | ((ULong)rmode);
1489893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj}
1490893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj
1491893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj/* CLEAN HELPER */
14927df596b1e36840e2d74c90aa55589934add61ccfsewardj/* Given fpround as an IRRoundingMode value, create a suitable x87
14937df596b1e36840e2d74c90aa55589934add61ccfsewardj   native format FPU control word. */
14943bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardjUInt x86g_create_fpucw ( UInt fpround )
1495893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj{
1496d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj   fpround &= 3;
1497d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj   return 0x037F | (fpround << 10);
1498893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj}
1499893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj
1500893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj
15017df596b1e36840e2d74c90aa55589934add61ccfsewardj/* CLEAN HELPER */
1502a0e83b06f304527e3e9aec527c344e35e7023d76sewardj/* mxcsr[15:0] contains a SSE native format MXCSR value.
15037df596b1e36840e2d74c90aa55589934add61ccfsewardj   Extract from it the required SSEROUND value and any resulting
15047df596b1e36840e2d74c90aa55589934add61ccfsewardj   emulation warning, and return (warn << 32) | sseround value.
15057df596b1e36840e2d74c90aa55589934add61ccfsewardj*/
15063bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardjULong x86g_check_ldmxcsr ( UInt mxcsr )
15077df596b1e36840e2d74c90aa55589934add61ccfsewardj{
15087df596b1e36840e2d74c90aa55589934add61ccfsewardj   /* Decide on a rounding mode.  mxcsr[14:13] holds it. */
15097df596b1e36840e2d74c90aa55589934add61ccfsewardj   /* NOTE, encoded exactly as per enum IRRoundingMode. */
15107df596b1e36840e2d74c90aa55589934add61ccfsewardj   UInt rmode = (mxcsr >> 13) & 3;
15117df596b1e36840e2d74c90aa55589934add61ccfsewardj
15127df596b1e36840e2d74c90aa55589934add61ccfsewardj   /* Detect any required emulation warnings. */
15136ef84bed9bb3af22060eb1759788034602bbcc88florian   VexEmNote ew = EmNote_NONE;
15147df596b1e36840e2d74c90aa55589934add61ccfsewardj
15157df596b1e36840e2d74c90aa55589934add61ccfsewardj   if ((mxcsr & 0x1F80) != 0x1F80) {
15167df596b1e36840e2d74c90aa55589934add61ccfsewardj      /* unmasked exceptions! */
15177df596b1e36840e2d74c90aa55589934add61ccfsewardj      ew = EmWarn_X86_sseExns;
15187df596b1e36840e2d74c90aa55589934add61ccfsewardj   }
15197df596b1e36840e2d74c90aa55589934add61ccfsewardj   else
15205edfc26d72ca8ebea2aa0443a1ed4dd218343d04sewardj   if (mxcsr & (1<<15)) {
15215edfc26d72ca8ebea2aa0443a1ed4dd218343d04sewardj      /* FZ is set */
15225edfc26d72ca8ebea2aa0443a1ed4dd218343d04sewardj      ew = EmWarn_X86_fz;
15235edfc26d72ca8ebea2aa0443a1ed4dd218343d04sewardj   }
15245edfc26d72ca8ebea2aa0443a1ed4dd218343d04sewardj   else
15255edfc26d72ca8ebea2aa0443a1ed4dd218343d04sewardj   if (mxcsr & (1<<6)) {
15265edfc26d72ca8ebea2aa0443a1ed4dd218343d04sewardj      /* DAZ is set */
15275edfc26d72ca8ebea2aa0443a1ed4dd218343d04sewardj      ew = EmWarn_X86_daz;
15287df596b1e36840e2d74c90aa55589934add61ccfsewardj   }
15297df596b1e36840e2d74c90aa55589934add61ccfsewardj
15307df596b1e36840e2d74c90aa55589934add61ccfsewardj   return (((ULong)ew) << 32) | ((ULong)rmode);
15317df596b1e36840e2d74c90aa55589934add61ccfsewardj}
15327df596b1e36840e2d74c90aa55589934add61ccfsewardj
15337df596b1e36840e2d74c90aa55589934add61ccfsewardj
15347df596b1e36840e2d74c90aa55589934add61ccfsewardj/* CLEAN HELPER */
15357df596b1e36840e2d74c90aa55589934add61ccfsewardj/* Given sseround as an IRRoundingMode value, create a suitable SSE
15367df596b1e36840e2d74c90aa55589934add61ccfsewardj   native format MXCSR value. */
15373bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardjUInt x86g_create_mxcsr ( UInt sseround )
15387df596b1e36840e2d74c90aa55589934add61ccfsewardj{
15397df596b1e36840e2d74c90aa55589934add61ccfsewardj   sseround &= 3;
15407df596b1e36840e2d74c90aa55589934add61ccfsewardj   return 0x1F80 | (sseround << 13);
15417df596b1e36840e2d74c90aa55589934add61ccfsewardj}
15427df596b1e36840e2d74c90aa55589934add61ccfsewardj
15437df596b1e36840e2d74c90aa55589934add61ccfsewardj
1544a0e83b06f304527e3e9aec527c344e35e7023d76sewardj/* CALLED FROM GENERATED CODE */
1545a0e83b06f304527e3e9aec527c344e35e7023d76sewardj/* DIRTY HELPER (writes guest state) */
1546a0e83b06f304527e3e9aec527c344e35e7023d76sewardj/* Initialise the x87 FPU state as per 'finit'. */
1547a0e83b06f304527e3e9aec527c344e35e7023d76sewardjvoid x86g_dirtyhelper_FINIT ( VexGuestX86State* gst )
1548a0e83b06f304527e3e9aec527c344e35e7023d76sewardj{
1549a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   Int i;
1550a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   gst->guest_FTOP = 0;
1551a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   for (i = 0; i < 8; i++) {
1552a0e83b06f304527e3e9aec527c344e35e7023d76sewardj      gst->guest_FPTAG[i] = 0; /* empty */
1553a0e83b06f304527e3e9aec527c344e35e7023d76sewardj      gst->guest_FPREG[i] = 0; /* IEEE754 64-bit zero */
1554a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   }
1555a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   gst->guest_FPROUND = (UInt)Irrm_NEAREST;
1556a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   gst->guest_FC3210  = 0;
1557a0e83b06f304527e3e9aec527c344e35e7023d76sewardj}
1558a0e83b06f304527e3e9aec527c344e35e7023d76sewardj
1559a0e83b06f304527e3e9aec527c344e35e7023d76sewardj
15607df596b1e36840e2d74c90aa55589934add61ccfsewardj/* This is used to implement both 'frstor' and 'fldenv'.  The latter
15617df596b1e36840e2d74c90aa55589934add61ccfsewardj   appears to differ from the former only in that the 8 FP registers
15627df596b1e36840e2d74c90aa55589934add61ccfsewardj   themselves are not transferred into the guest state. */
15637df596b1e36840e2d74c90aa55589934add61ccfsewardjstatic
15646ef84bed9bb3af22060eb1759788034602bbcc88florianVexEmNote do_put_x87 ( Bool moveRegs,
156538a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj                       /*IN*/UChar* x87_state,
156638a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj                       /*OUT*/VexGuestX86State* vex_state )
15670c2cb623cca372a2b42b073121c7413cdaaf75besewardj{
1568a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   Int        stno, preg;
15690c2cb623cca372a2b42b073121c7413cdaaf75besewardj   UInt       tag;
1570c3778a2dd48ea461a4fb47e3d50877e94069fc7esewardj   ULong*     vexRegs = (ULong*)(&vex_state->guest_FPREG[0]);
1571f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj   UChar*     vexTags = (UChar*)(&vex_state->guest_FPTAG[0]);
15720c2cb623cca372a2b42b073121c7413cdaaf75besewardj   Fpu_State* x87     = (Fpu_State*)x87_state;
15730c2cb623cca372a2b42b073121c7413cdaaf75besewardj   UInt       ftop    = (x87->env[FP_ENV_STAT] >> 11) & 7;
15740c2cb623cca372a2b42b073121c7413cdaaf75besewardj   UInt       tagw    = x87->env[FP_ENV_TAG];
15756e0dbda4f7ea53dd29996d4d429d3c5c92ee3640sewardj   UInt       fpucw   = x87->env[FP_ENV_CTRL];
1576c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   UInt       c3210   = x87->env[FP_ENV_STAT] & 0x4700;
15776ef84bed9bb3af22060eb1759788034602bbcc88florian   VexEmNote  ew;
1578d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj   UInt       fpround;
1579893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj   ULong      pair;
15800c2cb623cca372a2b42b073121c7413cdaaf75besewardj
15810c2cb623cca372a2b42b073121c7413cdaaf75besewardj   /* Copy registers and tags */
1582a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   for (stno = 0; stno < 8; stno++) {
1583a0e83b06f304527e3e9aec527c344e35e7023d76sewardj      preg = (stno + ftop) & 7;
1584a0e83b06f304527e3e9aec527c344e35e7023d76sewardj      tag = (tagw >> (2*preg)) & 3;
15850c2cb623cca372a2b42b073121c7413cdaaf75besewardj      if (tag == 3) {
15860c2cb623cca372a2b42b073121c7413cdaaf75besewardj         /* register is empty */
1587a0e83b06f304527e3e9aec527c344e35e7023d76sewardj         /* hmm, if it's empty, does it still get written?  Probably
1588a0e83b06f304527e3e9aec527c344e35e7023d76sewardj            safer to say it does.  If we don't, memcheck could get out
1589a0e83b06f304527e3e9aec527c344e35e7023d76sewardj            of sync, in that it thinks all FP registers are defined by
1590a0e83b06f304527e3e9aec527c344e35e7023d76sewardj            this helper, but in reality some have not been updated. */
15910f33861a0aaf18e89f5f24fd5bdfa39a9049dadasewardj         if (moveRegs)
1592c3778a2dd48ea461a4fb47e3d50877e94069fc7esewardj            vexRegs[preg] = 0; /* IEEE754 64-bit zero */
1593a0e83b06f304527e3e9aec527c344e35e7023d76sewardj         vexTags[preg] = 0;
15940c2cb623cca372a2b42b073121c7413cdaaf75besewardj      } else {
15950c2cb623cca372a2b42b073121c7413cdaaf75besewardj         /* register is non-empty */
15967df596b1e36840e2d74c90aa55589934add61ccfsewardj         if (moveRegs)
1597a0e83b06f304527e3e9aec527c344e35e7023d76sewardj            convert_f80le_to_f64le( &x87->reg[10*stno],
1598a0e83b06f304527e3e9aec527c344e35e7023d76sewardj                                    (UChar*)&vexRegs[preg] );
1599a0e83b06f304527e3e9aec527c344e35e7023d76sewardj         vexTags[preg] = 1;
16000c2cb623cca372a2b42b073121c7413cdaaf75besewardj      }
16010c2cb623cca372a2b42b073121c7413cdaaf75besewardj   }
16020c2cb623cca372a2b42b073121c7413cdaaf75besewardj
16030c2cb623cca372a2b42b073121c7413cdaaf75besewardj   /* stack pointer */
1604f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj   vex_state->guest_FTOP = ftop;
16050c2cb623cca372a2b42b073121c7413cdaaf75besewardj
16063f868e5262a8d2488f41cc49058ba60c24843c3esewardj   /* status word */
1607f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj   vex_state->guest_FC3210 = c3210;
1608893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj
1609d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj   /* handle the control word, setting FPROUND and detecting any
1610893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj      emulation warnings. */
16113bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   pair    = x86g_check_fldcw ( (UInt)fpucw );
1612d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj   fpround = (UInt)pair;
16136ef84bed9bb3af22060eb1759788034602bbcc88florian   ew      = (VexEmNote)(pair >> 32);
1614893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj
1615d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj   vex_state->guest_FPROUND = fpround & 3;
1616893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj
1617893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj   /* emulation warnings --> caller */
1618893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj   return ew;
16190c2cb623cca372a2b42b073121c7413cdaaf75besewardj}
16200c2cb623cca372a2b42b073121c7413cdaaf75besewardj
16216e0dbda4f7ea53dd29996d4d429d3c5c92ee3640sewardj
1622a0e83b06f304527e3e9aec527c344e35e7023d76sewardj/* Create an x87 FPU state from the guest state, as close as
1623a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   we can approximate it. */
162438a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic
162538a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjvoid do_get_x87 ( /*IN*/VexGuestX86State* vex_state,
162638a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj                  /*OUT*/UChar* x87_state )
16270c2cb623cca372a2b42b073121c7413cdaaf75besewardj{
1628a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   Int        i, stno, preg;
16290c2cb623cca372a2b42b073121c7413cdaaf75besewardj   UInt       tagw;
1630c3778a2dd48ea461a4fb47e3d50877e94069fc7esewardj   ULong*     vexRegs = (ULong*)(&vex_state->guest_FPREG[0]);
1631f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj   UChar*     vexTags = (UChar*)(&vex_state->guest_FPTAG[0]);
16320c2cb623cca372a2b42b073121c7413cdaaf75besewardj   Fpu_State* x87     = (Fpu_State*)x87_state;
1633f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj   UInt       ftop    = vex_state->guest_FTOP;
1634f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj   UInt       c3210   = vex_state->guest_FC3210;
16350c2cb623cca372a2b42b073121c7413cdaaf75besewardj
16360c2cb623cca372a2b42b073121c7413cdaaf75besewardj   for (i = 0; i < 14; i++)
16370c2cb623cca372a2b42b073121c7413cdaaf75besewardj      x87->env[i] = 0;
16380c2cb623cca372a2b42b073121c7413cdaaf75besewardj
16390c2cb623cca372a2b42b073121c7413cdaaf75besewardj   x87->env[1] = x87->env[3] = x87->env[5] = x87->env[13] = 0xFFFF;
1640a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   x87->env[FP_ENV_STAT]
1641a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj      = toUShort(((ftop & 7) << 11) | (c3210 & 0x4700));
1642893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj   x87->env[FP_ENV_CTRL]
1643a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj      = toUShort(x86g_create_fpucw( vex_state->guest_FPROUND ));
16440c2cb623cca372a2b42b073121c7413cdaaf75besewardj
1645a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   /* Dump the register stack in ST order. */
16460c2cb623cca372a2b42b073121c7413cdaaf75besewardj   tagw = 0;
1647a0e83b06f304527e3e9aec527c344e35e7023d76sewardj   for (stno = 0; stno < 8; stno++) {
1648a0e83b06f304527e3e9aec527c344e35e7023d76sewardj      preg = (stno + ftop) & 7;
1649a0e83b06f304527e3e9aec527c344e35e7023d76sewardj      if (vexTags[preg] == 0) {
16500c2cb623cca372a2b42b073121c7413cdaaf75besewardj         /* register is empty */
1651a0e83b06f304527e3e9aec527c344e35e7023d76sewardj         tagw |= (3 << (2*preg));
1652a0e83b06f304527e3e9aec527c344e35e7023d76sewardj         convert_f64le_to_f80le( (UChar*)&vexRegs[preg],
1653a0e83b06f304527e3e9aec527c344e35e7023d76sewardj                                 &x87->reg[10*stno] );
16540c2cb623cca372a2b42b073121c7413cdaaf75besewardj      } else {
16550c2cb623cca372a2b42b073121c7413cdaaf75besewardj         /* register is full. */
1656a0e83b06f304527e3e9aec527c344e35e7023d76sewardj         tagw |= (0 << (2*preg));
1657a0e83b06f304527e3e9aec527c344e35e7023d76sewardj         convert_f64le_to_f80le( (UChar*)&vexRegs[preg],
1658a0e83b06f304527e3e9aec527c344e35e7023d76sewardj                                 &x87->reg[10*stno] );
16590c2cb623cca372a2b42b073121c7413cdaaf75besewardj      }
16600c2cb623cca372a2b42b073121c7413cdaaf75besewardj   }
1661a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   x87->env[FP_ENV_TAG] = toUShort(tagw);
16620c2cb623cca372a2b42b073121c7413cdaaf75besewardj}
16630c2cb623cca372a2b42b073121c7413cdaaf75besewardj
16640c2cb623cca372a2b42b073121c7413cdaaf75besewardj
1665893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/* CALLED FROM GENERATED CODE */
1666893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/* DIRTY HELPER (reads guest state, writes guest mem) */
1667893a3302cc943e2ad1db421a8e6a753f82f532a7sewardjvoid x86g_dirtyhelper_FXSAVE ( VexGuestX86State* gst, HWord addr )
1668f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj{
1669893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   /* Somewhat roundabout, but at least it's simple. */
1670893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   Fpu_State tmp;
1671893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   UShort*   addrS = (UShort*)addr;
1672893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   UChar*    addrC = (UChar*)addr;
1673893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   U128*     xmm   = (U128*)(addr + 160);
1674893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   UInt      mxcsr;
1675893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   UShort    fp_tags;
1676a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   UInt      summary_tags;
1677893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   Int       r, stno;
1678893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   UShort    *srcS, *dstS;
1679f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj
1680893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   do_get_x87( gst, (UChar*)&tmp );
1681893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   mxcsr = x86g_create_mxcsr( gst->guest_SSEROUND );
168276bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj
1683893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   /* Now build the proper fxsave image from the x87 image we just
1684893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      made. */
168576bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj
1686893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   addrS[0]  = tmp.env[FP_ENV_CTRL]; /* FCW: fpu control word */
1687893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   addrS[1]  = tmp.env[FP_ENV_STAT]; /* FCW: fpu status word */
168876bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj
1689893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   /* set addrS[2] in an endian-independent way */
1690893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   summary_tags = 0;
1691893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   fp_tags = tmp.env[FP_ENV_TAG];
1692893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   for (r = 0; r < 8; r++) {
1693893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      if ( ((fp_tags >> (2*r)) & 3) != 3 )
1694893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj         summary_tags |= (1 << r);
1695893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   }
1696a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   addrC[4]  = toUChar(summary_tags); /* FTW: tag summary byte */
1697893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   addrC[5]  = 0; /* pad */
169876bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj
1699893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   addrS[3]  = 0; /* FOP: fpu opcode (bogus) */
1700893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   addrS[4]  = 0;
1701893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   addrS[5]  = 0; /* FPU IP (bogus) */
1702893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   addrS[6]  = 0; /* FPU IP's segment selector (bogus) (although we
1703893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj                     could conceivably dump %CS here) */
1704c9a43665879a03886b27a65b68af2a2c11b04f59sewardj
1705893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   addrS[7]  = 0; /* Intel reserved */
1706c9a43665879a03886b27a65b68af2a2c11b04f59sewardj
1707893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   addrS[8]  = 0; /* FPU DP (operand pointer) (bogus) */
1708893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   addrS[9]  = 0; /* FPU DP (operand pointer) (bogus) */
1709893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   addrS[10] = 0; /* segment selector for above operand pointer; %DS
1710893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj                     perhaps? */
1711893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   addrS[11] = 0; /* Intel reserved */
1712c9a43665879a03886b27a65b68af2a2c11b04f59sewardj
1713a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   addrS[12] = toUShort(mxcsr);  /* MXCSR */
1714a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   addrS[13] = toUShort(mxcsr >> 16);
1715893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj
1716893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   addrS[14] = 0xFFFF; /* MXCSR mask (lo16); who knows what for */
1717893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   addrS[15] = 0xFFFF; /* MXCSR mask (hi16); who knows what for */
1718893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
1719893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   /* Copy in the FP registers, in ST order. */
1720893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   for (stno = 0; stno < 8; stno++) {
1721893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      srcS = (UShort*)(&tmp.reg[10*stno]);
1722893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      dstS = (UShort*)(&addrS[16 + 8*stno]);
1723893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      dstS[0] = srcS[0];
1724893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      dstS[1] = srcS[1];
1725893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      dstS[2] = srcS[2];
1726893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      dstS[3] = srcS[3];
1727893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      dstS[4] = srcS[4];
1728893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      dstS[5] = 0;
1729893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      dstS[6] = 0;
1730893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      dstS[7] = 0;
1731893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   }
1732893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
1733893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   /* That's the first 160 bytes of the image done.  Now only %xmm0
1734893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      .. %xmm7 remain to be copied.  If the host is big-endian, these
1735893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      need to be byte-swapped. */
1736893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vassert(host_is_little_endian());
1737893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
1738893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj#  define COPY_U128(_dst,_src)                       \
1739893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      do { _dst[0] = _src[0]; _dst[1] = _src[1];     \
1740893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj           _dst[2] = _src[2]; _dst[3] = _src[3]; }   \
1741893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      while (0)
1742893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
1743893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   COPY_U128( xmm[0], gst->guest_XMM0 );
1744893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   COPY_U128( xmm[1], gst->guest_XMM1 );
1745893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   COPY_U128( xmm[2], gst->guest_XMM2 );
1746893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   COPY_U128( xmm[3], gst->guest_XMM3 );
1747893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   COPY_U128( xmm[4], gst->guest_XMM4 );
1748893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   COPY_U128( xmm[5], gst->guest_XMM5 );
1749893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   COPY_U128( xmm[6], gst->guest_XMM6 );
1750893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   COPY_U128( xmm[7], gst->guest_XMM7 );
1751893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
1752893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj#  undef COPY_U128
1753dda7a4c98be4c7c6f11eab4e1cad6ab275aed79csewardj}
1754f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj
1755f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj
1756893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/* CALLED FROM GENERATED CODE */
17573800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj/* DIRTY HELPER (writes guest state, reads guest mem) */
17586ef84bed9bb3af22060eb1759788034602bbcc88florianVexEmNote x86g_dirtyhelper_FXRSTOR ( VexGuestX86State* gst, HWord addr )
17593800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj{
17603800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj   Fpu_State tmp;
17616ef84bed9bb3af22060eb1759788034602bbcc88florian   VexEmNote warnX87 = EmNote_NONE;
17626ef84bed9bb3af22060eb1759788034602bbcc88florian   VexEmNote warnXMM = EmNote_NONE;
17633800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj   UShort*   addrS   = (UShort*)addr;
17643800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj   UChar*    addrC   = (UChar*)addr;
17653800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj   U128*     xmm     = (U128*)(addr + 160);
17663800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj   UShort    fp_tags;
17673800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj   Int       r, stno, i;
17683800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj
17693800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj   /* Restore %xmm0 .. %xmm7.  If the host is big-endian, these need
17703800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj      to be byte-swapped. */
17713800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj   vassert(host_is_little_endian());
17723800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj
17733800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj#  define COPY_U128(_dst,_src)                       \
17743800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj      do { _dst[0] = _src[0]; _dst[1] = _src[1];     \
17753800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj           _dst[2] = _src[2]; _dst[3] = _src[3]; }   \
17763800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj      while (0)
17773800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj
17783800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj   COPY_U128( gst->guest_XMM0, xmm[0] );
17793800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj   COPY_U128( gst->guest_XMM1, xmm[1] );
17803800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj   COPY_U128( gst->guest_XMM2, xmm[2] );
17813800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj   COPY_U128( gst->guest_XMM3, xmm[3] );
17823800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj   COPY_U128( gst->guest_XMM4, xmm[4] );
17833800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj   COPY_U128( gst->guest_XMM5, xmm[5] );
17843800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj   COPY_U128( gst->guest_XMM6, xmm[6] );
17853800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj   COPY_U128( gst->guest_XMM7, xmm[7] );
17863800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj
17873800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj#  undef COPY_U128
17883800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj
17893800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj   /* Copy the x87 registers out of the image, into a temporary
17903800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj      Fpu_State struct. */
17910f30dbc3c88b854cbcc42c60c5ef6ae4c57785a4sewardj
17924ff2a1aa52dbed78055deba39c14c3978d12601csewardj   /* LLVM on Darwin turns the following loop into a movaps plus a
17934ff2a1aa52dbed78055deba39c14c3978d12601csewardj      handful of scalar stores.  This would work fine except for the
17944ff2a1aa52dbed78055deba39c14c3978d12601csewardj      fact that VEX doesn't keep the stack correctly (16-) aligned for
17954ff2a1aa52dbed78055deba39c14c3978d12601csewardj      the call, so it segfaults.  Hence, split the loop into two
17964ff2a1aa52dbed78055deba39c14c3978d12601csewardj      pieces (and pray LLVM doesn't merely glue them back together) so
17974ff2a1aa52dbed78055deba39c14c3978d12601csewardj      it's composed only of scalar stores and so is alignment
17984ff2a1aa52dbed78055deba39c14c3978d12601csewardj      insensitive.  Of course this is a kludge of the lamest kind --
17994ff2a1aa52dbed78055deba39c14c3978d12601csewardj      VEX should be fixed properly. */
18000f30dbc3c88b854cbcc42c60c5ef6ae4c57785a4sewardj   /* Code that seems to trigger the problem:
18010f30dbc3c88b854cbcc42c60c5ef6ae4c57785a4sewardj      for (i = 0; i < 14; i++) tmp.env[i] = 0; */
18020f30dbc3c88b854cbcc42c60c5ef6ae4c57785a4sewardj   for (i = 0; i < 7; i++) tmp.env[i+0] = 0;
18030f30dbc3c88b854cbcc42c60c5ef6ae4c57785a4sewardj   for (i = 0; i < 7; i++) tmp.env[i+7] = 0;
18040f30dbc3c88b854cbcc42c60c5ef6ae4c57785a4sewardj
18053800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj   for (i = 0; i < 80; i++) tmp.reg[i] = 0;
18063800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj   /* fill in tmp.reg[0..7] */
18073800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj   for (stno = 0; stno < 8; stno++) {
18083800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj      UShort* dstS = (UShort*)(&tmp.reg[10*stno]);
18093800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj      UShort* srcS = (UShort*)(&addrS[16 + 8*stno]);
18103800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj      dstS[0] = srcS[0];
18113800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj      dstS[1] = srcS[1];
18123800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj      dstS[2] = srcS[2];
18133800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj      dstS[3] = srcS[3];
18143800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj      dstS[4] = srcS[4];
18153800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj   }
18163800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj   /* fill in tmp.env[0..13] */
18173800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj   tmp.env[FP_ENV_CTRL] = addrS[0]; /* FCW: fpu control word */
18183800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj   tmp.env[FP_ENV_STAT] = addrS[1]; /* FCW: fpu status word */
18193800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj
18203800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj   fp_tags = 0;
18213800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj   for (r = 0; r < 8; r++) {
18223800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj      if (addrC[4] & (1<<r))
18233800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj         fp_tags |= (0 << (2*r)); /* EMPTY */
18243800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj      else
18253800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj         fp_tags |= (3 << (2*r)); /* VALID -- not really precise enough. */
18263800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj   }
18273800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj   tmp.env[FP_ENV_TAG] = fp_tags;
18283800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj
18293800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj   /* Now write 'tmp' into the guest state. */
18303800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj   warnX87 = do_put_x87( True/*moveRegs*/, (UChar*)&tmp, gst );
18313800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj
18323800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj   { UInt w32 = (((UInt)addrS[12]) & 0xFFFF)
18333800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj                | ((((UInt)addrS[13]) & 0xFFFF) << 16);
18343800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj     ULong w64 = x86g_check_ldmxcsr( w32 );
18353800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj
18366ef84bed9bb3af22060eb1759788034602bbcc88florian     warnXMM = (VexEmNote)(w64 >> 32);
18373800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj
18383800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj     gst->guest_SSEROUND = (UInt)w64;
18393800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj   }
18403800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj
18413800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj   /* Prefer an X87 emwarn over an XMM one, if both exist. */
18426ef84bed9bb3af22060eb1759788034602bbcc88florian   if (warnX87 != EmNote_NONE)
18433800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj      return warnX87;
18443800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj   else
18453800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj      return warnXMM;
18463800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj}
18473800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj
18483800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj
18493800e2d3c23c6480b0bfbaf04444d6b10628b25esewardj/* CALLED FROM GENERATED CODE */
1850893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/* DIRTY HELPER (reads guest state, writes guest mem) */
1851893a3302cc943e2ad1db421a8e6a753f82f532a7sewardjvoid x86g_dirtyhelper_FSAVE ( VexGuestX86State* gst, HWord addr )
1852893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj{
1853893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   do_get_x87( gst, (UChar*)addr );
1854893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj}
1855893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
1856893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/* CALLED FROM GENERATED CODE */
1857893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/* DIRTY HELPER (writes guest state, reads guest mem) */
18586ef84bed9bb3af22060eb1759788034602bbcc88florianVexEmNote x86g_dirtyhelper_FRSTOR ( VexGuestX86State* gst, HWord addr )
1859893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj{
1860893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   return do_put_x87( True/*regs too*/, (UChar*)addr, gst );
1861893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj}
1862893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
1863893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/* CALLED FROM GENERATED CODE */
1864893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/* DIRTY HELPER (reads guest state, writes guest mem) */
1865893a3302cc943e2ad1db421a8e6a753f82f532a7sewardjvoid x86g_dirtyhelper_FSTENV ( VexGuestX86State* gst, HWord addr )
1866893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj{
1867893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   /* Somewhat roundabout, but at least it's simple. */
1868893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   Int       i;
1869893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   UShort*   addrP = (UShort*)addr;
1870893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   Fpu_State tmp;
1871893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   do_get_x87( gst, (UChar*)&tmp );
1872893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   for (i = 0; i < 14; i++)
1873893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj      addrP[i] = tmp.env[i];
1874893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj}
1875893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
1876893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/* CALLED FROM GENERATED CODE */
1877893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/* DIRTY HELPER (writes guest state, reads guest mem) */
18786ef84bed9bb3af22060eb1759788034602bbcc88florianVexEmNote x86g_dirtyhelper_FLDENV ( VexGuestX86State* gst, HWord addr )
1879893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj{
1880893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   return do_put_x87( False/*don't move regs*/, (UChar*)addr, gst);
1881893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj}
1882893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
1883893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
1884893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/*---------------------------------------------------------------*/
1885893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/*--- Misc integer helpers, including rotates and CPUID.      ---*/
1886893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/*---------------------------------------------------------------*/
18879aebb0c3f7a7f43313786826f31402f2b733badfsewardj
18889aebb0c3f7a7f43313786826f31402f2b733badfsewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
18899aebb0c3f7a7f43313786826f31402f2b733badfsewardj/* Calculate both flags and value result for rotate right
18909aebb0c3f7a7f43313786826f31402f2b733badfsewardj   through the carry bit.  Result in low 32 bits,
18919aebb0c3f7a7f43313786826f31402f2b733badfsewardj   new flags (OSZACP) in high 32 bits.
18929aebb0c3f7a7f43313786826f31402f2b733badfsewardj*/
18932a9ad023890d3b34cf45e429df2a8ae88b419128sewardjULong x86g_calculate_RCR ( UInt arg, UInt rot_amt, UInt eflags_in, UInt sz )
18949aebb0c3f7a7f43313786826f31402f2b733badfsewardj{
18959aebb0c3f7a7f43313786826f31402f2b733badfsewardj   UInt tempCOUNT = rot_amt & 0x1F, cf=0, of=0, tempcf;
18969aebb0c3f7a7f43313786826f31402f2b733badfsewardj
18979aebb0c3f7a7f43313786826f31402f2b733badfsewardj   switch (sz) {
18989aebb0c3f7a7f43313786826f31402f2b733badfsewardj      case 4:
18992a9ad023890d3b34cf45e429df2a8ae88b419128sewardj         cf        = (eflags_in >> X86G_CC_SHIFT_C) & 1;
19009aebb0c3f7a7f43313786826f31402f2b733badfsewardj         of        = ((arg >> 31) ^ cf) & 1;
19019aebb0c3f7a7f43313786826f31402f2b733badfsewardj         while (tempCOUNT > 0) {
19029aebb0c3f7a7f43313786826f31402f2b733badfsewardj            tempcf = arg & 1;
19039aebb0c3f7a7f43313786826f31402f2b733badfsewardj            arg    = (arg >> 1) | (cf << 31);
19049aebb0c3f7a7f43313786826f31402f2b733badfsewardj            cf     = tempcf;
19059aebb0c3f7a7f43313786826f31402f2b733badfsewardj            tempCOUNT--;
19069aebb0c3f7a7f43313786826f31402f2b733badfsewardj         }
19079aebb0c3f7a7f43313786826f31402f2b733badfsewardj         break;
19089aebb0c3f7a7f43313786826f31402f2b733badfsewardj      case 2:
19099aebb0c3f7a7f43313786826f31402f2b733badfsewardj         while (tempCOUNT >= 17) tempCOUNT -= 17;
19102a9ad023890d3b34cf45e429df2a8ae88b419128sewardj         cf        = (eflags_in >> X86G_CC_SHIFT_C) & 1;
19119aebb0c3f7a7f43313786826f31402f2b733badfsewardj         of        = ((arg >> 15) ^ cf) & 1;
19129aebb0c3f7a7f43313786826f31402f2b733badfsewardj         while (tempCOUNT > 0) {
19139aebb0c3f7a7f43313786826f31402f2b733badfsewardj            tempcf = arg & 1;
19149aebb0c3f7a7f43313786826f31402f2b733badfsewardj            arg    = ((arg >> 1) & 0x7FFF) | (cf << 15);
19159aebb0c3f7a7f43313786826f31402f2b733badfsewardj            cf     = tempcf;
19169aebb0c3f7a7f43313786826f31402f2b733badfsewardj            tempCOUNT--;
19179aebb0c3f7a7f43313786826f31402f2b733badfsewardj         }
19189aebb0c3f7a7f43313786826f31402f2b733badfsewardj         break;
19199aebb0c3f7a7f43313786826f31402f2b733badfsewardj      case 1:
19209aebb0c3f7a7f43313786826f31402f2b733badfsewardj         while (tempCOUNT >= 9) tempCOUNT -= 9;
19212a9ad023890d3b34cf45e429df2a8ae88b419128sewardj         cf        = (eflags_in >> X86G_CC_SHIFT_C) & 1;
19229aebb0c3f7a7f43313786826f31402f2b733badfsewardj         of        = ((arg >> 7) ^ cf) & 1;
19239aebb0c3f7a7f43313786826f31402f2b733badfsewardj         while (tempCOUNT > 0) {
19249aebb0c3f7a7f43313786826f31402f2b733badfsewardj            tempcf = arg & 1;
19259aebb0c3f7a7f43313786826f31402f2b733badfsewardj            arg    = ((arg >> 1) & 0x7F) | (cf << 7);
19269aebb0c3f7a7f43313786826f31402f2b733badfsewardj            cf     = tempcf;
19279aebb0c3f7a7f43313786826f31402f2b733badfsewardj            tempCOUNT--;
19289aebb0c3f7a7f43313786826f31402f2b733badfsewardj         }
19299aebb0c3f7a7f43313786826f31402f2b733badfsewardj         break;
19309aebb0c3f7a7f43313786826f31402f2b733badfsewardj      default:
19319aebb0c3f7a7f43313786826f31402f2b733badfsewardj         vpanic("calculate_RCR: invalid size");
19329aebb0c3f7a7f43313786826f31402f2b733badfsewardj   }
19339aebb0c3f7a7f43313786826f31402f2b733badfsewardj
19349aebb0c3f7a7f43313786826f31402f2b733badfsewardj   cf &= 1;
19359aebb0c3f7a7f43313786826f31402f2b733badfsewardj   of &= 1;
19362a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   eflags_in &= ~(X86G_CC_MASK_C | X86G_CC_MASK_O);
19372a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   eflags_in |= (cf << X86G_CC_SHIFT_C) | (of << X86G_CC_SHIFT_O);
19389aebb0c3f7a7f43313786826f31402f2b733badfsewardj
19399aebb0c3f7a7f43313786826f31402f2b733badfsewardj   return (((ULong)eflags_in) << 32) | ((ULong)arg);
19409aebb0c3f7a7f43313786826f31402f2b733badfsewardj}
19419aebb0c3f7a7f43313786826f31402f2b733badfsewardj
19427cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardj
19432eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
19442eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj/* Calculate both flags and value result for rotate left
19452eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj   through the carry bit.  Result in low 32 bits,
19462eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj   new flags (OSZACP) in high 32 bits.
19472eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj*/
19482eef773d07df9bbc5d62c0058ae99d5511c2759dsewardjULong x86g_calculate_RCL ( UInt arg, UInt rot_amt, UInt eflags_in, UInt sz )
19492eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj{
19502eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj   UInt tempCOUNT = rot_amt & 0x1F, cf=0, of=0, tempcf;
19512eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj
19522eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj   switch (sz) {
19532eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj      case 4:
19542eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj         cf = (eflags_in >> X86G_CC_SHIFT_C) & 1;
19552eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj         while (tempCOUNT > 0) {
19562eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj            tempcf = (arg >> 31) & 1;
19572eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj            arg    = (arg << 1) | (cf & 1);
19582eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj            cf     = tempcf;
19592eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj            tempCOUNT--;
19602eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj         }
19612eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj         of = ((arg >> 31) ^ cf) & 1;
19622eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj         break;
19632eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj      case 2:
19642eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj         while (tempCOUNT >= 17) tempCOUNT -= 17;
19652eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj         cf = (eflags_in >> X86G_CC_SHIFT_C) & 1;
19662eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj         while (tempCOUNT > 0) {
19672eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj            tempcf = (arg >> 15) & 1;
19682eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj            arg    = 0xFFFF & ((arg << 1) | (cf & 1));
19692eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj            cf     = tempcf;
19702eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj            tempCOUNT--;
19712eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj         }
19722eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj         of = ((arg >> 15) ^ cf) & 1;
19732eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj         break;
19742eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj      case 1:
19752eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj         while (tempCOUNT >= 9) tempCOUNT -= 9;
19762eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj         cf = (eflags_in >> X86G_CC_SHIFT_C) & 1;
19772eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj         while (tempCOUNT > 0) {
19782eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj            tempcf = (arg >> 7) & 1;
19792eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj            arg    = 0xFF & ((arg << 1) | (cf & 1));
19802eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj            cf     = tempcf;
19812eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj            tempCOUNT--;
19822eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj         }
19832eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj         of = ((arg >> 7) ^ cf) & 1;
19842eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj         break;
19852eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj      default:
19862eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj         vpanic("calculate_RCL: invalid size");
19872eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj   }
19882eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj
19892eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj   cf &= 1;
19902eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj   of &= 1;
19912eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj   eflags_in &= ~(X86G_CC_MASK_C | X86G_CC_MASK_O);
19922eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj   eflags_in |= (cf << X86G_CC_SHIFT_C) | (of << X86G_CC_SHIFT_O);
19932eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj
19942eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj   return (((ULong)eflags_in) << 32) | ((ULong)arg);
19952eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj}
19962eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj
19972eef773d07df9bbc5d62c0058ae99d5511c2759dsewardj
19988edc36b45e95a7ec9879a25b80390129f1d334c1sewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
19998edc36b45e95a7ec9879a25b80390129f1d334c1sewardj/* Calculate both flags and value result for DAA/DAS/AAA/AAS.
20008edc36b45e95a7ec9879a25b80390129f1d334c1sewardj   AX value in low half of arg, OSZACP in upper half.
20018edc36b45e95a7ec9879a25b80390129f1d334c1sewardj   See guest-x86/toIR.c usage point for details.
20028edc36b45e95a7ec9879a25b80390129f1d334c1sewardj*/
20038edc36b45e95a7ec9879a25b80390129f1d334c1sewardjstatic UInt calc_parity_8bit ( UInt w32 ) {
20048edc36b45e95a7ec9879a25b80390129f1d334c1sewardj   UInt i;
20058edc36b45e95a7ec9879a25b80390129f1d334c1sewardj   UInt p = 1;
20068edc36b45e95a7ec9879a25b80390129f1d334c1sewardj   for (i = 0; i < 8; i++)
20078edc36b45e95a7ec9879a25b80390129f1d334c1sewardj      p ^= (1 & (w32 >> i));
20088edc36b45e95a7ec9879a25b80390129f1d334c1sewardj   return p;
20098edc36b45e95a7ec9879a25b80390129f1d334c1sewardj}
20108edc36b45e95a7ec9879a25b80390129f1d334c1sewardjUInt x86g_calculate_daa_das_aaa_aas ( UInt flags_and_AX, UInt opcode )
20118edc36b45e95a7ec9879a25b80390129f1d334c1sewardj{
20128edc36b45e95a7ec9879a25b80390129f1d334c1sewardj   UInt r_AL = (flags_and_AX >> 0) & 0xFF;
20138edc36b45e95a7ec9879a25b80390129f1d334c1sewardj   UInt r_AH = (flags_and_AX >> 8) & 0xFF;
20148edc36b45e95a7ec9879a25b80390129f1d334c1sewardj   UInt r_O  = (flags_and_AX >> (16 + X86G_CC_SHIFT_O)) & 1;
20158edc36b45e95a7ec9879a25b80390129f1d334c1sewardj   UInt r_S  = (flags_and_AX >> (16 + X86G_CC_SHIFT_S)) & 1;
20168edc36b45e95a7ec9879a25b80390129f1d334c1sewardj   UInt r_Z  = (flags_and_AX >> (16 + X86G_CC_SHIFT_Z)) & 1;
20178edc36b45e95a7ec9879a25b80390129f1d334c1sewardj   UInt r_A  = (flags_and_AX >> (16 + X86G_CC_SHIFT_A)) & 1;
20188edc36b45e95a7ec9879a25b80390129f1d334c1sewardj   UInt r_C  = (flags_and_AX >> (16 + X86G_CC_SHIFT_C)) & 1;
20198edc36b45e95a7ec9879a25b80390129f1d334c1sewardj   UInt r_P  = (flags_and_AX >> (16 + X86G_CC_SHIFT_P)) & 1;
20208edc36b45e95a7ec9879a25b80390129f1d334c1sewardj   UInt result = 0;
20218edc36b45e95a7ec9879a25b80390129f1d334c1sewardj
20228edc36b45e95a7ec9879a25b80390129f1d334c1sewardj   switch (opcode) {
20238edc36b45e95a7ec9879a25b80390129f1d334c1sewardj      case 0x27: { /* DAA */
20248edc36b45e95a7ec9879a25b80390129f1d334c1sewardj         UInt old_AL = r_AL;
20258edc36b45e95a7ec9879a25b80390129f1d334c1sewardj         UInt old_C  = r_C;
20268edc36b45e95a7ec9879a25b80390129f1d334c1sewardj         r_C = 0;
20278edc36b45e95a7ec9879a25b80390129f1d334c1sewardj         if ((r_AL & 0xF) > 9 || r_A == 1) {
20288edc36b45e95a7ec9879a25b80390129f1d334c1sewardj            r_AL = r_AL + 6;
20298edc36b45e95a7ec9879a25b80390129f1d334c1sewardj            r_C  = old_C;
20308edc36b45e95a7ec9879a25b80390129f1d334c1sewardj            if (r_AL >= 0x100) r_C = 1;
20318edc36b45e95a7ec9879a25b80390129f1d334c1sewardj            r_A = 1;
20328edc36b45e95a7ec9879a25b80390129f1d334c1sewardj         } else {
20338edc36b45e95a7ec9879a25b80390129f1d334c1sewardj            r_A = 0;
20348edc36b45e95a7ec9879a25b80390129f1d334c1sewardj         }
20358edc36b45e95a7ec9879a25b80390129f1d334c1sewardj         if (old_AL > 0x99 || old_C == 1) {
20368edc36b45e95a7ec9879a25b80390129f1d334c1sewardj            r_AL = r_AL + 0x60;
20378edc36b45e95a7ec9879a25b80390129f1d334c1sewardj            r_C  = 1;
20388edc36b45e95a7ec9879a25b80390129f1d334c1sewardj         } else {
20398edc36b45e95a7ec9879a25b80390129f1d334c1sewardj            r_C = 0;
20408edc36b45e95a7ec9879a25b80390129f1d334c1sewardj         }
20418edc36b45e95a7ec9879a25b80390129f1d334c1sewardj         /* O is undefined.  S Z and P are set according to the
20428edc36b45e95a7ec9879a25b80390129f1d334c1sewardj	    result. */
20438edc36b45e95a7ec9879a25b80390129f1d334c1sewardj         r_AL &= 0xFF;
20448edc36b45e95a7ec9879a25b80390129f1d334c1sewardj         r_O = 0; /* let's say */
20458edc36b45e95a7ec9879a25b80390129f1d334c1sewardj         r_S = (r_AL & 0x80) ? 1 : 0;
20468edc36b45e95a7ec9879a25b80390129f1d334c1sewardj         r_Z = (r_AL == 0) ? 1 : 0;
20478edc36b45e95a7ec9879a25b80390129f1d334c1sewardj         r_P = calc_parity_8bit( r_AL );
20488edc36b45e95a7ec9879a25b80390129f1d334c1sewardj         break;
20498edc36b45e95a7ec9879a25b80390129f1d334c1sewardj      }
20508edc36b45e95a7ec9879a25b80390129f1d334c1sewardj      case 0x2F: { /* DAS */
20518edc36b45e95a7ec9879a25b80390129f1d334c1sewardj         UInt old_AL = r_AL;
20528edc36b45e95a7ec9879a25b80390129f1d334c1sewardj         UInt old_C  = r_C;
20538edc36b45e95a7ec9879a25b80390129f1d334c1sewardj         r_C = 0;
20548edc36b45e95a7ec9879a25b80390129f1d334c1sewardj         if ((r_AL & 0xF) > 9 || r_A == 1) {
20558edc36b45e95a7ec9879a25b80390129f1d334c1sewardj            Bool borrow = r_AL < 6;
20568edc36b45e95a7ec9879a25b80390129f1d334c1sewardj            r_AL = r_AL - 6;
20578edc36b45e95a7ec9879a25b80390129f1d334c1sewardj            r_C  = old_C;
20588edc36b45e95a7ec9879a25b80390129f1d334c1sewardj            if (borrow) r_C = 1;
20598edc36b45e95a7ec9879a25b80390129f1d334c1sewardj            r_A = 1;
20608edc36b45e95a7ec9879a25b80390129f1d334c1sewardj         } else {
20618edc36b45e95a7ec9879a25b80390129f1d334c1sewardj            r_A = 0;
20628edc36b45e95a7ec9879a25b80390129f1d334c1sewardj         }
20638edc36b45e95a7ec9879a25b80390129f1d334c1sewardj         if (old_AL > 0x99 || old_C == 1) {
20648edc36b45e95a7ec9879a25b80390129f1d334c1sewardj            r_AL = r_AL - 0x60;
20658edc36b45e95a7ec9879a25b80390129f1d334c1sewardj            r_C  = 1;
20668edc36b45e95a7ec9879a25b80390129f1d334c1sewardj         } else {
20678edc36b45e95a7ec9879a25b80390129f1d334c1sewardj            /* Intel docs are wrong: r_C = 0; */
20688edc36b45e95a7ec9879a25b80390129f1d334c1sewardj         }
20698edc36b45e95a7ec9879a25b80390129f1d334c1sewardj         /* O is undefined.  S Z and P are set according to the
20708edc36b45e95a7ec9879a25b80390129f1d334c1sewardj	    result. */
20718edc36b45e95a7ec9879a25b80390129f1d334c1sewardj         r_AL &= 0xFF;
20728edc36b45e95a7ec9879a25b80390129f1d334c1sewardj         r_O = 0; /* let's say */
20738edc36b45e95a7ec9879a25b80390129f1d334c1sewardj         r_S = (r_AL & 0x80) ? 1 : 0;
20748edc36b45e95a7ec9879a25b80390129f1d334c1sewardj         r_Z = (r_AL == 0) ? 1 : 0;
20758edc36b45e95a7ec9879a25b80390129f1d334c1sewardj         r_P = calc_parity_8bit( r_AL );
20768edc36b45e95a7ec9879a25b80390129f1d334c1sewardj         break;
20778edc36b45e95a7ec9879a25b80390129f1d334c1sewardj      }
20788edc36b45e95a7ec9879a25b80390129f1d334c1sewardj      case 0x37: { /* AAA */
20798edc36b45e95a7ec9879a25b80390129f1d334c1sewardj         Bool nudge = r_AL > 0xF9;
20808edc36b45e95a7ec9879a25b80390129f1d334c1sewardj         if ((r_AL & 0xF) > 9 || r_A == 1) {
20818edc36b45e95a7ec9879a25b80390129f1d334c1sewardj            r_AL = r_AL + 6;
20828edc36b45e95a7ec9879a25b80390129f1d334c1sewardj            r_AH = r_AH + 1 + (nudge ? 1 : 0);
20838edc36b45e95a7ec9879a25b80390129f1d334c1sewardj            r_A  = 1;
20848edc36b45e95a7ec9879a25b80390129f1d334c1sewardj            r_C  = 1;
20858edc36b45e95a7ec9879a25b80390129f1d334c1sewardj            r_AL = r_AL & 0xF;
20868edc36b45e95a7ec9879a25b80390129f1d334c1sewardj         } else {
20878edc36b45e95a7ec9879a25b80390129f1d334c1sewardj            r_A  = 0;
20888edc36b45e95a7ec9879a25b80390129f1d334c1sewardj            r_C  = 0;
20898edc36b45e95a7ec9879a25b80390129f1d334c1sewardj            r_AL = r_AL & 0xF;
20908edc36b45e95a7ec9879a25b80390129f1d334c1sewardj         }
20918edc36b45e95a7ec9879a25b80390129f1d334c1sewardj         /* O S Z and P are undefined. */
20928edc36b45e95a7ec9879a25b80390129f1d334c1sewardj         r_O = r_S = r_Z = r_P = 0; /* let's say */
20938edc36b45e95a7ec9879a25b80390129f1d334c1sewardj         break;
20948edc36b45e95a7ec9879a25b80390129f1d334c1sewardj      }
20958edc36b45e95a7ec9879a25b80390129f1d334c1sewardj      case 0x3F: { /* AAS */
20968edc36b45e95a7ec9879a25b80390129f1d334c1sewardj         Bool nudge = r_AL < 0x06;
20978edc36b45e95a7ec9879a25b80390129f1d334c1sewardj         if ((r_AL & 0xF) > 9 || r_A == 1) {
20988edc36b45e95a7ec9879a25b80390129f1d334c1sewardj            r_AL = r_AL - 6;
20998edc36b45e95a7ec9879a25b80390129f1d334c1sewardj            r_AH = r_AH - 1 - (nudge ? 1 : 0);
21008edc36b45e95a7ec9879a25b80390129f1d334c1sewardj            r_A  = 1;
21018edc36b45e95a7ec9879a25b80390129f1d334c1sewardj            r_C  = 1;
21028edc36b45e95a7ec9879a25b80390129f1d334c1sewardj            r_AL = r_AL & 0xF;
21038edc36b45e95a7ec9879a25b80390129f1d334c1sewardj         } else {
21048edc36b45e95a7ec9879a25b80390129f1d334c1sewardj            r_A  = 0;
21058edc36b45e95a7ec9879a25b80390129f1d334c1sewardj            r_C  = 0;
21068edc36b45e95a7ec9879a25b80390129f1d334c1sewardj            r_AL = r_AL & 0xF;
21078edc36b45e95a7ec9879a25b80390129f1d334c1sewardj         }
21088edc36b45e95a7ec9879a25b80390129f1d334c1sewardj         /* O S Z and P are undefined. */
21098edc36b45e95a7ec9879a25b80390129f1d334c1sewardj         r_O = r_S = r_Z = r_P = 0; /* let's say */
21108edc36b45e95a7ec9879a25b80390129f1d334c1sewardj         break;
21118edc36b45e95a7ec9879a25b80390129f1d334c1sewardj      }
21128edc36b45e95a7ec9879a25b80390129f1d334c1sewardj      default:
21138edc36b45e95a7ec9879a25b80390129f1d334c1sewardj         vassert(0);
21148edc36b45e95a7ec9879a25b80390129f1d334c1sewardj   }
21158edc36b45e95a7ec9879a25b80390129f1d334c1sewardj   result =   ( (r_O & 1) << (16 + X86G_CC_SHIFT_O) )
21168edc36b45e95a7ec9879a25b80390129f1d334c1sewardj            | ( (r_S & 1) << (16 + X86G_CC_SHIFT_S) )
21178edc36b45e95a7ec9879a25b80390129f1d334c1sewardj            | ( (r_Z & 1) << (16 + X86G_CC_SHIFT_Z) )
21188edc36b45e95a7ec9879a25b80390129f1d334c1sewardj            | ( (r_A & 1) << (16 + X86G_CC_SHIFT_A) )
21198edc36b45e95a7ec9879a25b80390129f1d334c1sewardj            | ( (r_C & 1) << (16 + X86G_CC_SHIFT_C) )
21208edc36b45e95a7ec9879a25b80390129f1d334c1sewardj            | ( (r_P & 1) << (16 + X86G_CC_SHIFT_P) )
21218edc36b45e95a7ec9879a25b80390129f1d334c1sewardj            | ( (r_AH & 0xFF) << 8 )
21228edc36b45e95a7ec9879a25b80390129f1d334c1sewardj            | ( (r_AL & 0xFF) << 0 );
21238edc36b45e95a7ec9879a25b80390129f1d334c1sewardj   return result;
21248edc36b45e95a7ec9879a25b80390129f1d334c1sewardj}
21258edc36b45e95a7ec9879a25b80390129f1d334c1sewardj
2126321bbbf4a200e69496eb0a48506d3b67a1cdbbdbsewardjUInt x86g_calculate_aad_aam ( UInt flags_and_AX, UInt opcode )
2127321bbbf4a200e69496eb0a48506d3b67a1cdbbdbsewardj{
2128321bbbf4a200e69496eb0a48506d3b67a1cdbbdbsewardj   UInt r_AL = (flags_and_AX >> 0) & 0xFF;
2129321bbbf4a200e69496eb0a48506d3b67a1cdbbdbsewardj   UInt r_AH = (flags_and_AX >> 8) & 0xFF;
2130321bbbf4a200e69496eb0a48506d3b67a1cdbbdbsewardj   UInt r_O  = (flags_and_AX >> (16 + X86G_CC_SHIFT_O)) & 1;
2131321bbbf4a200e69496eb0a48506d3b67a1cdbbdbsewardj   UInt r_S  = (flags_and_AX >> (16 + X86G_CC_SHIFT_S)) & 1;
2132321bbbf4a200e69496eb0a48506d3b67a1cdbbdbsewardj   UInt r_Z  = (flags_and_AX >> (16 + X86G_CC_SHIFT_Z)) & 1;
2133321bbbf4a200e69496eb0a48506d3b67a1cdbbdbsewardj   UInt r_A  = (flags_and_AX >> (16 + X86G_CC_SHIFT_A)) & 1;
2134321bbbf4a200e69496eb0a48506d3b67a1cdbbdbsewardj   UInt r_C  = (flags_and_AX >> (16 + X86G_CC_SHIFT_C)) & 1;
2135321bbbf4a200e69496eb0a48506d3b67a1cdbbdbsewardj   UInt r_P  = (flags_and_AX >> (16 + X86G_CC_SHIFT_P)) & 1;
2136321bbbf4a200e69496eb0a48506d3b67a1cdbbdbsewardj   UInt result = 0;
2137321bbbf4a200e69496eb0a48506d3b67a1cdbbdbsewardj
2138321bbbf4a200e69496eb0a48506d3b67a1cdbbdbsewardj   switch (opcode) {
2139321bbbf4a200e69496eb0a48506d3b67a1cdbbdbsewardj      case 0xD4: { /* AAM */
2140321bbbf4a200e69496eb0a48506d3b67a1cdbbdbsewardj         r_AH = r_AL / 10;
2141321bbbf4a200e69496eb0a48506d3b67a1cdbbdbsewardj         r_AL = r_AL % 10;
2142321bbbf4a200e69496eb0a48506d3b67a1cdbbdbsewardj         break;
2143321bbbf4a200e69496eb0a48506d3b67a1cdbbdbsewardj      }
2144321bbbf4a200e69496eb0a48506d3b67a1cdbbdbsewardj      case 0xD5: { /* AAD */
2145321bbbf4a200e69496eb0a48506d3b67a1cdbbdbsewardj         r_AL = ((r_AH * 10) + r_AL) & 0xff;
2146321bbbf4a200e69496eb0a48506d3b67a1cdbbdbsewardj         r_AH = 0;
2147321bbbf4a200e69496eb0a48506d3b67a1cdbbdbsewardj         break;
2148321bbbf4a200e69496eb0a48506d3b67a1cdbbdbsewardj      }
2149321bbbf4a200e69496eb0a48506d3b67a1cdbbdbsewardj      default:
2150321bbbf4a200e69496eb0a48506d3b67a1cdbbdbsewardj         vassert(0);
2151321bbbf4a200e69496eb0a48506d3b67a1cdbbdbsewardj   }
2152321bbbf4a200e69496eb0a48506d3b67a1cdbbdbsewardj
2153321bbbf4a200e69496eb0a48506d3b67a1cdbbdbsewardj   r_O = 0; /* let's say (undefined) */
2154321bbbf4a200e69496eb0a48506d3b67a1cdbbdbsewardj   r_C = 0; /* let's say (undefined) */
2155321bbbf4a200e69496eb0a48506d3b67a1cdbbdbsewardj   r_A = 0; /* let's say (undefined) */
2156321bbbf4a200e69496eb0a48506d3b67a1cdbbdbsewardj   r_S = (r_AL & 0x80) ? 1 : 0;
2157321bbbf4a200e69496eb0a48506d3b67a1cdbbdbsewardj   r_Z = (r_AL == 0) ? 1 : 0;
2158321bbbf4a200e69496eb0a48506d3b67a1cdbbdbsewardj   r_P = calc_parity_8bit( r_AL );
2159321bbbf4a200e69496eb0a48506d3b67a1cdbbdbsewardj
2160321bbbf4a200e69496eb0a48506d3b67a1cdbbdbsewardj   result =   ( (r_O & 1) << (16 + X86G_CC_SHIFT_O) )
2161321bbbf4a200e69496eb0a48506d3b67a1cdbbdbsewardj            | ( (r_S & 1) << (16 + X86G_CC_SHIFT_S) )
2162321bbbf4a200e69496eb0a48506d3b67a1cdbbdbsewardj            | ( (r_Z & 1) << (16 + X86G_CC_SHIFT_Z) )
2163321bbbf4a200e69496eb0a48506d3b67a1cdbbdbsewardj            | ( (r_A & 1) << (16 + X86G_CC_SHIFT_A) )
2164321bbbf4a200e69496eb0a48506d3b67a1cdbbdbsewardj            | ( (r_C & 1) << (16 + X86G_CC_SHIFT_C) )
2165321bbbf4a200e69496eb0a48506d3b67a1cdbbdbsewardj            | ( (r_P & 1) << (16 + X86G_CC_SHIFT_P) )
2166321bbbf4a200e69496eb0a48506d3b67a1cdbbdbsewardj            | ( (r_AH & 0xFF) << 8 )
2167321bbbf4a200e69496eb0a48506d3b67a1cdbbdbsewardj            | ( (r_AL & 0xFF) << 0 );
2168321bbbf4a200e69496eb0a48506d3b67a1cdbbdbsewardj   return result;
2169321bbbf4a200e69496eb0a48506d3b67a1cdbbdbsewardj}
2170321bbbf4a200e69496eb0a48506d3b67a1cdbbdbsewardj
21718edc36b45e95a7ec9879a25b80390129f1d334c1sewardj
21727cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardj/* CALLED FROM GENERATED CODE */
21734ed6429074bf94661586d751fbecac530f5e8156sewardj/* DIRTY HELPER (non-referentially-transparent) */
21744ed6429074bf94661586d751fbecac530f5e8156sewardj/* Horrible hack.  On non-x86 platforms, return 1. */
21754ed6429074bf94661586d751fbecac530f5e8156sewardjULong x86g_dirtyhelper_RDTSC ( void )
21764ed6429074bf94661586d751fbecac530f5e8156sewardj{
21774ed6429074bf94661586d751fbecac530f5e8156sewardj#  if defined(__i386__)
21784ed6429074bf94661586d751fbecac530f5e8156sewardj   ULong res;
21794ed6429074bf94661586d751fbecac530f5e8156sewardj   __asm__ __volatile__("rdtsc" : "=A" (res));
21804ed6429074bf94661586d751fbecac530f5e8156sewardj   return res;
21814ed6429074bf94661586d751fbecac530f5e8156sewardj#  else
21824ed6429074bf94661586d751fbecac530f5e8156sewardj   return 1ULL;
21834ed6429074bf94661586d751fbecac530f5e8156sewardj#  endif
21844ed6429074bf94661586d751fbecac530f5e8156sewardj}
21854ed6429074bf94661586d751fbecac530f5e8156sewardj
21864ed6429074bf94661586d751fbecac530f5e8156sewardj
21874ed6429074bf94661586d751fbecac530f5e8156sewardj/* CALLED FROM GENERATED CODE */
21887cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardj/* DIRTY HELPER (modifies guest state) */
21894ba6ed0799fcf768e3fb9627fabc52fb1d6c2a6csewardj/* Claim to be a P55C (Intel Pentium/MMX) */
21909df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardjvoid x86g_dirtyhelper_CPUID_sse0 ( VexGuestX86State* st )
21917cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardj{
21929df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   switch (st->guest_EAX) {
21939df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj      case 0:
21949df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EAX = 0x1;
21959df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EBX = 0x756e6547;
21969df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_ECX = 0x6c65746e;
21979df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EDX = 0x49656e69;
21989df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         break;
21999df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj      default:
22009df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EAX = 0x543;
22019df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EBX = 0x0;
22029df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_ECX = 0x0;
22039df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EDX = 0x8001bf;
22049df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         break;
22059df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   }
22069df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj}
22079df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj
22089df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj/* CALLED FROM GENERATED CODE */
22099df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj/* DIRTY HELPER (modifies guest state) */
22106c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw/* Claim to be a Athlon "Classic" (Model 2, K75 "Pluto/Orion") */
22116c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw/* But without 3DNow support (weird, but we really don't support it). */
22126c65c12ecf69436421ebc1b5637ee13bb4aaf41emjwvoid x86g_dirtyhelper_CPUID_mmxext ( VexGuestX86State* st )
22136c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw{
22146c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw   switch (st->guest_EAX) {
22156c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw      /* vendor ID */
22166c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw      case 0:
22176c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw         st->guest_EAX = 0x1;
22186c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw         st->guest_EBX = 0x68747541;
22196c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw         st->guest_ECX = 0x444d4163;
22206c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw         st->guest_EDX = 0x69746e65;
22216c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw         break;
22226c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw      /* feature bits */
22236c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw      case 1:
22246c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw         st->guest_EAX = 0x621;
22256c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw         st->guest_EBX = 0x0;
22266c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw         st->guest_ECX = 0x0;
22276c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw         st->guest_EDX = 0x183f9ff;
22286c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw         break;
22296c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw      /* Highest Extended Function Supported (0x80000004 brand string) */
22306c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw      case 0x80000000:
22316c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw         st->guest_EAX = 0x80000004;
22326c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw         st->guest_EBX = 0x68747541;
22336c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw         st->guest_ECX = 0x444d4163;
22346c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw         st->guest_EDX = 0x69746e65;
22356c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw         break;
22366c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw      /* Extended Processor Info and Feature Bits */
22376c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw      case 0x80000001:
22386c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw         st->guest_EAX = 0x721;
22396c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw         st->guest_EBX = 0x0;
22406c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw         st->guest_ECX = 0x0;
22416c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw         st->guest_EDX = 0x1c3f9ff; /* Note no 3DNow. */
22426c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw         break;
22436c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw      /* Processor Brand String "AMD Athlon(tm) Processor" */
22446c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw      case 0x80000002:
22456c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw         st->guest_EAX = 0x20444d41;
22466c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw         st->guest_EBX = 0x6c687441;
22476c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw         st->guest_ECX = 0x74286e6f;
22486c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw         st->guest_EDX = 0x5020296d;
22496c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw         break;
22506c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw      case 0x80000003:
22516c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw         st->guest_EAX = 0x65636f72;
22526c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw         st->guest_EBX = 0x726f7373;
22536c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw         st->guest_ECX = 0x0;
22546c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw         st->guest_EDX = 0x0;
22556c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw         break;
22566c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw      default:
22576c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw         st->guest_EAX = 0x0;
22586c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw         st->guest_EBX = 0x0;
22596c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw         st->guest_ECX = 0x0;
22606c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw         st->guest_EDX = 0x0;
22616c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw         break;
22626c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw   }
22636c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw}
22646c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw
22656c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw/* CALLED FROM GENERATED CODE */
22666c65c12ecf69436421ebc1b5637ee13bb4aaf41emjw/* DIRTY HELPER (modifies guest state) */
22679df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj/* Claim to be the following SSE1-capable CPU:
22689df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   vendor_id       : GenuineIntel
22699df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   cpu family      : 6
22709df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   model           : 11
22719df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   model name      : Intel(R) Pentium(R) III CPU family      1133MHz
22729df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   stepping        : 1
22739df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   cpu MHz         : 1131.013
22749df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   cache size      : 512 KB
22759df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj*/
22769df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardjvoid x86g_dirtyhelper_CPUID_sse1 ( VexGuestX86State* st )
22779df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj{
22789df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   switch (st->guest_EAX) {
22799df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj      case 0:
22809df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EAX = 0x00000002;
22819df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EBX = 0x756e6547;
22829df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_ECX = 0x6c65746e;
22839df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EDX = 0x49656e69;
22849df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         break;
22859df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj      case 1:
22869df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EAX = 0x000006b1;
22879df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EBX = 0x00000004;
22889df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_ECX = 0x00000000;
22899df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EDX = 0x0383fbff;
22909df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         break;
22919df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj      default:
22929df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EAX = 0x03020101;
22939df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EBX = 0x00000000;
22949df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_ECX = 0x00000000;
22959df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         st->guest_EDX = 0x0c040883;
22969df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         break;
22979df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   }
22989df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj}
22999df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj
2300150c9cddb753ad4dc38f43484144523174d38b02sewardj/* Claim to be the following SSSE3-capable CPU (2 x ...):
23019df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   vendor_id       : GenuineIntel
2302150c9cddb753ad4dc38f43484144523174d38b02sewardj   cpu family      : 6
2303150c9cddb753ad4dc38f43484144523174d38b02sewardj   model           : 15
2304150c9cddb753ad4dc38f43484144523174d38b02sewardj   model name      : Intel(R) Core(TM)2 CPU 6600 @ 2.40GHz
2305150c9cddb753ad4dc38f43484144523174d38b02sewardj   stepping        : 6
2306150c9cddb753ad4dc38f43484144523174d38b02sewardj   cpu MHz         : 2394.000
2307150c9cddb753ad4dc38f43484144523174d38b02sewardj   cache size      : 4096 KB
2308150c9cddb753ad4dc38f43484144523174d38b02sewardj   physical id     : 0
2309150c9cddb753ad4dc38f43484144523174d38b02sewardj   siblings        : 2
2310150c9cddb753ad4dc38f43484144523174d38b02sewardj   core id         : 0
2311150c9cddb753ad4dc38f43484144523174d38b02sewardj   cpu cores       : 2
2312150c9cddb753ad4dc38f43484144523174d38b02sewardj   fpu             : yes
2313150c9cddb753ad4dc38f43484144523174d38b02sewardj   fpu_exception   : yes
2314150c9cddb753ad4dc38f43484144523174d38b02sewardj   cpuid level     : 10
2315150c9cddb753ad4dc38f43484144523174d38b02sewardj   wp              : yes
2316150c9cddb753ad4dc38f43484144523174d38b02sewardj   flags           : fpu vme de pse tsc msr pae mce cx8 apic sep
2317150c9cddb753ad4dc38f43484144523174d38b02sewardj                     mtrr pge mca cmov pat pse36 clflush dts acpi
2318150c9cddb753ad4dc38f43484144523174d38b02sewardj                     mmx fxsr sse sse2 ss ht tm syscall nx lm
2319150c9cddb753ad4dc38f43484144523174d38b02sewardj                     constant_tsc pni monitor ds_cpl vmx est tm2
2320150c9cddb753ad4dc38f43484144523174d38b02sewardj                     cx16 xtpr lahf_lm
2321150c9cddb753ad4dc38f43484144523174d38b02sewardj   bogomips        : 4798.78
2322150c9cddb753ad4dc38f43484144523174d38b02sewardj   clflush size    : 64
2323150c9cddb753ad4dc38f43484144523174d38b02sewardj   cache_alignment : 64
2324150c9cddb753ad4dc38f43484144523174d38b02sewardj   address sizes   : 36 bits physical, 48 bits virtual
2325150c9cddb753ad4dc38f43484144523174d38b02sewardj   power management:
23269df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj*/
23279df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardjvoid x86g_dirtyhelper_CPUID_sse2 ( VexGuestX86State* st )
23289df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj{
2329150c9cddb753ad4dc38f43484144523174d38b02sewardj#  define SET_ABCD(_a,_b,_c,_d)               \
2330150c9cddb753ad4dc38f43484144523174d38b02sewardj      do { st->guest_EAX = (UInt)(_a);        \
2331150c9cddb753ad4dc38f43484144523174d38b02sewardj           st->guest_EBX = (UInt)(_b);        \
2332150c9cddb753ad4dc38f43484144523174d38b02sewardj           st->guest_ECX = (UInt)(_c);        \
2333150c9cddb753ad4dc38f43484144523174d38b02sewardj           st->guest_EDX = (UInt)(_d);        \
2334150c9cddb753ad4dc38f43484144523174d38b02sewardj      } while (0)
2335150c9cddb753ad4dc38f43484144523174d38b02sewardj
23369df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj   switch (st->guest_EAX) {
2337150c9cddb753ad4dc38f43484144523174d38b02sewardj      case 0x00000000:
2338150c9cddb753ad4dc38f43484144523174d38b02sewardj         SET_ABCD(0x0000000a, 0x756e6547, 0x6c65746e, 0x49656e69);
23399df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         break;
2340150c9cddb753ad4dc38f43484144523174d38b02sewardj      case 0x00000001:
2341150c9cddb753ad4dc38f43484144523174d38b02sewardj         SET_ABCD(0x000006f6, 0x00020800, 0x0000e3bd, 0xbfebfbff);
23429df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj         break;
2343150c9cddb753ad4dc38f43484144523174d38b02sewardj      case 0x00000002:
2344150c9cddb753ad4dc38f43484144523174d38b02sewardj         SET_ABCD(0x05b0b101, 0x005657f0, 0x00000000, 0x2cb43049);
2345150c9cddb753ad4dc38f43484144523174d38b02sewardj         break;
2346150c9cddb753ad4dc38f43484144523174d38b02sewardj      case 0x00000003:
2347150c9cddb753ad4dc38f43484144523174d38b02sewardj         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2348150c9cddb753ad4dc38f43484144523174d38b02sewardj         break;
234932bfd3e057bf3e0b215b1d234398b4d7791eba9asewardj      case 0x00000004: {
235032bfd3e057bf3e0b215b1d234398b4d7791eba9asewardj         switch (st->guest_ECX) {
235132bfd3e057bf3e0b215b1d234398b4d7791eba9asewardj            case 0x00000000: SET_ABCD(0x04000121, 0x01c0003f,
235232bfd3e057bf3e0b215b1d234398b4d7791eba9asewardj                                      0x0000003f, 0x00000001); break;
235332bfd3e057bf3e0b215b1d234398b4d7791eba9asewardj            case 0x00000001: SET_ABCD(0x04000122, 0x01c0003f,
235432bfd3e057bf3e0b215b1d234398b4d7791eba9asewardj                                      0x0000003f, 0x00000001); break;
235532bfd3e057bf3e0b215b1d234398b4d7791eba9asewardj            case 0x00000002: SET_ABCD(0x04004143, 0x03c0003f,
235632bfd3e057bf3e0b215b1d234398b4d7791eba9asewardj                                      0x00000fff, 0x00000001); break;
235732bfd3e057bf3e0b215b1d234398b4d7791eba9asewardj            default:         SET_ABCD(0x00000000, 0x00000000,
235832bfd3e057bf3e0b215b1d234398b4d7791eba9asewardj                                      0x00000000, 0x00000000); break;
235932bfd3e057bf3e0b215b1d234398b4d7791eba9asewardj         }
2360150c9cddb753ad4dc38f43484144523174d38b02sewardj         break;
236132bfd3e057bf3e0b215b1d234398b4d7791eba9asewardj      }
2362150c9cddb753ad4dc38f43484144523174d38b02sewardj      case 0x00000005:
2363150c9cddb753ad4dc38f43484144523174d38b02sewardj         SET_ABCD(0x00000040, 0x00000040, 0x00000003, 0x00000020);
2364150c9cddb753ad4dc38f43484144523174d38b02sewardj         break;
2365150c9cddb753ad4dc38f43484144523174d38b02sewardj      case 0x00000006:
2366150c9cddb753ad4dc38f43484144523174d38b02sewardj         SET_ABCD(0x00000001, 0x00000002, 0x00000001, 0x00000000);
2367150c9cddb753ad4dc38f43484144523174d38b02sewardj         break;
2368150c9cddb753ad4dc38f43484144523174d38b02sewardj      case 0x00000007:
2369150c9cddb753ad4dc38f43484144523174d38b02sewardj         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2370150c9cddb753ad4dc38f43484144523174d38b02sewardj         break;
2371150c9cddb753ad4dc38f43484144523174d38b02sewardj      case 0x00000008:
2372150c9cddb753ad4dc38f43484144523174d38b02sewardj         SET_ABCD(0x00000400, 0x00000000, 0x00000000, 0x00000000);
2373150c9cddb753ad4dc38f43484144523174d38b02sewardj         break;
2374150c9cddb753ad4dc38f43484144523174d38b02sewardj      case 0x00000009:
2375150c9cddb753ad4dc38f43484144523174d38b02sewardj         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2376150c9cddb753ad4dc38f43484144523174d38b02sewardj         break;
2377150c9cddb753ad4dc38f43484144523174d38b02sewardj      case 0x0000000a:
237832bfd3e057bf3e0b215b1d234398b4d7791eba9asewardj      unhandled_eax_value:
2379150c9cddb753ad4dc38f43484144523174d38b02sewardj         SET_ABCD(0x07280202, 0x00000000, 0x00000000, 0x00000000);
2380150c9cddb753ad4dc38f43484144523174d38b02sewardj         break;
2381150c9cddb753ad4dc38f43484144523174d38b02sewardj      case 0x80000000:
2382150c9cddb753ad4dc38f43484144523174d38b02sewardj         SET_ABCD(0x80000008, 0x00000000, 0x00000000, 0x00000000);
2383150c9cddb753ad4dc38f43484144523174d38b02sewardj         break;
2384150c9cddb753ad4dc38f43484144523174d38b02sewardj      case 0x80000001:
2385150c9cddb753ad4dc38f43484144523174d38b02sewardj         SET_ABCD(0x00000000, 0x00000000, 0x00000001, 0x20100000);
2386150c9cddb753ad4dc38f43484144523174d38b02sewardj         break;
2387150c9cddb753ad4dc38f43484144523174d38b02sewardj      case 0x80000002:
2388150c9cddb753ad4dc38f43484144523174d38b02sewardj         SET_ABCD(0x65746e49, 0x2952286c, 0x726f4320, 0x4d542865);
2389150c9cddb753ad4dc38f43484144523174d38b02sewardj         break;
2390150c9cddb753ad4dc38f43484144523174d38b02sewardj      case 0x80000003:
2391150c9cddb753ad4dc38f43484144523174d38b02sewardj         SET_ABCD(0x43203229, 0x20205550, 0x20202020, 0x20202020);
2392150c9cddb753ad4dc38f43484144523174d38b02sewardj         break;
2393150c9cddb753ad4dc38f43484144523174d38b02sewardj      case 0x80000004:
2394150c9cddb753ad4dc38f43484144523174d38b02sewardj         SET_ABCD(0x30303636, 0x20402020, 0x30342e32, 0x007a4847);
2395150c9cddb753ad4dc38f43484144523174d38b02sewardj         break;
2396150c9cddb753ad4dc38f43484144523174d38b02sewardj      case 0x80000005:
2397150c9cddb753ad4dc38f43484144523174d38b02sewardj         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2398150c9cddb753ad4dc38f43484144523174d38b02sewardj         break;
2399150c9cddb753ad4dc38f43484144523174d38b02sewardj      case 0x80000006:
2400150c9cddb753ad4dc38f43484144523174d38b02sewardj         SET_ABCD(0x00000000, 0x00000000, 0x10008040, 0x00000000);
2401150c9cddb753ad4dc38f43484144523174d38b02sewardj         break;
2402150c9cddb753ad4dc38f43484144523174d38b02sewardj      case 0x80000007:
2403150c9cddb753ad4dc38f43484144523174d38b02sewardj         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2404150c9cddb753ad4dc38f43484144523174d38b02sewardj         break;
2405150c9cddb753ad4dc38f43484144523174d38b02sewardj      case 0x80000008:
2406150c9cddb753ad4dc38f43484144523174d38b02sewardj         SET_ABCD(0x00003024, 0x00000000, 0x00000000, 0x00000000);
2407150c9cddb753ad4dc38f43484144523174d38b02sewardj         break;
240832bfd3e057bf3e0b215b1d234398b4d7791eba9asewardj      default:
240932bfd3e057bf3e0b215b1d234398b4d7791eba9asewardj         goto unhandled_eax_value;
24107cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardj   }
2411150c9cddb753ad4dc38f43484144523174d38b02sewardj#  undef SET_ABCD
24127cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardj}
24137cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardj
2414464efa446b2db97115d3e5f04af5db3464cc0e93sewardj
2415d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj/* CALLED FROM GENERATED CODE */
2416d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj/* DIRTY HELPER (non-referentially-transparent) */
2417d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj/* Horrible hack.  On non-x86 platforms, return 0. */
2418d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardjUInt x86g_dirtyhelper_IN ( UInt portno, UInt sz/*1,2 or 4*/ )
2419d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj{
2420d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj#  if defined(__i386__)
2421d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj   UInt r = 0;
2422d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj   portno &= 0xFFFF;
2423d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj   switch (sz) {
2424d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj      case 4:
2425d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj         __asm__ __volatile__("movl $0,%%eax; inl %w1,%0"
2426d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj                              : "=a" (r) : "Nd" (portno));
2427d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj	 break;
2428d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj      case 2:
2429d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj         __asm__ __volatile__("movl $0,%%eax; inw %w1,%w0"
2430d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj                              : "=a" (r) : "Nd" (portno));
2431d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj	 break;
2432d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj      case 1:
2433d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj         __asm__ __volatile__("movl $0,%%eax; inb %w1,%b0"
2434d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj                              : "=a" (r) : "Nd" (portno));
2435d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj	 break;
2436d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj      default:
2437d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj         break;
2438d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj   }
2439d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj   return r;
2440d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj#  else
2441d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj   return 0;
2442d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj#  endif
2443d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj}
2444d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj
2445d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj
2446d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj/* CALLED FROM GENERATED CODE */
2447d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj/* DIRTY HELPER (non-referentially-transparent) */
2448d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj/* Horrible hack.  On non-x86 platforms, do nothing. */
2449d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardjvoid x86g_dirtyhelper_OUT ( UInt portno, UInt data, UInt sz/*1,2 or 4*/ )
2450d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj{
2451d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj#  if defined(__i386__)
2452d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj   portno &= 0xFFFF;
2453d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj   switch (sz) {
2454d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj      case 4:
2455d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj         __asm__ __volatile__("outl %0, %w1"
2456d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj                              : : "a" (data), "Nd" (portno));
2457d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj	 break;
2458d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj      case 2:
2459d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj         __asm__ __volatile__("outw %w0, %w1"
2460d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj                              : : "a" (data), "Nd" (portno));
2461d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj	 break;
2462d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj      case 1:
2463d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj         __asm__ __volatile__("outb %b0, %w1"
2464d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj                              : : "a" (data), "Nd" (portno));
2465d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj	 break;
2466d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj      default:
2467d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj         break;
2468d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj   }
2469d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj#  else
24705e55f492bb4e0d6cca529a31653d8682fbc5a6dasewardj   /* do nothing */
2471d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj#  endif
2472d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj}
2473d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj
2474b9dc2430577bddf8c42e3d3fbe887c32cada9130sewardj/* CALLED FROM GENERATED CODE */
2475b9dc2430577bddf8c42e3d3fbe887c32cada9130sewardj/* DIRTY HELPER (non-referentially-transparent) */
2476b9dc2430577bddf8c42e3d3fbe887c32cada9130sewardj/* Horrible hack.  On non-x86 platforms, do nothing. */
2477b9dc2430577bddf8c42e3d3fbe887c32cada9130sewardj/* op = 0: call the native SGDT instruction.
2478b9dc2430577bddf8c42e3d3fbe887c32cada9130sewardj   op = 1: call the native SIDT instruction.
2479b9dc2430577bddf8c42e3d3fbe887c32cada9130sewardj*/
2480b9dc2430577bddf8c42e3d3fbe887c32cada9130sewardjvoid x86g_dirtyhelper_SxDT ( void *address, UInt op ) {
2481b9dc2430577bddf8c42e3d3fbe887c32cada9130sewardj#  if defined(__i386__)
2482b9dc2430577bddf8c42e3d3fbe887c32cada9130sewardj   switch (op) {
2483b9dc2430577bddf8c42e3d3fbe887c32cada9130sewardj      case 0:
2484b9dc2430577bddf8c42e3d3fbe887c32cada9130sewardj         __asm__ __volatile__("sgdt (%0)" : : "r" (address) : "memory");
2485b9dc2430577bddf8c42e3d3fbe887c32cada9130sewardj         break;
2486b9dc2430577bddf8c42e3d3fbe887c32cada9130sewardj      case 1:
2487b9dc2430577bddf8c42e3d3fbe887c32cada9130sewardj         __asm__ __volatile__("sidt (%0)" : : "r" (address) : "memory");
2488b9dc2430577bddf8c42e3d3fbe887c32cada9130sewardj         break;
2489b9dc2430577bddf8c42e3d3fbe887c32cada9130sewardj      default:
2490b9dc2430577bddf8c42e3d3fbe887c32cada9130sewardj         vpanic("x86g_dirtyhelper_SxDT");
2491b9dc2430577bddf8c42e3d3fbe887c32cada9130sewardj   }
2492b9dc2430577bddf8c42e3d3fbe887c32cada9130sewardj#  else
2493b9dc2430577bddf8c42e3d3fbe887c32cada9130sewardj   /* do nothing */
2494b9dc2430577bddf8c42e3d3fbe887c32cada9130sewardj   UChar* p = (UChar*)address;
2495b9dc2430577bddf8c42e3d3fbe887c32cada9130sewardj   p[0] = p[1] = p[2] = p[3] = p[4] = p[5] = 0;
2496b9dc2430577bddf8c42e3d3fbe887c32cada9130sewardj#  endif
2497b9dc2430577bddf8c42e3d3fbe887c32cada9130sewardj}
2498d14c5702cd2a0b15a66119ec1a6d68e4840a0dd5sewardj
2499893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/*---------------------------------------------------------------*/
2500893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/*--- Helpers for MMX/SSE/SSE2.                               ---*/
2501893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/*---------------------------------------------------------------*/
2502464efa446b2db97115d3e5f04af5db3464cc0e93sewardj
250338a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UChar abdU8 ( UChar xx, UChar yy ) {
2504a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   return toUChar(xx>yy ? xx-yy : yy-xx);
250538a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj}
2506464efa446b2db97115d3e5f04af5db3464cc0e93sewardj
250738a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline ULong mk32x2 ( UInt w1, UInt w0 ) {
2508464efa446b2db97115d3e5f04af5db3464cc0e93sewardj   return (((ULong)w1) << 32) | ((ULong)w0);
2509464efa446b2db97115d3e5f04af5db3464cc0e93sewardj}
2510464efa446b2db97115d3e5f04af5db3464cc0e93sewardj
251138a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UShort sel16x4_3 ( ULong w64 ) {
2512a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   UInt hi32 = toUInt(w64 >> 32);
2513a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   return toUShort(hi32 >> 16);
2514464efa446b2db97115d3e5f04af5db3464cc0e93sewardj}
251538a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UShort sel16x4_2 ( ULong w64 ) {
2516a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   UInt hi32 = toUInt(w64 >> 32);
2517a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   return toUShort(hi32);
2518464efa446b2db97115d3e5f04af5db3464cc0e93sewardj}
251938a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UShort sel16x4_1 ( ULong w64 ) {
2520a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   UInt lo32 = toUInt(w64);
2521a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   return toUShort(lo32 >> 16);
2522464efa446b2db97115d3e5f04af5db3464cc0e93sewardj}
252338a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UShort sel16x4_0 ( ULong w64 ) {
2524a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   UInt lo32 = toUInt(w64);
2525a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   return toUShort(lo32);
2526464efa446b2db97115d3e5f04af5db3464cc0e93sewardj}
2527464efa446b2db97115d3e5f04af5db3464cc0e93sewardj
252838a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UChar sel8x8_7 ( ULong w64 ) {
2529a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   UInt hi32 = toUInt(w64 >> 32);
2530a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   return toUChar(hi32 >> 24);
2531464efa446b2db97115d3e5f04af5db3464cc0e93sewardj}
253238a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UChar sel8x8_6 ( ULong w64 ) {
2533a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   UInt hi32 = toUInt(w64 >> 32);
2534a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   return toUChar(hi32 >> 16);
2535464efa446b2db97115d3e5f04af5db3464cc0e93sewardj}
253638a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UChar sel8x8_5 ( ULong w64 ) {
2537a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   UInt hi32 = toUInt(w64 >> 32);
2538a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   return toUChar(hi32 >> 8);
2539464efa446b2db97115d3e5f04af5db3464cc0e93sewardj}
254038a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UChar sel8x8_4 ( ULong w64 ) {
2541a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   UInt hi32 = toUInt(w64 >> 32);
2542a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   return toUChar(hi32 >> 0);
2543464efa446b2db97115d3e5f04af5db3464cc0e93sewardj}
254438a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UChar sel8x8_3 ( ULong w64 ) {
2545a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   UInt lo32 = toUInt(w64);
2546a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   return toUChar(lo32 >> 24);
2547464efa446b2db97115d3e5f04af5db3464cc0e93sewardj}
254838a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UChar sel8x8_2 ( ULong w64 ) {
2549a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   UInt lo32 = toUInt(w64);
2550a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   return toUChar(lo32 >> 16);
2551464efa446b2db97115d3e5f04af5db3464cc0e93sewardj}
255238a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UChar sel8x8_1 ( ULong w64 ) {
2553a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   UInt lo32 = toUInt(w64);
2554a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   return toUChar(lo32 >> 8);
2555464efa446b2db97115d3e5f04af5db3464cc0e93sewardj}
255638a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UChar sel8x8_0 ( ULong w64 ) {
2557a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   UInt lo32 = toUInt(w64);
2558a4b4be4e6d9bfaf4149b99b59069b61651915102sewardj   return toUChar(lo32 >> 0);
2559464efa446b2db97115d3e5f04af5db3464cc0e93sewardj}
2560464efa446b2db97115d3e5f04af5db3464cc0e93sewardj
256138a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
256238a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjULong x86g_calculate_mmx_pmaddwd ( ULong xx, ULong yy )
25634340dac5c2cede4962868e6da5b73282da2bc465sewardj{
25644340dac5c2cede4962868e6da5b73282da2bc465sewardj   return
25654340dac5c2cede4962868e6da5b73282da2bc465sewardj      mk32x2(
25664340dac5c2cede4962868e6da5b73282da2bc465sewardj         (((Int)(Short)sel16x4_3(xx)) * ((Int)(Short)sel16x4_3(yy)))
25674340dac5c2cede4962868e6da5b73282da2bc465sewardj            + (((Int)(Short)sel16x4_2(xx)) * ((Int)(Short)sel16x4_2(yy))),
25684340dac5c2cede4962868e6da5b73282da2bc465sewardj         (((Int)(Short)sel16x4_1(xx)) * ((Int)(Short)sel16x4_1(yy)))
25694340dac5c2cede4962868e6da5b73282da2bc465sewardj            + (((Int)(Short)sel16x4_0(xx)) * ((Int)(Short)sel16x4_0(yy)))
25704340dac5c2cede4962868e6da5b73282da2bc465sewardj      );
25714340dac5c2cede4962868e6da5b73282da2bc465sewardj}
25724340dac5c2cede4962868e6da5b73282da2bc465sewardj
257338a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
257438a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjULong x86g_calculate_mmx_psadbw ( ULong xx, ULong yy )
25750bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj{
25760bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj   UInt t = 0;
25770bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj   t += (UInt)abdU8( sel8x8_7(xx), sel8x8_7(yy) );
25780bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj   t += (UInt)abdU8( sel8x8_6(xx), sel8x8_6(yy) );
25790bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj   t += (UInt)abdU8( sel8x8_5(xx), sel8x8_5(yy) );
25800bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj   t += (UInt)abdU8( sel8x8_4(xx), sel8x8_4(yy) );
25810bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj   t += (UInt)abdU8( sel8x8_3(xx), sel8x8_3(yy) );
25820bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj   t += (UInt)abdU8( sel8x8_2(xx), sel8x8_2(yy) );
25830bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj   t += (UInt)abdU8( sel8x8_1(xx), sel8x8_1(yy) );
25840bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj   t += (UInt)abdU8( sel8x8_0(xx), sel8x8_0(yy) );
25850bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj   t &= 0xFFFF;
25860bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj   return (ULong)t;
25870bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj}
25880bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj
2589464efa446b2db97115d3e5f04af5db3464cc0e93sewardj
2590893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/*---------------------------------------------------------------*/
2591893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/*--- Helpers for dealing with segment overrides.             ---*/
2592893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/*---------------------------------------------------------------*/
25933bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
25943bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardjstatic inline
25953bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardjUInt get_segdescr_base ( VexGuestX86SegDescr* ent )
25963bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj{
25973bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   UInt lo  = 0xFFFF & (UInt)ent->LdtEnt.Bits.BaseLow;
25983bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   UInt mid =   0xFF & (UInt)ent->LdtEnt.Bits.BaseMid;
25993bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   UInt hi  =   0xFF & (UInt)ent->LdtEnt.Bits.BaseHi;
26003bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   return (hi << 24) | (mid << 16) | lo;
26013bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj}
26023bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
26033bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardjstatic inline
26043bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardjUInt get_segdescr_limit ( VexGuestX86SegDescr* ent )
26053bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj{
26063bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj    UInt lo    = 0xFFFF & (UInt)ent->LdtEnt.Bits.LimitLow;
26073bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj    UInt hi    =    0xF & (UInt)ent->LdtEnt.Bits.LimitHi;
26083bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj    UInt limit = (hi << 16) | lo;
26093bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj    if (ent->LdtEnt.Bits.Granularity)
26103bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj       limit = (limit << 12) | 0xFFF;
26113bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj    return limit;
26123bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj}
26133bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
261438a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
26153bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardjULong x86g_use_seg_selector ( HWord ldt, HWord gdt,
26163bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj                              UInt seg_selector, UInt virtual_addr )
26173bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj{
26183bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   UInt tiBit, base, limit;
26193bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   VexGuestX86SegDescr* the_descrs;
26203bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
26213bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   Bool verboze = False;
26223bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
26233bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   /* If this isn't true, we're in Big Trouble. */
26243bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   vassert(8 == sizeof(VexGuestX86SegDescr));
26253bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
26263bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   if (verboze)
26273bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      vex_printf("x86h_use_seg_selector: "
26283bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj                 "seg_selector = 0x%x, vaddr = 0x%x\n",
26293bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj                 seg_selector, virtual_addr);
26303bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
26313bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   /* Check for wildly invalid selector. */
26323bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   if (seg_selector & ~0xFFFF)
26333bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      goto bad;
26343bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
26353bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   seg_selector &= 0x0000FFFF;
26363bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
26373bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   /* Sanity check the segment selector.  Ensure that RPL=11b (least
26383bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      privilege).  This forms the bottom 2 bits of the selector. */
26393bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   if ((seg_selector & 3) != 3)
26403bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      goto bad;
26413bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
26423bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   /* Extract the TI bit (0 means GDT, 1 means LDT) */
26433bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   tiBit = (seg_selector >> 2) & 1;
26443bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
26453bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   /* Convert the segment selector onto a table index */
26463bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   seg_selector >>= 3;
26473bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   vassert(seg_selector >= 0 && seg_selector < 8192);
26483bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
26493bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   if (tiBit == 0) {
26503bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
26513bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      /* GDT access. */
26523bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      /* Do we actually have a GDT to look at? */
26533bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      if (gdt == 0)
26543bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj         goto bad;
26553bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
26563bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      /* Check for access to non-existent entry. */
26573bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      if (seg_selector >= VEX_GUEST_X86_GDT_NENT)
26583bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj         goto bad;
26593bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
26603bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      the_descrs = (VexGuestX86SegDescr*)gdt;
26613bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      base  = get_segdescr_base (&the_descrs[seg_selector]);
26623bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      limit = get_segdescr_limit(&the_descrs[seg_selector]);
26633bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
26643bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   } else {
26653bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
26663bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      /* All the same stuff, except for the LDT. */
26673bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      if (ldt == 0)
26683bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj         goto bad;
26693bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
26703bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      if (seg_selector >= VEX_GUEST_X86_LDT_NENT)
26713bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj         goto bad;
26723bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
26733bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      the_descrs = (VexGuestX86SegDescr*)ldt;
26743bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      base  = get_segdescr_base (&the_descrs[seg_selector]);
26753bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      limit = get_segdescr_limit(&the_descrs[seg_selector]);
26763bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
26773bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   }
26783bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
26793bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   /* Do the limit check.  Note, this check is just slightly too
26803bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      slack.  Really it should be "if (virtual_addr + size - 1 >=
26813bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      limit)," but we don't have the size info to hand.  Getting it
26823bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      could be significantly complex.  */
26833bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   if (virtual_addr >= limit)
26843bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      goto bad;
26853bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
26863bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   if (verboze)
26873bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj      vex_printf("x86h_use_seg_selector: "
26883bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj                 "base = 0x%x, addr = 0x%x\n",
26893bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj                 base, base + virtual_addr);
26903bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
26913bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   /* High 32 bits are zero, indicating success. */
26923bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   return (ULong)( ((UInt)virtual_addr) + base );
26933bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
26943bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj bad:
26953bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj   return 1ULL << 32;
26963bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj}
26973bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
26983bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
2699893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/*---------------------------------------------------------------*/
2700893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/*--- Helpers for dealing with, and describing,               ---*/
2701893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/*--- guest state as a whole.                                 ---*/
2702893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/*---------------------------------------------------------------*/
2703893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
2704893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/* Initialise the entire x86 guest state. */
2705893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj/* VISIBLE TO LIBVEX CLIENT */
2706893a3302cc943e2ad1db421a8e6a753f82f532a7sewardjvoid LibVEX_GuestX86_initialise ( /*OUT*/VexGuestX86State* vex_state )
2707893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj{
2708c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   vex_state->host_EvC_FAILADDR = 0;
2709c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   vex_state->host_EvC_COUNTER = 0;
2710c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj
2711893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_state->guest_EAX = 0;
2712893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_state->guest_ECX = 0;
2713893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_state->guest_EDX = 0;
2714893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_state->guest_EBX = 0;
2715893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_state->guest_ESP = 0;
2716893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_state->guest_EBP = 0;
2717893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_state->guest_ESI = 0;
2718893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_state->guest_EDI = 0;
2719893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
2720893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_state->guest_CC_OP   = X86G_CC_OP_COPY;
2721893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_state->guest_CC_DEP1 = 0;
2722893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_state->guest_CC_DEP2 = 0;
2723893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_state->guest_CC_NDEP = 0;
2724893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_state->guest_DFLAG   = 1; /* forwards */
2725893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_state->guest_IDFLAG  = 0;
27266d26984a0df6a7d20b658bac6edf869eb872cca3sewardj   vex_state->guest_ACFLAG  = 0;
2727893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
2728893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_state->guest_EIP = 0;
2729893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
2730893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   /* Initialise the simulated FPU */
2731893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   x86g_dirtyhelper_FINIT( vex_state );
2732893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
2733893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   /* Initialse the SSE state. */
2734893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj#  define SSEZERO(_xmm) _xmm[0]=_xmm[1]=_xmm[2]=_xmm[3] = 0;
2735893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
2736893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_state->guest_SSEROUND = (UInt)Irrm_NEAREST;
2737893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   SSEZERO(vex_state->guest_XMM0);
2738893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   SSEZERO(vex_state->guest_XMM1);
2739893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   SSEZERO(vex_state->guest_XMM2);
2740893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   SSEZERO(vex_state->guest_XMM3);
2741893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   SSEZERO(vex_state->guest_XMM4);
2742893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   SSEZERO(vex_state->guest_XMM5);
2743893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   SSEZERO(vex_state->guest_XMM6);
2744893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   SSEZERO(vex_state->guest_XMM7);
2745893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
2746893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj#  undef SSEZERO
2747893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
2748893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_state->guest_CS  = 0;
2749893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_state->guest_DS  = 0;
2750893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_state->guest_ES  = 0;
2751893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_state->guest_FS  = 0;
2752893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_state->guest_GS  = 0;
2753893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_state->guest_SS  = 0;
2754893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_state->guest_LDT = 0;
2755893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj   vex_state->guest_GDT = 0;
2756893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
27576ef84bed9bb3af22060eb1759788034602bbcc88florian   vex_state->guest_EMNOTE = EmNote_NONE;
27581f126c5c092801acfc1ac968d2f1a37dde334bccsewardj
2759bfceb089644ce9eee882bae5cec5902be4831cacsewardj   /* SSE2 has a 'clflush' cache-line-invalidator which uses these. */
276005f5e0172384dd2983fb16fbb7deebd74d71cd35sewardj   vex_state->guest_CMSTART = 0;
276105f5e0172384dd2983fb16fbb7deebd74d71cd35sewardj   vex_state->guest_CMLEN   = 0;
2762ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj
2763d660d41d4174e44f284bad3264601662ed68d4a1sewardj   vex_state->guest_NRADDR   = 0;
2764d660d41d4174e44f284bad3264601662ed68d4a1sewardj   vex_state->guest_SC_CLASS = 0;
2765e86310f555a233cc2ca02e1a5d0adb555f12bdcdsewardj   vex_state->guest_IP_AT_SYSCALL = 0;
2766e86310f555a233cc2ca02e1a5d0adb555f12bdcdsewardj
276795a487bc73c0f8c9371ad500988a51c9e78ee34aflorian   vex_state->padding1 = 0;
2768893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj}
2769893a3302cc943e2ad1db421a8e6a753f82f532a7sewardj
27708d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj
27718d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj/* Figure out if any part of the guest state contained in minoff
27728d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   .. maxoff requires precise memory exceptions.  If in doubt return
27736c46befd9eb90c1b6e739926c1fa335cba75bf46philippe   True (but this generates significantly slower code).
27748d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj
27754cca75cb48776ceda40e8e305232d85f62021804sewardj   By default we enforce precise exns for guest %ESP, %EBP and %EIP
27764cca75cb48776ceda40e8e305232d85f62021804sewardj   only.  These are the minimum needed to extract correct stack
27774cca75cb48776ceda40e8e305232d85f62021804sewardj   backtraces from x86 code.
27786c46befd9eb90c1b6e739926c1fa335cba75bf46philippe
27796c46befd9eb90c1b6e739926c1fa335cba75bf46philippe   Only %ESP is needed in mode VexRegUpdSpAtMemAccess.
27808d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj*/
2781ca2c3c75784d35d136fc7c952717cdee5063c193sewardjBool guest_x86_state_requires_precise_mem_exns (
2782ca2c3c75784d35d136fc7c952717cdee5063c193sewardj        Int minoff, Int maxoff, VexRegisterUpdates pxControl
2783ca2c3c75784d35d136fc7c952717cdee5063c193sewardj     )
27848d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj{
27854cca75cb48776ceda40e8e305232d85f62021804sewardj   Int ebp_min = offsetof(VexGuestX86State, guest_EBP);
27864cca75cb48776ceda40e8e305232d85f62021804sewardj   Int ebp_max = ebp_min + 4 - 1;
27878d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   Int esp_min = offsetof(VexGuestX86State, guest_ESP);
27888d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   Int esp_max = esp_min + 4 - 1;
27898d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   Int eip_min = offsetof(VexGuestX86State, guest_EIP);
27908d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   Int eip_max = eip_min + 4 - 1;
27918d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj
27926c46befd9eb90c1b6e739926c1fa335cba75bf46philippe   if (maxoff < esp_min || minoff > esp_max) {
27936c46befd9eb90c1b6e739926c1fa335cba75bf46philippe      /* no overlap with esp */
2794ca2c3c75784d35d136fc7c952717cdee5063c193sewardj      if (pxControl == VexRegUpdSpAtMemAccess)
27956c46befd9eb90c1b6e739926c1fa335cba75bf46philippe         return False; // We only need to check stack pointer.
27964cca75cb48776ceda40e8e305232d85f62021804sewardj   } else {
27974cca75cb48776ceda40e8e305232d85f62021804sewardj      return True;
27984cca75cb48776ceda40e8e305232d85f62021804sewardj   }
27994cca75cb48776ceda40e8e305232d85f62021804sewardj
28006c46befd9eb90c1b6e739926c1fa335cba75bf46philippe   if (maxoff < ebp_min || minoff > ebp_max) {
28016c46befd9eb90c1b6e739926c1fa335cba75bf46philippe      /* no overlap with ebp */
28028d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   } else {
2803eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj      return True;
28048d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   }
28058d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj
28068d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   if (maxoff < eip_min || minoff > eip_max) {
2807eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj      /* no overlap with eip */
28088d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   } else {
2809eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj      return True;
28108d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   }
28118d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj
28128d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   return False;
28138d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj}
28148d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj
28158d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj
2816eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj#define ALWAYSDEFD(field)                           \
2817eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj    { offsetof(VexGuestX86State, field),            \
2818eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj      (sizeof ((VexGuestX86State*)0)->field) }
2819eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj
2820eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardjVexGuestLayout
282149651f4b59b1ab7e0e70cccd34001630eafbe957sewardj   x86guest_layout
2822eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj      = {
2823eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj          /* Total size of the guest state, in bytes. */
2824eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj          .total_sizeB = sizeof(VexGuestX86State),
2825eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj
2826eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj          /* Describe the stack pointer. */
2827eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj          .offset_SP = offsetof(VexGuestX86State,guest_ESP),
2828eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj          .sizeof_SP = 4,
2829eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj
2830a203330aad67bc3e52ca1395a55e94ef9a091223sewardj          /* Describe the frame pointer. */
2831a203330aad67bc3e52ca1395a55e94ef9a091223sewardj          .offset_FP = offsetof(VexGuestX86State,guest_EBP),
2832a203330aad67bc3e52ca1395a55e94ef9a091223sewardj          .sizeof_FP = 4,
2833a203330aad67bc3e52ca1395a55e94ef9a091223sewardj
2834cf7879021370aabcccb1a9347244fcc7d5680141sewardj          /* Describe the instruction pointer. */
2835cf7879021370aabcccb1a9347244fcc7d5680141sewardj          .offset_IP = offsetof(VexGuestX86State,guest_EIP),
2836cf7879021370aabcccb1a9347244fcc7d5680141sewardj          .sizeof_IP = 4,
2837eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj
2838eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj          /* Describe any sections to be regarded by Memcheck as
2839eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj             'always-defined'. */
2840e86310f555a233cc2ca02e1a5d0adb555f12bdcdsewardj          .n_alwaysDefd = 24,
28413bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj
28422a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj          /* flags thunk: OP and NDEP are always defd, whereas DEP1
28432a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj             and DEP2 have to be tracked.  See detailed comment in
28442a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj             gdefs.h on meaning of thunk fields. */
28458fc937421c954ff9f707254f028b1fa0410c473dsewardj          .alwaysDefd
28468fc937421c954ff9f707254f028b1fa0410c473dsewardj             = { /*  0 */ ALWAYSDEFD(guest_CC_OP),
28478fc937421c954ff9f707254f028b1fa0410c473dsewardj                 /*  1 */ ALWAYSDEFD(guest_CC_NDEP),
28488fc937421c954ff9f707254f028b1fa0410c473dsewardj                 /*  2 */ ALWAYSDEFD(guest_DFLAG),
28498fc937421c954ff9f707254f028b1fa0410c473dsewardj                 /*  3 */ ALWAYSDEFD(guest_IDFLAG),
28506d26984a0df6a7d20b658bac6edf869eb872cca3sewardj                 /*  4 */ ALWAYSDEFD(guest_ACFLAG),
28516d26984a0df6a7d20b658bac6edf869eb872cca3sewardj                 /*  5 */ ALWAYSDEFD(guest_EIP),
28526d26984a0df6a7d20b658bac6edf869eb872cca3sewardj                 /*  6 */ ALWAYSDEFD(guest_FTOP),
28536d26984a0df6a7d20b658bac6edf869eb872cca3sewardj                 /*  7 */ ALWAYSDEFD(guest_FPTAG),
28546d26984a0df6a7d20b658bac6edf869eb872cca3sewardj                 /*  8 */ ALWAYSDEFD(guest_FPROUND),
28556d26984a0df6a7d20b658bac6edf869eb872cca3sewardj                 /*  9 */ ALWAYSDEFD(guest_FC3210),
28566d26984a0df6a7d20b658bac6edf869eb872cca3sewardj                 /* 10 */ ALWAYSDEFD(guest_CS),
28576d26984a0df6a7d20b658bac6edf869eb872cca3sewardj                 /* 11 */ ALWAYSDEFD(guest_DS),
28586d26984a0df6a7d20b658bac6edf869eb872cca3sewardj                 /* 12 */ ALWAYSDEFD(guest_ES),
28596d26984a0df6a7d20b658bac6edf869eb872cca3sewardj                 /* 13 */ ALWAYSDEFD(guest_FS),
28606d26984a0df6a7d20b658bac6edf869eb872cca3sewardj                 /* 14 */ ALWAYSDEFD(guest_GS),
28616d26984a0df6a7d20b658bac6edf869eb872cca3sewardj                 /* 15 */ ALWAYSDEFD(guest_SS),
28626d26984a0df6a7d20b658bac6edf869eb872cca3sewardj                 /* 16 */ ALWAYSDEFD(guest_LDT),
28636d26984a0df6a7d20b658bac6edf869eb872cca3sewardj                 /* 17 */ ALWAYSDEFD(guest_GDT),
28646ef84bed9bb3af22060eb1759788034602bbcc88florian                 /* 18 */ ALWAYSDEFD(guest_EMNOTE),
28656d26984a0df6a7d20b658bac6edf869eb872cca3sewardj                 /* 19 */ ALWAYSDEFD(guest_SSEROUND),
286605f5e0172384dd2983fb16fbb7deebd74d71cd35sewardj                 /* 20 */ ALWAYSDEFD(guest_CMSTART),
286705f5e0172384dd2983fb16fbb7deebd74d71cd35sewardj                 /* 21 */ ALWAYSDEFD(guest_CMLEN),
2868e86310f555a233cc2ca02e1a5d0adb555f12bdcdsewardj                 /* 22 */ ALWAYSDEFD(guest_SC_CLASS),
2869e86310f555a233cc2ca02e1a5d0adb555f12bdcdsewardj                 /* 23 */ ALWAYSDEFD(guest_IP_AT_SYSCALL)
28708fc937421c954ff9f707254f028b1fa0410c473dsewardj               }
2871eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj        };
287249651f4b59b1ab7e0e70cccd34001630eafbe957sewardj
287349651f4b59b1ab7e0e70cccd34001630eafbe957sewardj
287436ca51378f8851635df814230fa23f2c409b9eddsewardj/*---------------------------------------------------------------*/
2875cef7d3e3df4796e35b4521158d9dc058f034aa87sewardj/*--- end                                 guest_x86_helpers.c ---*/
287636ca51378f8851635df814230fa23f2c409b9eddsewardj/*---------------------------------------------------------------*/
2877