guest_x86_helpers.c revision 006a6a2f15f48f705895a516d4883e8f8142e910
136ca51378f8851635df814230fa23f2c409b9eddsewardj
236ca51378f8851635df814230fa23f2c409b9eddsewardj/*---------------------------------------------------------------*/
336ca51378f8851635df814230fa23f2c409b9eddsewardj/*---                                                         ---*/
4c0ee2edb4563c90bc8f1a83a09984a1fda86d1d3sewardj/*--- This file (guest-x86/ghelpers.c) is                     ---*/
536ca51378f8851635df814230fa23f2c409b9eddsewardj/*--- Copyright (c) 2004 OpenWorks LLP.  All rights reserved. ---*/
636ca51378f8851635df814230fa23f2c409b9eddsewardj/*---                                                         ---*/
736ca51378f8851635df814230fa23f2c409b9eddsewardj/*---------------------------------------------------------------*/
836ca51378f8851635df814230fa23f2c409b9eddsewardj
936ca51378f8851635df814230fa23f2c409b9eddsewardj#include "libvex_basictypes.h"
100c2cb623cca372a2b42b073121c7413cdaaf75besewardj#include "libvex_guest_x86.h"
1136ca51378f8851635df814230fa23f2c409b9eddsewardj#include "libvex_ir.h"
12c0ee2edb4563c90bc8f1a83a09984a1fda86d1d3sewardj
13c0ee2edb4563c90bc8f1a83a09984a1fda86d1d3sewardj#include "main/vex_util.h"
14c0ee2edb4563c90bc8f1a83a09984a1fda86d1d3sewardj#include "guest-x86/gdefs.h"
1536ca51378f8851635df814230fa23f2c409b9eddsewardj
16c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj/* --- Forwardses --- */
179aebb0c3f7a7f43313786826f31402f2b733badfsewardj
189aebb0c3f7a7f43313786826f31402f2b733badfsewardj/* --- CLEAN HELPERS --- */
199aebb0c3f7a7f43313786826f31402f2b733badfsewardjstatic UInt  calculate_eflags_all ( UInt cc_op, UInt cc_src, UInt cc_dst );
209aebb0c3f7a7f43313786826f31402f2b733badfsewardjstatic UInt  calculate_eflags_c   ( UInt cc_op, UInt cc_src, UInt cc_dst );
219aebb0c3f7a7f43313786826f31402f2b733badfsewardjstatic UInt  calculate_condition  ( UInt/*Condcode*/ cond,
229aebb0c3f7a7f43313786826f31402f2b733badfsewardj                                    UInt cc_op, UInt cc_src, UInt cc_dst );
239aebb0c3f7a7f43313786826f31402f2b733badfsewardjstatic UInt  calculate_FXAM ( UInt tag, ULong dbl );
249aebb0c3f7a7f43313786826f31402f2b733badfsewardjstatic ULong calculate_RCR  ( UInt arg, UInt rot_amt, UInt eflags_in, UInt sz );
259aebb0c3f7a7f43313786826f31402f2b733badfsewardj
269aebb0c3f7a7f43313786826f31402f2b733badfsewardj/* --- DIRTY HELPERS --- */
277cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardjstatic ULong loadF80le  ( VexGuestX86State*, UInt );
287cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardjstatic void  storeF80le ( VexGuestX86State*, UInt, ULong );
297cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardjstatic void  dirtyhelper_CPUID ( VexGuestX86State* st );
30c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
31c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
3236ca51378f8851635df814230fa23f2c409b9eddsewardj/* This file contains helper functions for x86 guest code.
3336ca51378f8851635df814230fa23f2c409b9eddsewardj   Calls to these functions are generated by the back end.
3436ca51378f8851635df814230fa23f2c409b9eddsewardj   These calls are of course in the host machine code and
3536ca51378f8851635df814230fa23f2c409b9eddsewardj   this file will be compiled to host machine code, so that
3636ca51378f8851635df814230fa23f2c409b9eddsewardj   all makes sense.
3736ca51378f8851635df814230fa23f2c409b9eddsewardj
3836ca51378f8851635df814230fa23f2c409b9eddsewardj   x86guest_findhelper() is the only exported function.
3936ca51378f8851635df814230fa23f2c409b9eddsewardj
4036ca51378f8851635df814230fa23f2c409b9eddsewardj   Only change the signatures of these helper functions very
4136ca51378f8851635df814230fa23f2c409b9eddsewardj   carefully.  If you change the signature here, you'll have to change
4236ca51378f8851635df814230fa23f2c409b9eddsewardj   the parameters passed to it in the IR calls constructed by
4389050e58e7bee40892662fe94231aefc33768cf5sewardj   x86toIR.c.
4489050e58e7bee40892662fe94231aefc33768cf5sewardj
4589050e58e7bee40892662fe94231aefc33768cf5sewardj   Some of this code/logic is derived from QEMU, which is copyright
4689050e58e7bee40892662fe94231aefc33768cf5sewardj   Fabrice Bellard, licensed under the LGPL.  It is used with
4789050e58e7bee40892662fe94231aefc33768cf5sewardj   permission.
4836ca51378f8851635df814230fa23f2c409b9eddsewardj*/
4936ca51378f8851635df814230fa23f2c409b9eddsewardj
5084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj/* Set to 1 to get detailed profiling info about use of the flag
5184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   machinery. */
5284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#define PROFILE_EFLAGS 0
5384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
5484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
5514731f22bf7759d6d23383ca870ac89d9581f1e9sewardjtypedef UChar uint8_t;
56741153c4301023a420ab45b8a10b8e1bac968822sewardjtypedef UInt  uint32_t;
5714731f22bf7759d6d23383ca870ac89d9581f1e9sewardj
5814731f22bf7759d6d23383ca870ac89d9581f1e9sewardj
5914731f22bf7759d6d23383ca870ac89d9581f1e9sewardjstatic const uint8_t parity_table[256] = {
609aebb0c3f7a7f43313786826f31402f2b733badfsewardj    CC_MASK_P, 0, 0, CC_MASK_P, 0, CC_MASK_P, CC_MASK_P, 0,
619aebb0c3f7a7f43313786826f31402f2b733badfsewardj    0, CC_MASK_P, CC_MASK_P, 0, CC_MASK_P, 0, 0, CC_MASK_P,
629aebb0c3f7a7f43313786826f31402f2b733badfsewardj    0, CC_MASK_P, CC_MASK_P, 0, CC_MASK_P, 0, 0, CC_MASK_P,
639aebb0c3f7a7f43313786826f31402f2b733badfsewardj    CC_MASK_P, 0, 0, CC_MASK_P, 0, CC_MASK_P, CC_MASK_P, 0,
649aebb0c3f7a7f43313786826f31402f2b733badfsewardj    0, CC_MASK_P, CC_MASK_P, 0, CC_MASK_P, 0, 0, CC_MASK_P,
659aebb0c3f7a7f43313786826f31402f2b733badfsewardj    CC_MASK_P, 0, 0, CC_MASK_P, 0, CC_MASK_P, CC_MASK_P, 0,
669aebb0c3f7a7f43313786826f31402f2b733badfsewardj    CC_MASK_P, 0, 0, CC_MASK_P, 0, CC_MASK_P, CC_MASK_P, 0,
679aebb0c3f7a7f43313786826f31402f2b733badfsewardj    0, CC_MASK_P, CC_MASK_P, 0, CC_MASK_P, 0, 0, CC_MASK_P,
689aebb0c3f7a7f43313786826f31402f2b733badfsewardj    0, CC_MASK_P, CC_MASK_P, 0, CC_MASK_P, 0, 0, CC_MASK_P,
699aebb0c3f7a7f43313786826f31402f2b733badfsewardj    CC_MASK_P, 0, 0, CC_MASK_P, 0, CC_MASK_P, CC_MASK_P, 0,
709aebb0c3f7a7f43313786826f31402f2b733badfsewardj    CC_MASK_P, 0, 0, CC_MASK_P, 0, CC_MASK_P, CC_MASK_P, 0,
719aebb0c3f7a7f43313786826f31402f2b733badfsewardj    0, CC_MASK_P, CC_MASK_P, 0, CC_MASK_P, 0, 0, CC_MASK_P,
729aebb0c3f7a7f43313786826f31402f2b733badfsewardj    CC_MASK_P, 0, 0, CC_MASK_P, 0, CC_MASK_P, CC_MASK_P, 0,
739aebb0c3f7a7f43313786826f31402f2b733badfsewardj    0, CC_MASK_P, CC_MASK_P, 0, CC_MASK_P, 0, 0, CC_MASK_P,
749aebb0c3f7a7f43313786826f31402f2b733badfsewardj    0, CC_MASK_P, CC_MASK_P, 0, CC_MASK_P, 0, 0, CC_MASK_P,
759aebb0c3f7a7f43313786826f31402f2b733badfsewardj    CC_MASK_P, 0, 0, CC_MASK_P, 0, CC_MASK_P, CC_MASK_P, 0,
769aebb0c3f7a7f43313786826f31402f2b733badfsewardj    0, CC_MASK_P, CC_MASK_P, 0, CC_MASK_P, 0, 0, CC_MASK_P,
779aebb0c3f7a7f43313786826f31402f2b733badfsewardj    CC_MASK_P, 0, 0, CC_MASK_P, 0, CC_MASK_P, CC_MASK_P, 0,
789aebb0c3f7a7f43313786826f31402f2b733badfsewardj    CC_MASK_P, 0, 0, CC_MASK_P, 0, CC_MASK_P, CC_MASK_P, 0,
799aebb0c3f7a7f43313786826f31402f2b733badfsewardj    0, CC_MASK_P, CC_MASK_P, 0, CC_MASK_P, 0, 0, CC_MASK_P,
809aebb0c3f7a7f43313786826f31402f2b733badfsewardj    CC_MASK_P, 0, 0, CC_MASK_P, 0, CC_MASK_P, CC_MASK_P, 0,
819aebb0c3f7a7f43313786826f31402f2b733badfsewardj    0, CC_MASK_P, CC_MASK_P, 0, CC_MASK_P, 0, 0, CC_MASK_P,
829aebb0c3f7a7f43313786826f31402f2b733badfsewardj    0, CC_MASK_P, CC_MASK_P, 0, CC_MASK_P, 0, 0, CC_MASK_P,
839aebb0c3f7a7f43313786826f31402f2b733badfsewardj    CC_MASK_P, 0, 0, CC_MASK_P, 0, CC_MASK_P, CC_MASK_P, 0,
849aebb0c3f7a7f43313786826f31402f2b733badfsewardj    CC_MASK_P, 0, 0, CC_MASK_P, 0, CC_MASK_P, CC_MASK_P, 0,
859aebb0c3f7a7f43313786826f31402f2b733badfsewardj    0, CC_MASK_P, CC_MASK_P, 0, CC_MASK_P, 0, 0, CC_MASK_P,
869aebb0c3f7a7f43313786826f31402f2b733badfsewardj    0, CC_MASK_P, CC_MASK_P, 0, CC_MASK_P, 0, 0, CC_MASK_P,
879aebb0c3f7a7f43313786826f31402f2b733badfsewardj    CC_MASK_P, 0, 0, CC_MASK_P, 0, CC_MASK_P, CC_MASK_P, 0,
889aebb0c3f7a7f43313786826f31402f2b733badfsewardj    0, CC_MASK_P, CC_MASK_P, 0, CC_MASK_P, 0, 0, CC_MASK_P,
899aebb0c3f7a7f43313786826f31402f2b733badfsewardj    CC_MASK_P, 0, 0, CC_MASK_P, 0, CC_MASK_P, CC_MASK_P, 0,
909aebb0c3f7a7f43313786826f31402f2b733badfsewardj    CC_MASK_P, 0, 0, CC_MASK_P, 0, CC_MASK_P, CC_MASK_P, 0,
919aebb0c3f7a7f43313786826f31402f2b733badfsewardj    0, CC_MASK_P, CC_MASK_P, 0, CC_MASK_P, 0, 0, CC_MASK_P,
9214731f22bf7759d6d23383ca870ac89d9581f1e9sewardj};
9314731f22bf7759d6d23383ca870ac89d9581f1e9sewardj
9414731f22bf7759d6d23383ca870ac89d9581f1e9sewardj/* n must be a constant to be efficient */
95df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardjinline static Int lshift ( Int x, Int n )
9614731f22bf7759d6d23383ca870ac89d9581f1e9sewardj{
97df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   if (n >= 0)
98df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj      return x << n;
99df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   else
100df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj      return x >> (-n);
10114731f22bf7759d6d23383ca870ac89d9581f1e9sewardj}
10214731f22bf7759d6d23383ca870ac89d9581f1e9sewardj
10314731f22bf7759d6d23383ca870ac89d9581f1e9sewardj
104b9c5cf639b3b21b972599d27207a033afc76ef67sewardj#define PREAMBLE(__data_bits)					\
105df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   /* const */ UInt DATA_MASK 					\
106b9c5cf639b3b21b972599d27207a033afc76ef67sewardj      = __data_bits==8 ? 0xFF 					\
107b9c5cf639b3b21b972599d27207a033afc76ef67sewardj                       : (__data_bits==16 ? 0xFFFF 		\
108b9c5cf639b3b21b972599d27207a033afc76ef67sewardj                                          : 0xFFFFFFFF); 	\
109df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   /* const */ UInt SIGN_MASK = 1 << (__data_bits - 1);		\
110df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   /* const */ UInt CC_DST = cc_dst_formal;			\
111df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   /* const */ UInt CC_SRC = cc_src_formal;			\
112df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   /* Three bogus assignments, which hopefully gcc can    */	\
113df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   /* optimise away, and which stop it complaining about  */	\
114df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   /* unused variables.                                   */	\
115df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   SIGN_MASK = SIGN_MASK;					\
116df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   DATA_MASK = DATA_MASK;					\
117df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   CC_SRC = CC_SRC;
118df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj
11914731f22bf7759d6d23383ca870ac89d9581f1e9sewardj
120b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
121b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
122df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_ADD(DATA_BITS,DATA_UTYPE)			\
123b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
124b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
125b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   int cf, pf, af, zf, sf, of;					\
126b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   int src1, src2, dst;						\
127b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   src1 = CC_SRC;						\
128b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   src2 = CC_DST;						\
129b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   dst  = src1 + src2;						\
130df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   cf = (DATA_UTYPE)dst < (DATA_UTYPE)src1;			\
131b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   pf = parity_table[(uint8_t)dst];				\
132b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   af = (dst ^ src1 ^ src2) & 0x10;				\
133df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   zf = ((DATA_UTYPE)dst == 0) << 6;				\
134b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   sf = lshift(dst, 8 - DATA_BITS) & 0x80;			\
135b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   of = lshift((src1 ^ src2 ^ -1) & (src1 ^ dst), 		\
1369aebb0c3f7a7f43313786826f31402f2b733badfsewardj               12 - DATA_BITS) & CC_MASK_O;			\
137b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   return cf | pf | af | zf | sf | of;				\
1382ef5f2a829433c4ca17f33e1bf993cf16b9e347dsewardj}
1392ef5f2a829433c4ca17f33e1bf993cf16b9e347dsewardj
140b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
141b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
142df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_ADC(DATA_BITS,DATA_UTYPE)			\
143b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
144b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
145b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   int cf, pf, af, zf, sf, of;					\
146b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   int src1, src2, dst;						\
147b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   src1 = CC_SRC;						\
148b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   src2 = CC_DST;						\
149b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   dst = src1 + src2 + 1;					\
150df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   cf = (DATA_UTYPE)dst <= (DATA_UTYPE)src1;			\
151b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   pf = parity_table[(uint8_t)dst];				\
152b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   af = (dst ^ src1 ^ src2) & 0x10;				\
153df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   zf = ((DATA_UTYPE)dst == 0) << 6;				\
154b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   sf = lshift(dst, 8 - DATA_BITS) & 0x80;			\
155b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   of = lshift((src1 ^ src2 ^ -1) & (src1 ^ dst), 		\
1569aebb0c3f7a7f43313786826f31402f2b733badfsewardj                12 - DATA_BITS) & CC_MASK_O;			\
157b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   return cf | pf | af | zf | sf | of;				\
1582ef5f2a829433c4ca17f33e1bf993cf16b9e347dsewardj}
1592ef5f2a829433c4ca17f33e1bf993cf16b9e347dsewardj
160b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
161b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
162df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_SUB(DATA_BITS,DATA_UTYPE)			\
163b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
164b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
165b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   int cf, pf, af, zf, sf, of;					\
166b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   int src1, src2, dst;						\
167b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   src1 = CC_DST;						\
168b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   src2 = CC_SRC;						\
169b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   dst = src1 - src2;						\
170df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   cf = (DATA_UTYPE)src1 < (DATA_UTYPE)src2;			\
171b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   pf = parity_table[(uint8_t)dst];				\
172b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   af = (dst ^ src1 ^ src2) & 0x10;				\
173df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   zf = ((DATA_UTYPE)dst == 0) << 6;				\
174b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   sf = lshift(dst, 8 - DATA_BITS) & 0x80;			\
175b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   of = lshift((src1 ^ src2) & (src1 ^ dst),	 		\
1769aebb0c3f7a7f43313786826f31402f2b733badfsewardj               12 - DATA_BITS) & CC_MASK_O; 			\
177b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   return cf | pf | af | zf | sf | of;				\
1782ef5f2a829433c4ca17f33e1bf993cf16b9e347dsewardj}
1792ef5f2a829433c4ca17f33e1bf993cf16b9e347dsewardj
180b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
181b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
182df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_SBB(DATA_BITS,DATA_UTYPE)			\
183b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
184b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
185b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   int cf, pf, af, zf, sf, of;					\
186b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   int src1, src2, dst;						\
187b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   src1 = CC_DST;						\
188b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   src2 = CC_SRC;						\
189b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   dst = (src1 - src2) - 1;					\
190df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   cf = (DATA_UTYPE)src1 <= (DATA_UTYPE)src2;			\
191b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   pf = parity_table[(uint8_t)dst];				\
192b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   af = (dst ^ src1 ^ src2) & 0x10;				\
193df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   zf = ((DATA_UTYPE)dst == 0) << 6;				\
194b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   sf = lshift(dst, 8 - DATA_BITS) & 0x80;			\
195b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   of = lshift((src1 ^ src2) & (src1 ^ dst), 			\
1969aebb0c3f7a7f43313786826f31402f2b733badfsewardj               12 - DATA_BITS) & CC_MASK_O;			\
197b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   return cf | pf | af | zf | sf | of;				\
198a238471814bd386aeb58a76718b41e68b1a794b2sewardj}
199a238471814bd386aeb58a76718b41e68b1a794b2sewardj
200b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
201b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
202df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_LOGIC(DATA_BITS,DATA_UTYPE)			\
203b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
204b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
205b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   int cf, pf, af, zf, sf, of;					\
206b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   cf = 0;							\
207b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   pf = parity_table[(uint8_t)CC_DST];				\
208b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   af = 0;							\
209df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   zf = ((DATA_UTYPE)CC_DST == 0) << 6;				\
210b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;			\
211b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   of = 0;							\
212b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   return cf | pf | af | zf | sf | of;				\
213a238471814bd386aeb58a76718b41e68b1a794b2sewardj}
214a238471814bd386aeb58a76718b41e68b1a794b2sewardj
215b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
216b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
217df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_INC(DATA_BITS,DATA_UTYPE)			\
218b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
219b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
220b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   int cf, pf, af, zf, sf, of;					\
221b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   int src1, src2;						\
222b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   src1 = CC_DST - 1;						\
223b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   src2 = 1;							\
224b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   cf = CC_SRC;							\
225b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   pf = parity_table[(uint8_t)CC_DST];				\
226b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   af = (CC_DST ^ src1 ^ src2) & 0x10;				\
227df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   zf = ((DATA_UTYPE)CC_DST == 0) << 6;				\
228b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;			\
229b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   of = ((CC_DST & DATA_MASK) == SIGN_MASK) << 11;		\
230b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   return cf | pf | af | zf | sf | of;				\
23189050e58e7bee40892662fe94231aefc33768cf5sewardj}
23289050e58e7bee40892662fe94231aefc33768cf5sewardj
233b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
234b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
235df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_DEC(DATA_BITS,DATA_UTYPE)			\
236b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
237b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
238b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   int cf, pf, af, zf, sf, of;					\
239b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   int src1, src2;						\
240b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   src1 = CC_DST + 1;						\
241b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   src2 = 1;							\
242b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   cf = CC_SRC;							\
243b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   pf = parity_table[(uint8_t)CC_DST];				\
244b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   af = (CC_DST ^ src1 ^ src2) & 0x10;				\
245df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   zf = ((DATA_UTYPE)CC_DST == 0) << 6;				\
246b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;			\
247b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   of = ((CC_DST & DATA_MASK) 					\
248b9c5cf639b3b21b972599d27207a033afc76ef67sewardj        == ((uint32_t)SIGN_MASK - 1)) << 11;			\
249b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   return cf | pf | af | zf | sf | of;				\
25089050e58e7bee40892662fe94231aefc33768cf5sewardj}
25189050e58e7bee40892662fe94231aefc33768cf5sewardj
252b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
253b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
254df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_SHL(DATA_BITS,DATA_UTYPE)			\
255b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
256b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
257b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   int cf, pf, af, zf, sf, of;					\
2589aebb0c3f7a7f43313786826f31402f2b733badfsewardj   cf = (CC_SRC >> (DATA_BITS - 1)) & CC_MASK_C;		\
259b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   pf = parity_table[(uint8_t)CC_DST];				\
260b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   af = 0; /* undefined */					\
261df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   zf = ((DATA_UTYPE)CC_DST == 0) << 6;				\
262b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;			\
263b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   /* of is defined if shift count == 1 */			\
2649aebb0c3f7a7f43313786826f31402f2b733badfsewardj   of = lshift(CC_SRC ^ CC_DST, 12 - DATA_BITS) & CC_MASK_O;	\
265b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   return cf | pf | af | zf | sf | of;				\
2665f6303579435ddb8315e11c2f02c904b978782a0sewardj}
2675f6303579435ddb8315e11c2f02c904b978782a0sewardj
268b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
269b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
270df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_SAR(DATA_BITS,DATA_UTYPE)			\
271b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
272b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);  					\
273b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   int cf, pf, af, zf, sf, of;					\
274b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   cf = CC_SRC & 1;						\
275b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   pf = parity_table[(uint8_t)CC_DST];				\
276b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   af = 0; /* undefined */					\
277df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   zf = ((DATA_UTYPE)CC_DST == 0) << 6;				\
278b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;			\
279b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   /* of is defined if shift count == 1 */			\
2809aebb0c3f7a7f43313786826f31402f2b733badfsewardj   of = lshift(CC_SRC ^ CC_DST, 12 - DATA_BITS) & CC_MASK_O;	\
281b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   return cf | pf | af | zf | sf | of;				\
2825f6303579435ddb8315e11c2f02c904b978782a0sewardj}
2835f6303579435ddb8315e11c2f02c904b978782a0sewardj
284b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
285b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
2868ee2de1f5f72c13120f59c0ca6ac8291219123dfsewardj/* ROL: cf' = lsb(result).  of' = msb(result) ^ lsb(result). */
2878c7f1abe9e022f6382634efea09c9cac89ec6336sewardj/* DST = result, SRC = old flags */
288df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_ROL(DATA_BITS,DATA_UTYPE)			\
289b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
290b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
291b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   int fl 							\
2929aebb0c3f7a7f43313786826f31402f2b733badfsewardj      = (CC_SRC & ~(CC_MASK_O | CC_MASK_C))			\
2939aebb0c3f7a7f43313786826f31402f2b733badfsewardj        | (CC_MASK_C & CC_DST)					\
2949aebb0c3f7a7f43313786826f31402f2b733badfsewardj        | (CC_MASK_O & (lshift(CC_DST, 11-(DATA_BITS-1)) 	\
295b9c5cf639b3b21b972599d27207a033afc76ef67sewardj                   ^ lshift(CC_DST, 11)));			\
296b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   return fl;							\
2978c7f1abe9e022f6382634efea09c9cac89ec6336sewardj}
2988c7f1abe9e022f6382634efea09c9cac89ec6336sewardj
299b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
300b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
3011813dbeb912870e9a544cae17a3fadbf8d2b0d55sewardj/* ROR: cf' = msb(result).  of' = msb(result) ^ msb-1(result). */
3021813dbeb912870e9a544cae17a3fadbf8d2b0d55sewardj/* DST = result, SRC = old flags */
303df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_ROR(DATA_BITS,DATA_UTYPE)			\
304b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
305b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
306b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   int fl 							\
3079aebb0c3f7a7f43313786826f31402f2b733badfsewardj      = (CC_SRC & ~(CC_MASK_O | CC_MASK_C))			\
3089aebb0c3f7a7f43313786826f31402f2b733badfsewardj        | (CC_MASK_C & (CC_DST >> (DATA_BITS-1)))		\
3099aebb0c3f7a7f43313786826f31402f2b733badfsewardj        | (CC_MASK_O & (lshift(CC_DST, 11-(DATA_BITS-1)) 	\
310b9c5cf639b3b21b972599d27207a033afc76ef67sewardj                   ^ lshift(CC_DST, 11-(DATA_BITS-1)+1)));	\
311b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   return fl;							\
3121813dbeb912870e9a544cae17a3fadbf8d2b0d55sewardj}
3131813dbeb912870e9a544cae17a3fadbf8d2b0d55sewardj
314b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
315b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
316df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_UMUL(DATA_BITS,DATA_UTYPE,DATA_U2TYPE)		\
317b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
318b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
319b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   int cf, pf, af, zf, sf, of;					\
320df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   DATA_UTYPE  hi;						\
321df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   DATA_UTYPE  lo = ((DATA_UTYPE)CC_SRC) * ((DATA_UTYPE)CC_DST);\
322df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   DATA_U2TYPE rr = ((DATA_U2TYPE)((DATA_UTYPE)CC_SRC))		\
323df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj                    * ((DATA_U2TYPE)((DATA_UTYPE)CC_DST));	\
324df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   hi = (DATA_UTYPE)(rr >>/*u*/ DATA_BITS);			\
325df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   cf = (hi != 0);						\
326b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   pf = parity_table[(uint8_t)lo];				\
327b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   af = 0; /* undefined */					\
328df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   zf = (lo == 0) << 6;				  	     	\
329b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   sf = lshift(lo, 8 - DATA_BITS) & 0x80;			\
330b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   of = cf << 11;						\
331b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   return cf | pf | af | zf | sf | of;				\
33256296d80c9e15ec59eebecf1c3aea9ebd4dac115sewardj}
33356296d80c9e15ec59eebecf1c3aea9ebd4dac115sewardj
334b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
335b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
336df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_SMUL(DATA_BITS,DATA_STYPE,DATA_S2TYPE)		\
337b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
338b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
339b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   int cf, pf, af, zf, sf, of;					\
340df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   DATA_STYPE  hi;						\
341df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   DATA_STYPE  lo = ((DATA_STYPE)CC_SRC) * ((DATA_STYPE)CC_DST);\
342df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   DATA_S2TYPE rr = ((DATA_S2TYPE)((DATA_STYPE)CC_SRC))		\
343df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj                    * ((DATA_S2TYPE)((DATA_STYPE)CC_DST));	\
344df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   hi = (DATA_STYPE)(rr >>/*s*/ DATA_BITS);			\
345df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   cf = (hi != (lo >>/*s*/ (DATA_BITS-1)));			\
346b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   pf = parity_table[(uint8_t)lo];				\
347b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   af = 0; /* undefined */					\
348df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   zf = (lo == 0) << 6;						\
349b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   sf = lshift(lo, 8 - DATA_BITS) & 0x80;			\
350b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   of = cf << 11;						\
351b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   return cf | pf | af | zf | sf | of;				\
3527ed2295459ac5e788a98dd5570fef0d4645c27d4sewardj}
353741153c4301023a420ab45b8a10b8e1bac968822sewardj
35436ca51378f8851635df814230fa23f2c409b9eddsewardj
35584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
35684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#define CC_SHIFT_C 0
35784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#define CC_SHIFT_P 2
35884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#define CC_SHIFT_A 4
35984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#define CC_SHIFT_Z 6
36084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#define CC_SHIFT_S 7
361b9c5cf639b3b21b972599d27207a033afc76ef67sewardj#define CC_SHIFT_O 11
36284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
36384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#if PROFILE_EFLAGS
36484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
36584ff0657940e62f38e618ea18bac6f27ce0e741fsewardjstatic UInt tabc[CC_OP_NUMBER];
36684ff0657940e62f38e618ea18bac6f27ce0e741fsewardjstatic UInt tab[CC_OP_NUMBER][16];
3679eab588e223e52b1e7b710ff1c0da7b032ab2837sewardjstatic Bool initted     = False;
36884ff0657940e62f38e618ea18bac6f27ce0e741fsewardjstatic UInt n_calc_cond = 0;
36984ff0657940e62f38e618ea18bac6f27ce0e741fsewardjstatic UInt n_calc_all  = 0;
37084ff0657940e62f38e618ea18bac6f27ce0e741fsewardjstatic UInt n_calc_c    = 0;
37184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
37284ff0657940e62f38e618ea18bac6f27ce0e741fsewardjstatic void showCounts ( void )
37384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj{
37484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   Int op, co;
37584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   Char ch;
3769eab588e223e52b1e7b710ff1c0da7b032ab2837sewardj   vex_printf("\nALL=%d  COND=%d   C=%d\n",
37784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj              n_calc_all-n_calc_cond-n_calc_c, n_calc_cond, n_calc_c);
37884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   vex_printf("      CARRY    O   NO    B   NB    Z   NZ   BE  NBE"
37984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj              "    S   NS    P   NP    L   NL   LE  NLE\n");
38084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   vex_printf("     ----------------------------------------------"
38184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj              "----------------------------------------\n");
38284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   for (op = 0; op < CC_OP_NUMBER; op++) {
38384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
38484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      ch = ' ';
38584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      if (op > 0 && (op-1) % 3 == 2)
38684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         ch = 'L';
38784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
38884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      vex_printf("%2d%c: ", op, ch);
38984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      vex_printf("%6d ", tabc[op]);
39084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      for (co = 0; co < 16; co++) {
39184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         Int n = tab[op][co];
39284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         if (n >= 1000) {
39384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj            vex_printf(" %3dK", n / 1000);
39484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         } else
39584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         if (n >= 0) {
39684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj           vex_printf(" %3d ", n );
39784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         } else {
39884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj            vex_printf("     ");
39984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         }
40084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
40184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      vex_printf("\n");
40284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   }
40384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   vex_printf("\n");
40484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj}
40584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
40684ff0657940e62f38e618ea18bac6f27ce0e741fsewardjstatic void initCounts ( void )
40784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj{
40884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   Int op, co;
40984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   initted = True;
41084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   for (op = 0; op < CC_OP_NUMBER; op++) {
41184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      tabc[op] = 0;
41284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      for (co = 0; co < 16; co++)
41384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         tab[op][co] = 0;
41484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   }
41584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj}
41684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
41784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#endif /* PROFILE_EFLAGS */
41884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
4199aebb0c3f7a7f43313786826f31402f2b733badfsewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
420b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/* Calculate all the 6 flags from the supplied thunk parameters. */
4219aebb0c3f7a7f43313786826f31402f2b733badfsewardjstatic
422df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardjUInt calculate_eflags_all ( UInt cc_op, UInt cc_src_formal, UInt cc_dst_formal )
42336ca51378f8851635df814230fa23f2c409b9eddsewardj{
42484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  if PROFILE_EFLAGS
42584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   n_calc_all++;
42684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  endif
42736ca51378f8851635df814230fa23f2c409b9eddsewardj   switch (cc_op) {
4281813dbeb912870e9a544cae17a3fadbf8d2b0d55sewardj      case CC_OP_COPY:
429df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj         return cc_src_formal
430df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj                & (CC_MASK_O | CC_MASK_S | CC_MASK_Z
431df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj                   | CC_MASK_A | CC_MASK_C | CC_MASK_P);
43214731f22bf7759d6d23383ca870ac89d9581f1e9sewardj
4338c7f1abe9e022f6382634efea09c9cac89ec6336sewardj      case CC_OP_ADDB:   ACTIONS_ADD( 8,  UChar  );
434a238471814bd386aeb58a76718b41e68b1a794b2sewardj      case CC_OP_ADDW:   ACTIONS_ADD( 16, UShort );
4358c7f1abe9e022f6382634efea09c9cac89ec6336sewardj      case CC_OP_ADDL:   ACTIONS_ADD( 32, UInt   );
436a238471814bd386aeb58a76718b41e68b1a794b2sewardj
4378c7f1abe9e022f6382634efea09c9cac89ec6336sewardj      case CC_OP_ADCB:   ACTIONS_ADC( 8,  UChar  );
438a238471814bd386aeb58a76718b41e68b1a794b2sewardj      case CC_OP_ADCW:   ACTIONS_ADC( 16, UShort );
4398c7f1abe9e022f6382634efea09c9cac89ec6336sewardj      case CC_OP_ADCL:   ACTIONS_ADC( 32, UInt   );
440a238471814bd386aeb58a76718b41e68b1a794b2sewardj
4418c7f1abe9e022f6382634efea09c9cac89ec6336sewardj      case CC_OP_SUBB:   ACTIONS_SUB(  8, UChar  );
442a238471814bd386aeb58a76718b41e68b1a794b2sewardj      case CC_OP_SUBW:   ACTIONS_SUB( 16, UShort );
4438c7f1abe9e022f6382634efea09c9cac89ec6336sewardj      case CC_OP_SUBL:   ACTIONS_SUB( 32, UInt   );
444afc5787e1c4b8e9678669577cf57ac509c6cd6b5sewardj
4458c7f1abe9e022f6382634efea09c9cac89ec6336sewardj      case CC_OP_SBBB:   ACTIONS_SBB(  8, UChar  );
446a238471814bd386aeb58a76718b41e68b1a794b2sewardj      case CC_OP_SBBW:   ACTIONS_SBB( 16, UShort );
4478c7f1abe9e022f6382634efea09c9cac89ec6336sewardj      case CC_OP_SBBL:   ACTIONS_SBB( 32, UInt   );
448741153c4301023a420ab45b8a10b8e1bac968822sewardj
4498c7f1abe9e022f6382634efea09c9cac89ec6336sewardj      case CC_OP_LOGICB: ACTIONS_LOGIC(  8, UChar  );
450a238471814bd386aeb58a76718b41e68b1a794b2sewardj      case CC_OP_LOGICW: ACTIONS_LOGIC( 16, UShort );
4518c7f1abe9e022f6382634efea09c9cac89ec6336sewardj      case CC_OP_LOGICL: ACTIONS_LOGIC( 32, UInt   );
4525f6303579435ddb8315e11c2f02c904b978782a0sewardj
4538c7f1abe9e022f6382634efea09c9cac89ec6336sewardj      case CC_OP_INCB:   ACTIONS_INC(  8, UChar  );
454a238471814bd386aeb58a76718b41e68b1a794b2sewardj      case CC_OP_INCW:   ACTIONS_INC( 16, UShort );
4558c7f1abe9e022f6382634efea09c9cac89ec6336sewardj      case CC_OP_INCL:   ACTIONS_INC( 32, UInt   );
4561813dbeb912870e9a544cae17a3fadbf8d2b0d55sewardj
4578c7f1abe9e022f6382634efea09c9cac89ec6336sewardj      case CC_OP_DECB:   ACTIONS_DEC(  8, UChar  );
458a238471814bd386aeb58a76718b41e68b1a794b2sewardj      case CC_OP_DECW:   ACTIONS_DEC( 16, UShort );
4598c7f1abe9e022f6382634efea09c9cac89ec6336sewardj      case CC_OP_DECL:   ACTIONS_DEC( 32, UInt   );
4608c7f1abe9e022f6382634efea09c9cac89ec6336sewardj
4618c7f1abe9e022f6382634efea09c9cac89ec6336sewardj      case CC_OP_SHLB:   ACTIONS_SHL(  8, UChar  );
4628c7f1abe9e022f6382634efea09c9cac89ec6336sewardj      case CC_OP_SHLW:   ACTIONS_SHL( 16, UShort );
4638c7f1abe9e022f6382634efea09c9cac89ec6336sewardj      case CC_OP_SHLL:   ACTIONS_SHL( 32, UInt   );
4648c7f1abe9e022f6382634efea09c9cac89ec6336sewardj
4658c7f1abe9e022f6382634efea09c9cac89ec6336sewardj      case CC_OP_SARB:   ACTIONS_SAR(  8, UChar  );
4668c7f1abe9e022f6382634efea09c9cac89ec6336sewardj      case CC_OP_SARW:   ACTIONS_SAR( 16, UShort );
4678c7f1abe9e022f6382634efea09c9cac89ec6336sewardj      case CC_OP_SARL:   ACTIONS_SAR( 32, UInt   );
4681813dbeb912870e9a544cae17a3fadbf8d2b0d55sewardj
4698c7f1abe9e022f6382634efea09c9cac89ec6336sewardj      case CC_OP_ROLB:   ACTIONS_ROL(  8, UChar  );
4708c7f1abe9e022f6382634efea09c9cac89ec6336sewardj      case CC_OP_ROLW:   ACTIONS_ROL( 16, UShort );
4718c7f1abe9e022f6382634efea09c9cac89ec6336sewardj      case CC_OP_ROLL:   ACTIONS_ROL( 32, UInt   );
472750f407b6be1aac303964a219acf0a6de8b8c4dasewardj
4738c7f1abe9e022f6382634efea09c9cac89ec6336sewardj      case CC_OP_RORB:   ACTIONS_ROR(  8, UChar  );
474a238471814bd386aeb58a76718b41e68b1a794b2sewardj      case CC_OP_RORW:   ACTIONS_ROR( 16, UShort );
4758c7f1abe9e022f6382634efea09c9cac89ec6336sewardj      case CC_OP_RORL:   ACTIONS_ROR( 32, UInt   );
4767ed2295459ac5e788a98dd5570fef0d4645c27d4sewardj
477b81f8b3e9110a5608094b8ec1a5c6d3c30a8e5aesewardj      case CC_OP_UMULB:  ACTIONS_UMUL(  8, UChar,  UShort );
478b81f8b3e9110a5608094b8ec1a5c6d3c30a8e5aesewardj      case CC_OP_UMULW:  ACTIONS_UMUL( 16, UShort, UInt   );
479b81f8b3e9110a5608094b8ec1a5c6d3c30a8e5aesewardj      case CC_OP_UMULL:  ACTIONS_UMUL( 32, UInt,   ULong  );
48056296d80c9e15ec59eebecf1c3aea9ebd4dac115sewardj
481b81f8b3e9110a5608094b8ec1a5c6d3c30a8e5aesewardj      case CC_OP_SMULB:  ACTIONS_SMUL(  8, Char,  Short );
482b81f8b3e9110a5608094b8ec1a5c6d3c30a8e5aesewardj      case CC_OP_SMULW:  ACTIONS_SMUL( 16, Short, Int   );
483b81f8b3e9110a5608094b8ec1a5c6d3c30a8e5aesewardj      case CC_OP_SMULL:  ACTIONS_SMUL( 32, Int,   Long  );
484741153c4301023a420ab45b8a10b8e1bac968822sewardj
48536ca51378f8851635df814230fa23f2c409b9eddsewardj      default:
48636ca51378f8851635df814230fa23f2c409b9eddsewardj         /* shouldn't really make these calls from generated code */
48714731f22bf7759d6d23383ca870ac89d9581f1e9sewardj         vex_printf("calculate_eflags_all( %d, 0x%x, 0x%x )\n",
488df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj                    cc_op, cc_src_formal, cc_dst_formal );
48936ca51378f8851635df814230fa23f2c409b9eddsewardj         vpanic("calculate_eflags_all");
49036ca51378f8851635df814230fa23f2c409b9eddsewardj   }
49136ca51378f8851635df814230fa23f2c409b9eddsewardj}
49236ca51378f8851635df814230fa23f2c409b9eddsewardj
493b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
4949aebb0c3f7a7f43313786826f31402f2b733badfsewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
495b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/* Calculate just the carry flag from the supplied thunk parameters. */
49636ca51378f8851635df814230fa23f2c409b9eddsewardjstatic UInt calculate_eflags_c ( UInt cc_op, UInt cc_src, UInt cc_dst )
49736ca51378f8851635df814230fa23f2c409b9eddsewardj{
4989eab588e223e52b1e7b710ff1c0da7b032ab2837sewardj   /* Fast-case some common ones. */
49943c46951628d616290f7245c3af2f9a652180806sewardj   switch (cc_op) {
50043c46951628d616290f7245c3af2f9a652180806sewardj      case CC_OP_LOGICL: case CC_OP_LOGICW: case CC_OP_LOGICB:
50143c46951628d616290f7245c3af2f9a652180806sewardj         return 0;
50243c46951628d616290f7245c3af2f9a652180806sewardj      case CC_OP_DECL:
50343c46951628d616290f7245c3af2f9a652180806sewardj         return cc_src;
50443c46951628d616290f7245c3af2f9a652180806sewardj      case CC_OP_SUBL:
50543c46951628d616290f7245c3af2f9a652180806sewardj         return ( ((UInt)cc_src) > ((UInt)cc_dst) )
50643c46951628d616290f7245c3af2f9a652180806sewardj                   ? CC_MASK_C : 0;
50743c46951628d616290f7245c3af2f9a652180806sewardj      case CC_OP_ADDL:
50843c46951628d616290f7245c3af2f9a652180806sewardj         return ( ((UInt)cc_src + (UInt)cc_dst) < ((UInt)cc_src) )
50943c46951628d616290f7245c3af2f9a652180806sewardj                   ? CC_MASK_C : 0;
51043c46951628d616290f7245c3af2f9a652180806sewardj      case CC_OP_SUBB:
51143c46951628d616290f7245c3af2f9a652180806sewardj         return ( ((UInt)(cc_src & 0xFF)) > ((UInt)(cc_dst & 0xFF)) )
51243c46951628d616290f7245c3af2f9a652180806sewardj                   ? CC_MASK_C : 0;
51343c46951628d616290f7245c3af2f9a652180806sewardj      default:
51443c46951628d616290f7245c3af2f9a652180806sewardj         break;
51543c46951628d616290f7245c3af2f9a652180806sewardj   }
5169eab588e223e52b1e7b710ff1c0da7b032ab2837sewardj
51784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  if PROFILE_EFLAGS
51884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   if (!initted)
51984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      initCounts();
52084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   tabc[cc_op]++;
52184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
52284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   n_calc_c++;
52384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  endif
52436ca51378f8851635df814230fa23f2c409b9eddsewardj   return calculate_eflags_all(cc_op,cc_src,cc_dst) & CC_MASK_C;
52536ca51378f8851635df814230fa23f2c409b9eddsewardj}
52636ca51378f8851635df814230fa23f2c409b9eddsewardj
52736ca51378f8851635df814230fa23f2c409b9eddsewardj
5289aebb0c3f7a7f43313786826f31402f2b733badfsewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
52984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj/* returns 1 or 0 */
53084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj/*static*/ UInt calculate_condition ( UInt/*Condcode*/ cond,
53184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj                                      UInt cc_op, UInt cc_src, UInt cc_dst )
53284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj{
53384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   UInt eflags = calculate_eflags_all(cc_op, cc_src, cc_dst);
53484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   UInt of,sf,zf,cf,pf;
53584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   UInt inv = cond & 1;
53684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
53784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  if PROFILE_EFLAGS
53884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   if (!initted)
53984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj     initCounts();
54084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
54184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   tab[cc_op][cond]++;
54284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   n_calc_cond++;
54384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
54446ccb51aff085d180120d310c0be2fe6c86e1b65sewardj   if (0 == ((n_calc_all+n_calc_c) & 0x3FFF)) showCounts();
54584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  endif
54684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
54784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   switch (cond) {
54884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      case CondNO:
54984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      case CondO: /* OF == 1 */
55084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         of = eflags >> CC_SHIFT_O;
55184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return 1 & (inv ^ of);
55284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
55384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      case CondNZ:
55484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      case CondZ: /* ZF == 1 */
55584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         zf = eflags >> CC_SHIFT_Z;
55684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return 1 & (inv ^ zf);
55784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
55884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      case CondNB:
55984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      case CondB: /* CF == 1 */
56084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         cf = eflags >> CC_SHIFT_C;
56184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return 1 & (inv ^ cf);
56284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         break;
56384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
56484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      case CondNBE:
56584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      case CondBE: /* (CF or ZF) == 1 */
56684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         cf = eflags >> CC_SHIFT_C;
56784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         zf = eflags >> CC_SHIFT_Z;
56884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return 1 & (inv ^ (cf | zf));
56984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         break;
57084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
57184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      case CondNS:
57284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      case CondS: /* SF == 1 */
57384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         sf = eflags >> CC_SHIFT_S;
57484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return 1 & (inv ^ sf);
57584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
57684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      case CondNP:
57784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      case CondP: /* PF == 1 */
57884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         pf = eflags >> CC_SHIFT_P;
57984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return 1 & (inv ^ pf);
58084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
58184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      case CondNL:
58284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      case CondL: /* (SF xor OF) == 1 */
58384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         sf = eflags >> CC_SHIFT_S;
58484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         of = eflags >> CC_SHIFT_O;
58584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return 1 & (inv ^ (sf ^ of));
58684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         break;
58784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
58884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      case CondNLE:
58984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      case CondLE: /* ((SF xor OF) or ZF)  == 1 */
59084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         sf = eflags >> CC_SHIFT_S;
59184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         of = eflags >> CC_SHIFT_O;
59284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         zf = eflags >> CC_SHIFT_Z;
59384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return 1 & (inv ^ ((sf ^ of) | zf));
59484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         break;
59584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
59684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      default:
59784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         /* shouldn't really make these calls from generated code */
59884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         vex_printf("calculate_condition( %d, %d, 0x%x, 0x%x )\n",
59984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj                    cond, cc_op, cc_src, cc_dst );
60084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         vpanic("calculate_condition");
60184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   }
60284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj}
60384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
60484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
60536ca51378f8851635df814230fa23f2c409b9eddsewardjAddr64 x86guest_findhelper ( Char* function_name )
60636ca51378f8851635df814230fa23f2c409b9eddsewardj{
60784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   if (vex_streq(function_name, "calculate_condition"))
608b7e76e8cc158a9247b81287768d352911706c53dsewardj      return (Addr64)(Addr32)(& calculate_condition);
60917442fe8094d0f82266e5a05509f62cac8f7539esewardj   if (vex_streq(function_name, "calculate_eflags_c"))
610b7e76e8cc158a9247b81287768d352911706c53dsewardj      return (Addr64)(Addr32)(& calculate_eflags_c);
61117442fe8094d0f82266e5a05509f62cac8f7539esewardj   if (vex_streq(function_name, "calculate_eflags_all"))
612b7e76e8cc158a9247b81287768d352911706c53dsewardj      return (Addr64)(Addr32)(& calculate_eflags_all);
613c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   if (vex_streq(function_name, "calculate_FXAM"))
614b7e76e8cc158a9247b81287768d352911706c53dsewardj      return (Addr64)(Addr32)(& calculate_FXAM);
61517442fe8094d0f82266e5a05509f62cac8f7539esewardj   if (vex_streq(function_name, "storeF80le"))
616b7e76e8cc158a9247b81287768d352911706c53dsewardj      return (Addr64)(Addr32)(& storeF80le);
61717442fe8094d0f82266e5a05509f62cac8f7539esewardj   if (vex_streq(function_name, "loadF80le"))
618b7e76e8cc158a9247b81287768d352911706c53dsewardj      return (Addr64)(Addr32)(& loadF80le);
6199aebb0c3f7a7f43313786826f31402f2b733badfsewardj   if (vex_streq(function_name, "calculate_RCR"))
6209aebb0c3f7a7f43313786826f31402f2b733badfsewardj      return (Addr64)(Addr32)(& calculate_RCR);
6217cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardj   if (vex_streq(function_name, "dirtyhelper_CPUID"))
6227cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardj      return (Addr64)(Addr32)(& dirtyhelper_CPUID);
62336ca51378f8851635df814230fa23f2c409b9eddsewardj   vex_printf("\nx86 guest: can't find helper: %s\n", function_name);
62436ca51378f8851635df814230fa23f2c409b9eddsewardj   vpanic("x86guest_findhelper");
62536ca51378f8851635df814230fa23f2c409b9eddsewardj}
62636ca51378f8851635df814230fa23f2c409b9eddsewardj
62784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj/* Used by the optimiser to try specialisations.  Returns an
62884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   equivalent expression, or NULL if none. */
62984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
63084ff0657940e62f38e618ea18bac6f27ce0e741fsewardjstatic Bool isU32 ( IRExpr* e, UInt n )
63184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj{
63284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   return e->tag == Iex_Const
63384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj          && e->Iex.Const.con->tag == Ico_U32
63484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj          && e->Iex.Const.con->Ico.U32 == n;
63584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj}
63684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
63784ff0657940e62f38e618ea18bac6f27ce0e741fsewardjIRExpr* x86guest_spechelper ( Char* function_name,
63884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj                              IRExpr** args )
63984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj{
64084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  define unop(_op,_a1) IRExpr_Unop((_op),(_a1))
64184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  define binop(_op,_a1,_a2) IRExpr_Binop((_op),(_a1),(_a2))
64284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  define mkU32(_n) IRExpr_Const(IRConst_U32(_n))
64384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
64484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   Int i, arity = 0;
64584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   for (i = 0; args[i]; i++)
64684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      arity++;
64784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  if 0
64884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   vex_printf("spec request:\n");
64984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   vex_printf("   %s  ", function_name);
65084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   for (i = 0; i < arity; i++) {
65184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      vex_printf("  ");
65284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      ppIRExpr(args[i]);
65384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   }
65484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   vex_printf("\n");
65584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  endif
65684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
65784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   if (vex_streq(function_name, "calculate_eflags_c")) {
65884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      /* specialise calls to above "calculate_eflags_c" function */
65984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      IRExpr *cc_op, *cc_src, *cc_dst;
66084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      vassert(arity == 3);
66184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      cc_op = args[0];
66284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      cc_src = args[1];
66384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      cc_dst = args[2];
66484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
66584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      if (isU32(cc_op, CC_OP_LOGICL)) {
66684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         /* cflag after logic is zero */
66784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return mkU32(0);
66884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
66984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      if (isU32(cc_op, CC_OP_DECL) || isU32(cc_op, CC_OP_INCL)) {
67084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         /* If the thunk is dec or inc, the cflag is supplied as CC_SRC. */
67184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return cc_src;
67284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
67384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      if (isU32(cc_op, CC_OP_SUBL)) {
67484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         /* C after sub denotes unsigned less than */
67584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return unop(Iop_1Uto32,
676b9c5cf639b3b21b972599d27207a033afc76ef67sewardj                     binop(Iop_CmpLT32U, cc_dst, cc_src));
67784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
678b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
67984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#     if 0
68084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      if (cc_op->tag == Iex_Const) {
68184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         vex_printf("CFLAG "); ppIRExpr(cc_op); vex_printf("\n");
68284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
68384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#     endif
68484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
68584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      return NULL;
68684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   }
68784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
68884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   if (vex_streq(function_name, "calculate_condition")) {
68984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      /* specialise calls to above "calculate condition" function */
69084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      IRExpr *cond, *cc_op, *cc_src, *cc_dst;
69184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      vassert(arity == 4);
69284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      cond = args[0];
69384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      cc_op = args[1];
69484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      cc_src = args[2];
69584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      cc_dst = args[3];
69684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
69746ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      /*---------------- SUBL ----------------*/
69846ccb51aff085d180120d310c0be2fe6c86e1b65sewardj
69946ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      if (isU32(cc_op, CC_OP_SUBL) && isU32(cond, CondZ)) {
70046ccb51aff085d180120d310c0be2fe6c86e1b65sewardj         /* long sub/cmp, then Z --> test dst==src */
70184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return unop(Iop_1Uto32,
70246ccb51aff085d180120d310c0be2fe6c86e1b65sewardj                     binop(Iop_CmpEQ32, cc_dst, cc_src));
70346ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      }
70446ccb51aff085d180120d310c0be2fe6c86e1b65sewardj
70546ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      if (isU32(cc_op, CC_OP_SUBL) && isU32(cond, CondL)) {
70646ccb51aff085d180120d310c0be2fe6c86e1b65sewardj         /* long sub/cmp, then L (signed less than)
70746ccb51aff085d180120d310c0be2fe6c86e1b65sewardj            --> test dst <s src */
70846ccb51aff085d180120d310c0be2fe6c86e1b65sewardj         return unop(Iop_1Uto32,
70946ccb51aff085d180120d310c0be2fe6c86e1b65sewardj                     binop(Iop_CmpLT32S, cc_dst, cc_src));
71046ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      }
71146ccb51aff085d180120d310c0be2fe6c86e1b65sewardj
71246ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      if (isU32(cc_op, CC_OP_SUBL) && isU32(cond, CondLE)) {
71346ccb51aff085d180120d310c0be2fe6c86e1b65sewardj         /* long sub/cmp, then LE (signed less than or equal)
71446ccb51aff085d180120d310c0be2fe6c86e1b65sewardj            --> test dst <=s src */
71546ccb51aff085d180120d310c0be2fe6c86e1b65sewardj         return unop(Iop_1Uto32,
71646ccb51aff085d180120d310c0be2fe6c86e1b65sewardj                     binop(Iop_CmpLE32S, cc_dst, cc_src));
71746ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      }
71846ccb51aff085d180120d310c0be2fe6c86e1b65sewardj
71946ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      if (isU32(cc_op, CC_OP_SUBL) && isU32(cond, CondBE)) {
72046ccb51aff085d180120d310c0be2fe6c86e1b65sewardj         /* long sub/cmp, then BE (unsigned less than or equal)
72146ccb51aff085d180120d310c0be2fe6c86e1b65sewardj            --> test dst <=u src */
72246ccb51aff085d180120d310c0be2fe6c86e1b65sewardj         return unop(Iop_1Uto32,
72346ccb51aff085d180120d310c0be2fe6c86e1b65sewardj                     binop(Iop_CmpLE32U, cc_dst, cc_src));
72446ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      }
72546ccb51aff085d180120d310c0be2fe6c86e1b65sewardj
72646ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      if (isU32(cc_op, CC_OP_SUBL) && isU32(cond, CondB)) {
72746ccb51aff085d180120d310c0be2fe6c86e1b65sewardj         /* long sub/cmp, then B (unsigned less than)
72846ccb51aff085d180120d310c0be2fe6c86e1b65sewardj            --> test dst <u src */
72946ccb51aff085d180120d310c0be2fe6c86e1b65sewardj         return unop(Iop_1Uto32,
73046ccb51aff085d180120d310c0be2fe6c86e1b65sewardj                     binop(Iop_CmpLT32U, cc_dst, cc_src));
73184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
73284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
73346ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      /*---------------- SUBW ----------------*/
73446ccb51aff085d180120d310c0be2fe6c86e1b65sewardj
735b9c5cf639b3b21b972599d27207a033afc76ef67sewardj      if (isU32(cc_op, CC_OP_SUBW) && isU32(cond, CondZ)) {
736b9c5cf639b3b21b972599d27207a033afc76ef67sewardj         /* byte sub/cmp, then Z --> test dst==src */
737b9c5cf639b3b21b972599d27207a033afc76ef67sewardj         return unop(Iop_1Uto32,
738b9c5cf639b3b21b972599d27207a033afc76ef67sewardj                     binop(Iop_CmpEQ16,
739b9c5cf639b3b21b972599d27207a033afc76ef67sewardj                           unop(Iop_32to16,cc_dst),
740b9c5cf639b3b21b972599d27207a033afc76ef67sewardj                           unop(Iop_32to16,cc_src)));
741b9c5cf639b3b21b972599d27207a033afc76ef67sewardj      }
742b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
74346ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      /*---------------- SUBB ----------------*/
74446ccb51aff085d180120d310c0be2fe6c86e1b65sewardj
74584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      if (isU32(cc_op, CC_OP_SUBB) && isU32(cond, CondZ)) {
746b9c5cf639b3b21b972599d27207a033afc76ef67sewardj         /* byte sub/cmp, then Z --> test dst==src */
74784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return unop(Iop_1Uto32,
748b9c5cf639b3b21b972599d27207a033afc76ef67sewardj                     binop(Iop_CmpEQ8,
749b9c5cf639b3b21b972599d27207a033afc76ef67sewardj                           unop(Iop_32to8,cc_dst),
750b9c5cf639b3b21b972599d27207a033afc76ef67sewardj                           unop(Iop_32to8,cc_src)));
75184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
75284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
75384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      if (isU32(cc_op, CC_OP_SUBB) && isU32(cond, CondNZ)) {
754b9c5cf639b3b21b972599d27207a033afc76ef67sewardj         /* byte sub/cmp, then Z --> test dst!=src */
75584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return unop(Iop_1Uto32,
756b9c5cf639b3b21b972599d27207a033afc76ef67sewardj                     binop(Iop_CmpNE8,
757b9c5cf639b3b21b972599d27207a033afc76ef67sewardj                           unop(Iop_32to8,cc_dst),
758b9c5cf639b3b21b972599d27207a033afc76ef67sewardj                           unop(Iop_32to8,cc_src)));
759b9c5cf639b3b21b972599d27207a033afc76ef67sewardj      }
760b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
761b9c5cf639b3b21b972599d27207a033afc76ef67sewardj      if (isU32(cc_op, CC_OP_SUBB) && isU32(cond, CondNBE)) {
762b9c5cf639b3b21b972599d27207a033afc76ef67sewardj         /* long sub/cmp, then NBE (unsigned greater than)
763b9c5cf639b3b21b972599d27207a033afc76ef67sewardj            --> test src <=u dst */
764b9c5cf639b3b21b972599d27207a033afc76ef67sewardj         return unop(Iop_1Uto32,
765b9c5cf639b3b21b972599d27207a033afc76ef67sewardj                     binop(Iop_CmpLT32U,
7666cd3a78ada41360f404ea124c4651eb80aef3ccfsewardj                           binop(Iop_And32,cc_src,mkU32(0xFF)),
7676cd3a78ada41360f404ea124c4651eb80aef3ccfsewardj			   binop(Iop_And32,cc_dst,mkU32(0xFF))));
76884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
76984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
77046ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      /*---------------- LOGICL ----------------*/
77146ccb51aff085d180120d310c0be2fe6c86e1b65sewardj
77284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      if (isU32(cc_op, CC_OP_LOGICL) && isU32(cond, CondZ)) {
77384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         /* long and/or/xor, then Z --> test dst==0 */
77484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return unop(Iop_1Uto32,binop(Iop_CmpEQ32, cc_dst, mkU32(0)));
77584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
77684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
777fae2ca7ef81549a4b28235618317d4352ca32ac2sewardj      if (isU32(cc_op, CC_OP_LOGICL) && isU32(cond, CondS)) {
778fae2ca7ef81549a4b28235618317d4352ca32ac2sewardj         /* long and/or/xor, then S --> test dst <s 0 */
779fae2ca7ef81549a4b28235618317d4352ca32ac2sewardj         return unop(Iop_1Uto32,binop(Iop_CmpLT32S, cc_dst, mkU32(0)));
780fae2ca7ef81549a4b28235618317d4352ca32ac2sewardj      }
781fae2ca7ef81549a4b28235618317d4352ca32ac2sewardj
78284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      if (isU32(cc_op, CC_OP_LOGICL) && isU32(cond, CondLE)) {
78384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         /* long and/or/xor, then LE
78484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj            This is pretty subtle.  LOGIC sets SF and ZF according to the
78584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj            result and makes OF be zero.  LE computes (SZ ^ OF) | ZF, but
78684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj            OF is zero, so this reduces to SZ | ZF -- which will be 1 iff
78784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj            the result is <=signed 0.  Hence ...
78884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         */
78984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return unop(Iop_1Uto32,binop(Iop_CmpLE32S, cc_dst, mkU32(0)));
79084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
79184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
79246ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      /*---------------- LOGICB ----------------*/
79384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
79446ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      if (isU32(cc_op, CC_OP_LOGICB) && isU32(cond, CondZ)) {
79546ccb51aff085d180120d310c0be2fe6c86e1b65sewardj         /* byte and/or/xor, then Z --> test dst==0 */
79684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return unop(Iop_1Uto32,
79746ccb51aff085d180120d310c0be2fe6c86e1b65sewardj                     binop(Iop_CmpEQ32, binop(Iop_And32,cc_dst,mkU32(255)),
79846ccb51aff085d180120d310c0be2fe6c86e1b65sewardj                                        mkU32(0)));
79984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
80084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
80146ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      /*---------------- DECL ----------------*/
802af991dede2815b7570828b9d9174cf989e636254sewardj
80384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      if (isU32(cc_op, CC_OP_DECL) && isU32(cond, CondZ)) {
80484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         /* dec L, then Z --> test dst == 0 */
80584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return unop(Iop_1Uto32,binop(Iop_CmpEQ32, cc_dst, mkU32(0)));
80684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
80784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
808fae2ca7ef81549a4b28235618317d4352ca32ac2sewardj      if (isU32(cc_op, CC_OP_DECL) && isU32(cond, CondS)) {
809fae2ca7ef81549a4b28235618317d4352ca32ac2sewardj         /* dec L, then S --> compare DST <s 0 */
810fae2ca7ef81549a4b28235618317d4352ca32ac2sewardj         return unop(Iop_1Uto32,binop(Iop_CmpLT32S, cc_dst, mkU32(0)));
811fae2ca7ef81549a4b28235618317d4352ca32ac2sewardj      }
812fae2ca7ef81549a4b28235618317d4352ca32ac2sewardj
81384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      return NULL;
81484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   }
81584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
81684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  undef unop
81784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  undef binop
81884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  undef mkU32
81984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
82084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   return NULL;
82184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj}
82284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
82336ca51378f8851635df814230fa23f2c409b9eddsewardj
8240c2cb623cca372a2b42b073121c7413cdaaf75besewardj/*-----------------------------------------------------------*/
8250c2cb623cca372a2b42b073121c7413cdaaf75besewardj/*--- Utility functions for x87 FPU conversions.          ---*/
8260c2cb623cca372a2b42b073121c7413cdaaf75besewardj/*-----------------------------------------------------------*/
8270c2cb623cca372a2b42b073121c7413cdaaf75besewardj
8280c2cb623cca372a2b42b073121c7413cdaaf75besewardj
8290c2cb623cca372a2b42b073121c7413cdaaf75besewardj/* 80 and 64-bit floating point formats:
8300c2cb623cca372a2b42b073121c7413cdaaf75besewardj
8310c2cb623cca372a2b42b073121c7413cdaaf75besewardj   80-bit:
8320c2cb623cca372a2b42b073121c7413cdaaf75besewardj
8330c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  0       0-------0      zero
8340c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  0       0X------X      denormals
8350c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  1-7FFE  1X------X      normals (all normals have leading 1)
8360c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  7FFF    10------0      infinity
8370c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  7FFF    10X-----X      snan
8380c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  7FFF    11X-----X      qnan
8390c2cb623cca372a2b42b073121c7413cdaaf75besewardj
8400c2cb623cca372a2b42b073121c7413cdaaf75besewardj   S is the sign bit.  For runs X----X, at least one of the Xs must be
8410c2cb623cca372a2b42b073121c7413cdaaf75besewardj   nonzero.  Exponent is 15 bits, fractional part is 63 bits, and
8420c2cb623cca372a2b42b073121c7413cdaaf75besewardj   there is an explicitly represented leading 1, and a sign bit,
8430c2cb623cca372a2b42b073121c7413cdaaf75besewardj   giving 80 in total.
8440c2cb623cca372a2b42b073121c7413cdaaf75besewardj
8450c2cb623cca372a2b42b073121c7413cdaaf75besewardj   64-bit avoids the confusion of an explicitly represented leading 1
8460c2cb623cca372a2b42b073121c7413cdaaf75besewardj   and so is simpler:
8470c2cb623cca372a2b42b073121c7413cdaaf75besewardj
8480c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  0      0------0   zero
8490c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  0      X------X   denormals
8500c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  1-7FE  any        normals
8510c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  7FF    0------0   infinity
8520c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  7FF    0X-----X   snan
8530c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  7FF    1X-----X   qnan
8540c2cb623cca372a2b42b073121c7413cdaaf75besewardj
8550c2cb623cca372a2b42b073121c7413cdaaf75besewardj   Exponent is 11 bits, fractional part is 52 bits, and there is a
8560c2cb623cca372a2b42b073121c7413cdaaf75besewardj   sign bit, giving 64 in total.
8570c2cb623cca372a2b42b073121c7413cdaaf75besewardj*/
8580c2cb623cca372a2b42b073121c7413cdaaf75besewardj
859c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardjstatic inline Bool host_is_little_endian ( void )
860c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj{
861c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   UInt x = 0x76543210;
862c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   UChar* p = (UChar*)(&x);
863c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   return (*p == 0x10);
864c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj}
865c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
8669aebb0c3f7a7f43313786826f31402f2b733badfsewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
86717442fe8094d0f82266e5a05509f62cac8f7539esewardjstatic UInt calculate_FXAM ( UInt tag, ULong dbl )
868c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj{
869c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   Bool   mantissaIsZero;
870c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   Int    bexp;
871c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   UChar  sign;
872c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   UInt   c1;
873c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   UChar* f64;
874c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
875f5e36670bf70ac2d23f6336d7f46889bf996cfdfsewardj   if (!host_is_little_endian()) {
876c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      vassert(0);
877c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   }
878c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
879c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   /* vex_printf("calculate_FXAM ( %d, %llx ) .. ", tag, dbl ); */
880c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
881c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   f64  = (UChar*)(&dbl);
882c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   sign = (f64[7] >> 7) & 1;
883c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
884c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   /* First off, if the tag indicates the register was empty,
885c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      return 1,0,sign,1 */
886c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   if (tag == 0) {
887c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      /* vex_printf("Empty\n"); */
888c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      return FC_MASK_C3 | 0 | sign | FC_MASK_C0;
889c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   }
890c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
891c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   bexp = (f64[7] << 4) | ((f64[6] >> 4) & 0x0F);
892c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   bexp &= 0x7FF;
893c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
894c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   c1 = ((UInt)sign) << 9;
895c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
896c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   mantissaIsZero
897c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      = (f64[6] & 0x0F) == 0
898c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj        && (f64[5] | f64[4] | f64[3] | f64[2] | f64[1] | f64[0]) == 0;
899c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
900c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   /* If both exponent and mantissa are zero, the value is zero.
901c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      Return 1,0,sign,0. */
902c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   if (bexp == 0 && mantissaIsZero) {
903c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      /* vex_printf("Zero\n"); */
904c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      return FC_MASK_C3 | 0 | sign | 0;
905c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   }
906c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
907c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   /* If exponent is zero but mantissa isn't, it's a denormal.
908c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      Return 1,1,sign,0. */
909c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   if (bexp == 0 && !mantissaIsZero) {
910c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      /* vex_printf("Denormal\n"); */
911c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      return FC_MASK_C3 | FC_MASK_C2 | sign | 0;
912c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   }
913c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
914c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   /* If the exponent is 7FF and the mantissa is zero, this is an infinity.
915c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      Return 0,1,sign,1. */
916c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   if (bexp == 0x7FF && mantissaIsZero) {
917c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      /* vex_printf("Inf\n"); */
918c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      return 0 | FC_MASK_C2 | sign | FC_MASK_C0;
919c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   }
920c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
921c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   /* If the exponent is 7FF and the mantissa isn't zero, this is a NaN.
922c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      Return 0,0,sign,1. */
923c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   if (bexp == 0x7FF && !mantissaIsZero) {
924c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      /* vex_printf("NaN\n"); */
925c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      return 0 | 0 | sign | FC_MASK_C0;
926c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   }
927c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
928c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   /* Uh, ok, we give up.  It must be a normal finite number.
929c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      Return 0,1,sign,0.
930c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   */
931c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   /* vex_printf("normal\n"); */
932c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   return 0 | FC_MASK_C2 | sign | 0;
933c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj}
934c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
9350c2cb623cca372a2b42b073121c7413cdaaf75besewardj
9360c2cb623cca372a2b42b073121c7413cdaaf75besewardj/* Convert a IEEE754 double (64-bit) into an x87 extended double
9370c2cb623cca372a2b42b073121c7413cdaaf75besewardj   (80-bit), mimicing the hardware fairly closely.  Both numbers are
9380c2cb623cca372a2b42b073121c7413cdaaf75besewardj   stored little-endian.  Limitations, all of which could be fixed,
9390c2cb623cca372a2b42b073121c7413cdaaf75besewardj   given some level of hassle:
9400c2cb623cca372a2b42b073121c7413cdaaf75besewardj
9410c2cb623cca372a2b42b073121c7413cdaaf75besewardj   * Does not handle double precision denormals.  As a result, values
9420c2cb623cca372a2b42b073121c7413cdaaf75besewardj     with magnitudes less than 1e-308 are flushed to zero when they
9430c2cb623cca372a2b42b073121c7413cdaaf75besewardj     need not be.
9440c2cb623cca372a2b42b073121c7413cdaaf75besewardj
9450c2cb623cca372a2b42b073121c7413cdaaf75besewardj   * Identity of NaNs is not preserved.
9460c2cb623cca372a2b42b073121c7413cdaaf75besewardj
9470c2cb623cca372a2b42b073121c7413cdaaf75besewardj   See comments in the code for more details.
9480c2cb623cca372a2b42b073121c7413cdaaf75besewardj*/
9490c2cb623cca372a2b42b073121c7413cdaaf75besewardjstatic void convert_f64le_to_f80le ( /*IN*/UChar* f64, /*OUT*/UChar* f80 )
9500c2cb623cca372a2b42b073121c7413cdaaf75besewardj{
9510c2cb623cca372a2b42b073121c7413cdaaf75besewardj   Bool  isInf;
9520c2cb623cca372a2b42b073121c7413cdaaf75besewardj   Int   bexp;
9530c2cb623cca372a2b42b073121c7413cdaaf75besewardj   UChar sign;
9540c2cb623cca372a2b42b073121c7413cdaaf75besewardj
9550c2cb623cca372a2b42b073121c7413cdaaf75besewardj   sign = (f64[7] >> 7) & 1;
9560c2cb623cca372a2b42b073121c7413cdaaf75besewardj   bexp = (f64[7] << 4) | ((f64[6] >> 4) & 0x0F);
9570c2cb623cca372a2b42b073121c7413cdaaf75besewardj   bexp &= 0x7FF;
9580c2cb623cca372a2b42b073121c7413cdaaf75besewardj
9590c2cb623cca372a2b42b073121c7413cdaaf75besewardj   /* If the exponent is zero, either we have a zero or a denormal.
9600c2cb623cca372a2b42b073121c7413cdaaf75besewardj      Produce a zero.  This is a hack in that it forces denormals to
9610c2cb623cca372a2b42b073121c7413cdaaf75besewardj      zero.  Could do better. */
9620c2cb623cca372a2b42b073121c7413cdaaf75besewardj   if (bexp == 0) {
9630c2cb623cca372a2b42b073121c7413cdaaf75besewardj      f80[9] = sign << 7;
9640c2cb623cca372a2b42b073121c7413cdaaf75besewardj      f80[8] = f80[7] = f80[6] = f80[5] = f80[4]
9650c2cb623cca372a2b42b073121c7413cdaaf75besewardj             = f80[3] = f80[2] = f80[1] = f80[0] = 0;
9660c2cb623cca372a2b42b073121c7413cdaaf75besewardj      return;
9670c2cb623cca372a2b42b073121c7413cdaaf75besewardj   }
9680c2cb623cca372a2b42b073121c7413cdaaf75besewardj
9690c2cb623cca372a2b42b073121c7413cdaaf75besewardj   /* If the exponent is 7FF, this is either an Infinity, a SNaN or
9700c2cb623cca372a2b42b073121c7413cdaaf75besewardj      QNaN, as determined by examining bits 51:0, thus:
9710c2cb623cca372a2b42b073121c7413cdaaf75besewardj          0  ... 0    Inf
9720c2cb623cca372a2b42b073121c7413cdaaf75besewardj          0X ... X    SNaN
9730c2cb623cca372a2b42b073121c7413cdaaf75besewardj          1X ... X    QNaN
9740c2cb623cca372a2b42b073121c7413cdaaf75besewardj      where at least one of the Xs is not zero.
9750c2cb623cca372a2b42b073121c7413cdaaf75besewardj   */
9760c2cb623cca372a2b42b073121c7413cdaaf75besewardj   if (bexp == 0x7FF) {
9770c2cb623cca372a2b42b073121c7413cdaaf75besewardj      isInf = (f64[6] & 0x0F) == 0
9780c2cb623cca372a2b42b073121c7413cdaaf75besewardj              && f64[5] == 0 && f64[4] == 0 && f64[3] == 0
9790c2cb623cca372a2b42b073121c7413cdaaf75besewardj              && f64[2] == 0 && f64[1] == 0 && f64[0] == 0;
9800c2cb623cca372a2b42b073121c7413cdaaf75besewardj      if (isInf) {
9810c2cb623cca372a2b42b073121c7413cdaaf75besewardj         /* Produce an appropriately signed infinity:
9820c2cb623cca372a2b42b073121c7413cdaaf75besewardj            S 1--1 (15)  1  0--0 (63)
9830c2cb623cca372a2b42b073121c7413cdaaf75besewardj         */
9840c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f80[9] = (sign << 7) | 0x7F;
9850c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f80[8] = 0xFF;
9860c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f80[7] = 0x80;
9870c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f80[6] = f80[5] = f80[4] = f80[3]
9880c2cb623cca372a2b42b073121c7413cdaaf75besewardj                = f80[2] = f80[1] = f80[0] = 0;
9890c2cb623cca372a2b42b073121c7413cdaaf75besewardj         return;
9900c2cb623cca372a2b42b073121c7413cdaaf75besewardj      }
9910c2cb623cca372a2b42b073121c7413cdaaf75besewardj      /* So it's either a QNaN or SNaN.  Distinguish by considering
9920c2cb623cca372a2b42b073121c7413cdaaf75besewardj         bit 51.  Note, this destroys all the trailing bits
9930c2cb623cca372a2b42b073121c7413cdaaf75besewardj         (identity?) of the NaN.  IEEE754 doesn't require preserving
9940c2cb623cca372a2b42b073121c7413cdaaf75besewardj         these (it only requires that there be one QNaN value and one
9950c2cb623cca372a2b42b073121c7413cdaaf75besewardj         SNaN value), but x87 does seem to have some ability to
9960c2cb623cca372a2b42b073121c7413cdaaf75besewardj         preserve them.  Anyway, here, the NaN's identity is
9970c2cb623cca372a2b42b073121c7413cdaaf75besewardj         destroyed.  Could be improved. */
9980c2cb623cca372a2b42b073121c7413cdaaf75besewardj      if (f64[6] & 8) {
9990c2cb623cca372a2b42b073121c7413cdaaf75besewardj         /* QNaN.  Make a QNaN:
10000c2cb623cca372a2b42b073121c7413cdaaf75besewardj            S 1--1 (15)  1  1--1 (63)
10010c2cb623cca372a2b42b073121c7413cdaaf75besewardj         */
10020c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f80[9] = (sign << 7) | 0x7F;
10030c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f80[8] = 0xFF;
10040c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f80[7] = 0xFF;
10050c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f80[6] = f80[5] = f80[4] = f80[3]
10060c2cb623cca372a2b42b073121c7413cdaaf75besewardj                = f80[2] = f80[1] = f80[0] = 0xFF;
10070c2cb623cca372a2b42b073121c7413cdaaf75besewardj      } else {
10080c2cb623cca372a2b42b073121c7413cdaaf75besewardj         /* SNaN.  Make a SNaN:
10090c2cb623cca372a2b42b073121c7413cdaaf75besewardj            S 1--1 (15)  0  1--1 (63)
10100c2cb623cca372a2b42b073121c7413cdaaf75besewardj         */
10110c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f80[9] = (sign << 7) | 0x7F;
10120c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f80[8] = 0xFF;
10130c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f80[7] = 0x7F;
10140c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f80[6] = f80[5] = f80[4] = f80[3]
10150c2cb623cca372a2b42b073121c7413cdaaf75besewardj                = f80[2] = f80[1] = f80[0] = 0xFF;
10160c2cb623cca372a2b42b073121c7413cdaaf75besewardj      }
10170c2cb623cca372a2b42b073121c7413cdaaf75besewardj      return;
10180c2cb623cca372a2b42b073121c7413cdaaf75besewardj   }
10190c2cb623cca372a2b42b073121c7413cdaaf75besewardj
10200c2cb623cca372a2b42b073121c7413cdaaf75besewardj   /* It's not a zero, denormal, infinity or nan.  So it must be a
10210c2cb623cca372a2b42b073121c7413cdaaf75besewardj      normalised number.  Rebias the exponent and build the new
10220c2cb623cca372a2b42b073121c7413cdaaf75besewardj      number.  */
10230c2cb623cca372a2b42b073121c7413cdaaf75besewardj   bexp += (16383 - 1023);
10240c2cb623cca372a2b42b073121c7413cdaaf75besewardj
10250c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f80[9] = (sign << 7) | ((bexp >> 8) & 0xFF);
10260c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f80[8] = bexp & 0xFF;
10270c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f80[7] = (1 << 7) | ((f64[6] << 3) & 0x78) | ((f64[5] >> 5) & 7);
10280c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f80[6] = ((f64[5] << 3) & 0xF8) | ((f64[4] >> 5) & 7);
10290c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f80[5] = ((f64[4] << 3) & 0xF8) | ((f64[3] >> 5) & 7);
10300c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f80[4] = ((f64[3] << 3) & 0xF8) | ((f64[2] >> 5) & 7);
10310c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f80[3] = ((f64[2] << 3) & 0xF8) | ((f64[1] >> 5) & 7);
10320c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f80[2] = ((f64[1] << 3) & 0xF8) | ((f64[0] >> 5) & 7);
10330c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f80[1] = ((f64[0] << 3) & 0xF8);
10340c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f80[0] = 0;
10350c2cb623cca372a2b42b073121c7413cdaaf75besewardj}
10360c2cb623cca372a2b42b073121c7413cdaaf75besewardj
10370c2cb623cca372a2b42b073121c7413cdaaf75besewardj
10380c2cb623cca372a2b42b073121c7413cdaaf75besewardj/////////////////////////////////////////////////////////////////
10390c2cb623cca372a2b42b073121c7413cdaaf75besewardj
10400c2cb623cca372a2b42b073121c7413cdaaf75besewardj/* Convert a x87 extended double (80-bit) into an IEEE 754 double
10410c2cb623cca372a2b42b073121c7413cdaaf75besewardj   (64-bit), mimicing the hardware fairly closely.  Both numbers are
10420c2cb623cca372a2b42b073121c7413cdaaf75besewardj   stored little-endian.  Limitations, all of which could be fixed,
10430c2cb623cca372a2b42b073121c7413cdaaf75besewardj   given some level of hassle:
10440c2cb623cca372a2b42b073121c7413cdaaf75besewardj
10450c2cb623cca372a2b42b073121c7413cdaaf75besewardj   * Does not create double precision denormals.  As a result, values
10460c2cb623cca372a2b42b073121c7413cdaaf75besewardj     with magnitudes less than 1e-308 are flushed to zero when they
10470c2cb623cca372a2b42b073121c7413cdaaf75besewardj     need not be.
10480c2cb623cca372a2b42b073121c7413cdaaf75besewardj
10490c2cb623cca372a2b42b073121c7413cdaaf75besewardj   * Rounding following truncation could be a bit better.
10500c2cb623cca372a2b42b073121c7413cdaaf75besewardj
10510c2cb623cca372a2b42b073121c7413cdaaf75besewardj   * Identity of NaNs is not preserved.
10520c2cb623cca372a2b42b073121c7413cdaaf75besewardj
10530c2cb623cca372a2b42b073121c7413cdaaf75besewardj   See comments in the code for more details.
10540c2cb623cca372a2b42b073121c7413cdaaf75besewardj*/
10550c2cb623cca372a2b42b073121c7413cdaaf75besewardjstatic void convert_f80le_to_f64le ( /*IN*/UChar* f80, /*OUT*/UChar* f64 )
10560c2cb623cca372a2b42b073121c7413cdaaf75besewardj{
10570c2cb623cca372a2b42b073121c7413cdaaf75besewardj   Bool  isInf;
10580c2cb623cca372a2b42b073121c7413cdaaf75besewardj   Int   bexp;
10590c2cb623cca372a2b42b073121c7413cdaaf75besewardj   UChar sign;
10600c2cb623cca372a2b42b073121c7413cdaaf75besewardj
10610c2cb623cca372a2b42b073121c7413cdaaf75besewardj   sign = (f80[9] >> 7) & 1;
10620c2cb623cca372a2b42b073121c7413cdaaf75besewardj   bexp = (((UInt)f80[9]) << 8) | (UInt)f80[8];
10630c2cb623cca372a2b42b073121c7413cdaaf75besewardj   bexp &= 0x7FFF;
10640c2cb623cca372a2b42b073121c7413cdaaf75besewardj
10650c2cb623cca372a2b42b073121c7413cdaaf75besewardj   /* If the exponent is zero, either we have a zero or a denormal.
10660c2cb623cca372a2b42b073121c7413cdaaf75besewardj      But an extended precision denormal becomes a double precision
10670c2cb623cca372a2b42b073121c7413cdaaf75besewardj      zero, so in either case, just produce the appropriately signed
10680c2cb623cca372a2b42b073121c7413cdaaf75besewardj      zero. */
10690c2cb623cca372a2b42b073121c7413cdaaf75besewardj   if (bexp == 0) {
10700c2cb623cca372a2b42b073121c7413cdaaf75besewardj      f64[7] = sign << 7;
10710c2cb623cca372a2b42b073121c7413cdaaf75besewardj      f64[6] = f64[5] = f64[4] = f64[3] = f64[2] = f64[1] = f64[0] = 0;
10720c2cb623cca372a2b42b073121c7413cdaaf75besewardj      return;
10730c2cb623cca372a2b42b073121c7413cdaaf75besewardj   }
10740c2cb623cca372a2b42b073121c7413cdaaf75besewardj
10750c2cb623cca372a2b42b073121c7413cdaaf75besewardj   /* If the exponent is 7FFF, this is either an Infinity, a SNaN or
10760c2cb623cca372a2b42b073121c7413cdaaf75besewardj      QNaN, as determined by examining bits 62:0, thus:
10770c2cb623cca372a2b42b073121c7413cdaaf75besewardj          0  ... 0    Inf
10780c2cb623cca372a2b42b073121c7413cdaaf75besewardj          0X ... X    SNaN
10790c2cb623cca372a2b42b073121c7413cdaaf75besewardj          1X ... X    QNaN
10800c2cb623cca372a2b42b073121c7413cdaaf75besewardj      where at least one of the Xs is not zero.
10810c2cb623cca372a2b42b073121c7413cdaaf75besewardj   */
10820c2cb623cca372a2b42b073121c7413cdaaf75besewardj   if (bexp == 0x7FFF) {
10830c2cb623cca372a2b42b073121c7413cdaaf75besewardj      isInf = (f80[7] & 0x7F) == 0
10840c2cb623cca372a2b42b073121c7413cdaaf75besewardj              && f80[6] == 0 && f80[5] == 0 && f80[4] == 0
10850c2cb623cca372a2b42b073121c7413cdaaf75besewardj              && f80[3] == 0 && f80[2] == 0 && f80[1] == 0 && f80[0] == 0;
10860c2cb623cca372a2b42b073121c7413cdaaf75besewardj      if (isInf) {
10870c2cb623cca372a2b42b073121c7413cdaaf75besewardj         if (0 == (f80[7] & 0x80))
10880c2cb623cca372a2b42b073121c7413cdaaf75besewardj            goto wierd_NaN;
10890c2cb623cca372a2b42b073121c7413cdaaf75besewardj         /* Produce an appropriately signed infinity:
10900c2cb623cca372a2b42b073121c7413cdaaf75besewardj            S 1--1 (11)  0--0 (52)
10910c2cb623cca372a2b42b073121c7413cdaaf75besewardj         */
10920c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f64[7] = (sign << 7) | 0x7F;
10930c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f64[6] = 0xF0;
10940c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f64[5] = f64[4] = f64[3] = f64[2] = f64[1] = f64[0] = 0;
10950c2cb623cca372a2b42b073121c7413cdaaf75besewardj         return;
10960c2cb623cca372a2b42b073121c7413cdaaf75besewardj      }
10970c2cb623cca372a2b42b073121c7413cdaaf75besewardj      /* So it's either a QNaN or SNaN.  Distinguish by considering
10980c2cb623cca372a2b42b073121c7413cdaaf75besewardj         bit 62.  Note, this destroys all the trailing bits
10990c2cb623cca372a2b42b073121c7413cdaaf75besewardj         (identity?) of the NaN.  IEEE754 doesn't require preserving
11000c2cb623cca372a2b42b073121c7413cdaaf75besewardj         these (it only requires that there be one QNaN value and one
11010c2cb623cca372a2b42b073121c7413cdaaf75besewardj         SNaN value), but x87 does seem to have some ability to
11020c2cb623cca372a2b42b073121c7413cdaaf75besewardj         preserve them.  Anyway, here, the NaN's identity is
11030c2cb623cca372a2b42b073121c7413cdaaf75besewardj         destroyed.  Could be improved. */
11040c2cb623cca372a2b42b073121c7413cdaaf75besewardj      if (f80[8] & 0x40) {
11050c2cb623cca372a2b42b073121c7413cdaaf75besewardj         /* QNaN.  Make a QNaN:
11060c2cb623cca372a2b42b073121c7413cdaaf75besewardj            S 1--1 (11)  1  1--1 (51)
11070c2cb623cca372a2b42b073121c7413cdaaf75besewardj         */
11080c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f64[7] = (sign << 7) | 0x7F;
11090c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f64[6] = 0xFF;
11100c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f64[5] = f64[4] = f64[3] = f64[2] = f64[1] = f64[0] = 0xFF;
11110c2cb623cca372a2b42b073121c7413cdaaf75besewardj      } else {
11120c2cb623cca372a2b42b073121c7413cdaaf75besewardj         /* SNaN.  Make a SNaN:
11130c2cb623cca372a2b42b073121c7413cdaaf75besewardj            S 1--1 (11)  0  1--1 (51)
11140c2cb623cca372a2b42b073121c7413cdaaf75besewardj         */
11150c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f64[7] = (sign << 7) | 0x7F;
11160c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f64[6] = 0xF7;
11170c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f64[5] = f64[4] = f64[3] = f64[2] = f64[1] = f64[0] = 0xFF;
11180c2cb623cca372a2b42b073121c7413cdaaf75besewardj      }
11190c2cb623cca372a2b42b073121c7413cdaaf75besewardj      return;
11200c2cb623cca372a2b42b073121c7413cdaaf75besewardj   }
11210c2cb623cca372a2b42b073121c7413cdaaf75besewardj
11220c2cb623cca372a2b42b073121c7413cdaaf75besewardj   /* If it's not a Zero, NaN or Inf, and the integer part (bit 62) is
11230c2cb623cca372a2b42b073121c7413cdaaf75besewardj      zero, the x87 FPU appears to consider the number denormalised
11240c2cb623cca372a2b42b073121c7413cdaaf75besewardj      and converts it to a QNaN. */
11250c2cb623cca372a2b42b073121c7413cdaaf75besewardj   if (0 == (f80[7] & 0x80)) {
11260c2cb623cca372a2b42b073121c7413cdaaf75besewardj      wierd_NaN:
11270c2cb623cca372a2b42b073121c7413cdaaf75besewardj      /* Strange hardware QNaN:
11280c2cb623cca372a2b42b073121c7413cdaaf75besewardj         S 1--1 (11)  1  0--0 (51)
11290c2cb623cca372a2b42b073121c7413cdaaf75besewardj      */
11300c2cb623cca372a2b42b073121c7413cdaaf75besewardj      /* On a PIII, these QNaNs always appear with sign==1.  I have
11310c2cb623cca372a2b42b073121c7413cdaaf75besewardj         no idea why. */
11320c2cb623cca372a2b42b073121c7413cdaaf75besewardj      f64[7] = (1 /*sign*/ << 7) | 0x7F;
11330c2cb623cca372a2b42b073121c7413cdaaf75besewardj      f64[6] = 0xF8;
11340c2cb623cca372a2b42b073121c7413cdaaf75besewardj      f64[5] = f64[4] = f64[3] = f64[2] = f64[1] = f64[0] = 0;
11350c2cb623cca372a2b42b073121c7413cdaaf75besewardj      return;
11360c2cb623cca372a2b42b073121c7413cdaaf75besewardj   }
11370c2cb623cca372a2b42b073121c7413cdaaf75besewardj
11380c2cb623cca372a2b42b073121c7413cdaaf75besewardj   /* It's not a zero, denormal, infinity or nan.  So it must be a
11390c2cb623cca372a2b42b073121c7413cdaaf75besewardj      normalised number.  Rebias the exponent and consider. */
11400c2cb623cca372a2b42b073121c7413cdaaf75besewardj   bexp -= (16383 - 1023);
11410c2cb623cca372a2b42b073121c7413cdaaf75besewardj   if (bexp >= 0x7FF) {
11420c2cb623cca372a2b42b073121c7413cdaaf75besewardj      /* It's too big for a double.  Construct an infinity. */
11430c2cb623cca372a2b42b073121c7413cdaaf75besewardj      f64[7] = (sign << 7) | 0x7F;
11440c2cb623cca372a2b42b073121c7413cdaaf75besewardj      f64[6] = 0xF0;
11450c2cb623cca372a2b42b073121c7413cdaaf75besewardj      f64[5] = f64[4] = f64[3] = f64[2] = f64[1] = f64[0] = 0;
11460c2cb623cca372a2b42b073121c7413cdaaf75besewardj      return;
11470c2cb623cca372a2b42b073121c7413cdaaf75besewardj   }
11480c2cb623cca372a2b42b073121c7413cdaaf75besewardj
11490c2cb623cca372a2b42b073121c7413cdaaf75besewardj   if (bexp < 0) {
11500c2cb623cca372a2b42b073121c7413cdaaf75besewardj   /* It's too small for a double.  Construct a zero.  Note, this
11510c2cb623cca372a2b42b073121c7413cdaaf75besewardj      is a kludge since we could conceivably create a
11520c2cb623cca372a2b42b073121c7413cdaaf75besewardj      denormalised number for bexp in -1 to -51, but we don't
11530c2cb623cca372a2b42b073121c7413cdaaf75besewardj      bother.  This means the conversion flushes values
11540c2cb623cca372a2b42b073121c7413cdaaf75besewardj      approximately in the range 1e-309 to 1e-324 ish to zero
11550c2cb623cca372a2b42b073121c7413cdaaf75besewardj      when it doesn't actually need to.  This could be
11560c2cb623cca372a2b42b073121c7413cdaaf75besewardj      improved. */
11570c2cb623cca372a2b42b073121c7413cdaaf75besewardj      f64[7] = sign << 7;
11580c2cb623cca372a2b42b073121c7413cdaaf75besewardj      f64[6] = f64[5] = f64[4] = f64[3] = f64[2] = f64[1] = f64[0] = 0;
11590c2cb623cca372a2b42b073121c7413cdaaf75besewardj      return;
11600c2cb623cca372a2b42b073121c7413cdaaf75besewardj   }
11610c2cb623cca372a2b42b073121c7413cdaaf75besewardj
11620c2cb623cca372a2b42b073121c7413cdaaf75besewardj   /* Ok, it's a normalised number which is representable as a double.
11630c2cb623cca372a2b42b073121c7413cdaaf75besewardj      Copy the exponent and mantissa into place. */
11640c2cb623cca372a2b42b073121c7413cdaaf75besewardj   /*
11650c2cb623cca372a2b42b073121c7413cdaaf75besewardj   for (i = 0; i < 52; i++)
11660c2cb623cca372a2b42b073121c7413cdaaf75besewardj      write_bit_array ( f64,
11670c2cb623cca372a2b42b073121c7413cdaaf75besewardj                        i,
11680c2cb623cca372a2b42b073121c7413cdaaf75besewardj                        read_bit_array ( f80, i+11 ) );
11690c2cb623cca372a2b42b073121c7413cdaaf75besewardj   */
11700c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f64[0] = (f80[1] >> 3) | (f80[2] << 5);
11710c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f64[1] = (f80[2] >> 3) | (f80[3] << 5);
11720c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f64[2] = (f80[3] >> 3) | (f80[4] << 5);
11730c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f64[3] = (f80[4] >> 3) | (f80[5] << 5);
11740c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f64[4] = (f80[5] >> 3) | (f80[6] << 5);
11750c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f64[5] = (f80[6] >> 3) | (f80[7] << 5);
11760c2cb623cca372a2b42b073121c7413cdaaf75besewardj
11770c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f64[6] = ((bexp << 4) & 0xF0) | ((f80[7] >> 3) & 0x0F);
11780c2cb623cca372a2b42b073121c7413cdaaf75besewardj
11790c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f64[7] = (sign << 7) | ((bexp >> 4) & 0x7F);
11800c2cb623cca372a2b42b073121c7413cdaaf75besewardj
11810c2cb623cca372a2b42b073121c7413cdaaf75besewardj   /* Now consider any rounding that needs to happen as a result of
11820c2cb623cca372a2b42b073121c7413cdaaf75besewardj      truncating the mantissa. */
11830c2cb623cca372a2b42b073121c7413cdaaf75besewardj   if (f80[1] & 4) /* read_bit_array(f80, 10) == 1) */ {
11840c2cb623cca372a2b42b073121c7413cdaaf75besewardj      /* Round upwards.  This is a kludge.  Once in every 64k
11850c2cb623cca372a2b42b073121c7413cdaaf75besewardj         roundings (statistically) the bottom two bytes are both 0xFF
11860c2cb623cca372a2b42b073121c7413cdaaf75besewardj         and so we don't round at all.  Could be improved. */
11870c2cb623cca372a2b42b073121c7413cdaaf75besewardj      if (f64[0] != 0xFF) {
11880c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f64[0]++;
11890c2cb623cca372a2b42b073121c7413cdaaf75besewardj      }
11900c2cb623cca372a2b42b073121c7413cdaaf75besewardj      else
11910c2cb623cca372a2b42b073121c7413cdaaf75besewardj      if (f64[0] == 0xFF && f64[1] != 0xFF) {
11920c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f64[0] = 0;
11930c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f64[1]++;
11940c2cb623cca372a2b42b073121c7413cdaaf75besewardj      }
11950c2cb623cca372a2b42b073121c7413cdaaf75besewardj      /* else we don't round, but we should. */
11960c2cb623cca372a2b42b073121c7413cdaaf75besewardj   }
11970c2cb623cca372a2b42b073121c7413cdaaf75besewardj}
11980c2cb623cca372a2b42b073121c7413cdaaf75besewardj
119917442fe8094d0f82266e5a05509f62cac8f7539esewardj/* CALLED FROM GENERATED CODE */
120017442fe8094d0f82266e5a05509f62cac8f7539esewardj/* DIRTY HELPER (reads guest memory) */
12017cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardjstatic ULong loadF80le ( VexGuestX86State* st, UInt addrU )
120217442fe8094d0f82266e5a05509f62cac8f7539esewardj{
120317442fe8094d0f82266e5a05509f62cac8f7539esewardj   ULong f64;
120417442fe8094d0f82266e5a05509f62cac8f7539esewardj   convert_f80le_to_f64le ( (UChar*)addrU, (UChar*)&f64 );
120517442fe8094d0f82266e5a05509f62cac8f7539esewardj   return f64;
120617442fe8094d0f82266e5a05509f62cac8f7539esewardj}
120717442fe8094d0f82266e5a05509f62cac8f7539esewardj
120817442fe8094d0f82266e5a05509f62cac8f7539esewardj/* CALLED FROM GENERATED CODE */
120917442fe8094d0f82266e5a05509f62cac8f7539esewardj/* DIRTY HELPER (writes guest memory) */
12107cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardjstatic void storeF80le ( VexGuestX86State* st, UInt addrU, ULong f64 )
121117442fe8094d0f82266e5a05509f62cac8f7539esewardj{
121217442fe8094d0f82266e5a05509f62cac8f7539esewardj   convert_f64le_to_f80le( (UChar*)&f64, (UChar*)addrU );
121317442fe8094d0f82266e5a05509f62cac8f7539esewardj}
121417442fe8094d0f82266e5a05509f62cac8f7539esewardj
12150c2cb623cca372a2b42b073121c7413cdaaf75besewardj
12160c2cb623cca372a2b42b073121c7413cdaaf75besewardj/*----------------------------------------------*/
12170c2cb623cca372a2b42b073121c7413cdaaf75besewardj/*--- The exported fns ..                    ---*/
12180c2cb623cca372a2b42b073121c7413cdaaf75besewardj/*----------------------------------------------*/
12190c2cb623cca372a2b42b073121c7413cdaaf75besewardj
12200c2cb623cca372a2b42b073121c7413cdaaf75besewardj/* Layout of the real x87 state. */
12210c2cb623cca372a2b42b073121c7413cdaaf75besewardj
12220c2cb623cca372a2b42b073121c7413cdaaf75besewardjtypedef
12230c2cb623cca372a2b42b073121c7413cdaaf75besewardj   struct {
12240c2cb623cca372a2b42b073121c7413cdaaf75besewardj      UShort env[14];
12250c2cb623cca372a2b42b073121c7413cdaaf75besewardj      UChar  reg[80];
12260c2cb623cca372a2b42b073121c7413cdaaf75besewardj   }
12270c2cb623cca372a2b42b073121c7413cdaaf75besewardj   Fpu_State;
12280c2cb623cca372a2b42b073121c7413cdaaf75besewardj
12290c2cb623cca372a2b42b073121c7413cdaaf75besewardj/* Offsets, in 16-bit ints, into the FPU environment (env) area. */
12300c2cb623cca372a2b42b073121c7413cdaaf75besewardj#define FP_ENV_CTRL   0
12310c2cb623cca372a2b42b073121c7413cdaaf75besewardj#define FP_ENV_STAT   2
12320c2cb623cca372a2b42b073121c7413cdaaf75besewardj#define FP_ENV_TAG    4
12330c2cb623cca372a2b42b073121c7413cdaaf75besewardj#define FP_ENV_IP     6 /* and 7 */
12340c2cb623cca372a2b42b073121c7413cdaaf75besewardj#define FP_ENV_CS     8
12350c2cb623cca372a2b42b073121c7413cdaaf75besewardj#define FP_ENV_OPOFF  10 /* and 11 */
12360c2cb623cca372a2b42b073121c7413cdaaf75besewardj#define FP_ENV_OPSEL  12
12370c2cb623cca372a2b42b073121c7413cdaaf75besewardj#define FP_REG(ii)    (10*(7-(ii)))
12380c2cb623cca372a2b42b073121c7413cdaaf75besewardj
12390c2cb623cca372a2b42b073121c7413cdaaf75besewardj
12400c2cb623cca372a2b42b073121c7413cdaaf75besewardj/* VISIBLE TO LIBVEX CLIENT */
124176bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardjvoid LibVEX_GuestX86_put_x87 ( /*IN*/UChar* x87_state,
124276bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj                               /*OUT*/VexGuestX86State* vex_state )
12430c2cb623cca372a2b42b073121c7413cdaaf75besewardj{
12440c2cb623cca372a2b42b073121c7413cdaaf75besewardj   Int        r;
12450c2cb623cca372a2b42b073121c7413cdaaf75besewardj   UInt       tag;
1246f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj   Double*    vexRegs = (Double*)(&vex_state->guest_FPREG[0]);
1247f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj   UChar*     vexTags = (UChar*)(&vex_state->guest_FPTAG[0]);
12480c2cb623cca372a2b42b073121c7413cdaaf75besewardj   Fpu_State* x87     = (Fpu_State*)x87_state;
12490c2cb623cca372a2b42b073121c7413cdaaf75besewardj   UInt       ftop    = (x87->env[FP_ENV_STAT] >> 11) & 7;
12500c2cb623cca372a2b42b073121c7413cdaaf75besewardj   UInt       tagw    = x87->env[FP_ENV_TAG];
12516e0dbda4f7ea53dd29996d4d429d3c5c92ee3640sewardj   UInt       fpucw   = x87->env[FP_ENV_CTRL];
1252c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   UInt       c3210   = x87->env[FP_ENV_STAT] & 0x4700;
12530c2cb623cca372a2b42b073121c7413cdaaf75besewardj
12540c2cb623cca372a2b42b073121c7413cdaaf75besewardj   /* Copy registers and tags */
12550c2cb623cca372a2b42b073121c7413cdaaf75besewardj   for (r = 0; r < 8; r++) {
12560c2cb623cca372a2b42b073121c7413cdaaf75besewardj      tag = (tagw >> (2*r)) & 3;
12570c2cb623cca372a2b42b073121c7413cdaaf75besewardj      if (tag == 3) {
12580c2cb623cca372a2b42b073121c7413cdaaf75besewardj         /* register is empty */
12590c2cb623cca372a2b42b073121c7413cdaaf75besewardj         vexRegs[r] = 0.0;
12600c2cb623cca372a2b42b073121c7413cdaaf75besewardj         vexTags[r] = 0;
12610c2cb623cca372a2b42b073121c7413cdaaf75besewardj      } else {
12620c2cb623cca372a2b42b073121c7413cdaaf75besewardj         /* register is non-empty */
12630c2cb623cca372a2b42b073121c7413cdaaf75besewardj         convert_f80le_to_f64le( &x87->reg[FP_REG(r)], (UChar*)&vexRegs[r] );
12640c2cb623cca372a2b42b073121c7413cdaaf75besewardj         vexTags[r] = 1;
12650c2cb623cca372a2b42b073121c7413cdaaf75besewardj      }
12660c2cb623cca372a2b42b073121c7413cdaaf75besewardj   }
12670c2cb623cca372a2b42b073121c7413cdaaf75besewardj
12680c2cb623cca372a2b42b073121c7413cdaaf75besewardj   /* stack pointer */
1269f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj   vex_state->guest_FTOP = ftop;
12700c2cb623cca372a2b42b073121c7413cdaaf75besewardj
12716e0dbda4f7ea53dd29996d4d429d3c5c92ee3640sewardj   /* control word */
1272f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj   vex_state->guest_FPUCW = fpucw;
12733f868e5262a8d2488f41cc49058ba60c24843c3esewardj
12743f868e5262a8d2488f41cc49058ba60c24843c3esewardj   /* status word */
1275f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj   vex_state->guest_FC3210 = c3210;
12760c2cb623cca372a2b42b073121c7413cdaaf75besewardj}
12770c2cb623cca372a2b42b073121c7413cdaaf75besewardj
12786e0dbda4f7ea53dd29996d4d429d3c5c92ee3640sewardj
12790c2cb623cca372a2b42b073121c7413cdaaf75besewardj/* VISIBLE TO LIBVEX CLIENT */
128076bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardjvoid LibVEX_GuestX86_get_x87 ( /*IN*/VexGuestX86State* vex_state,
128176bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj                               /*OUT*/UChar* x87_state )
12820c2cb623cca372a2b42b073121c7413cdaaf75besewardj{
12830c2cb623cca372a2b42b073121c7413cdaaf75besewardj   Int        i, r;
12840c2cb623cca372a2b42b073121c7413cdaaf75besewardj   UInt       tagw;
1285f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj   Double*    vexRegs = (Double*)(&vex_state->guest_FPREG[0]);
1286f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj   UChar*     vexTags = (UChar*)(&vex_state->guest_FPTAG[0]);
12870c2cb623cca372a2b42b073121c7413cdaaf75besewardj   Fpu_State* x87     = (Fpu_State*)x87_state;
1288f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj   UInt       ftop    = vex_state->guest_FTOP;
1289f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj   UInt       c3210   = vex_state->guest_FC3210;
12900c2cb623cca372a2b42b073121c7413cdaaf75besewardj
12910c2cb623cca372a2b42b073121c7413cdaaf75besewardj   for (i = 0; i < 14; i++)
12920c2cb623cca372a2b42b073121c7413cdaaf75besewardj      x87->env[i] = 0;
12930c2cb623cca372a2b42b073121c7413cdaaf75besewardj
12940c2cb623cca372a2b42b073121c7413cdaaf75besewardj   x87->env[1] = x87->env[3] = x87->env[5] = x87->env[13] = 0xFFFF;
1295f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj   x87->env[FP_ENV_CTRL] = (UShort)( vex_state->guest_FPUCW );
1296c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   x87->env[FP_ENV_STAT] = ((ftop & 7) << 11) | (c3210 & 0x4700);
12970c2cb623cca372a2b42b073121c7413cdaaf75besewardj
12980c2cb623cca372a2b42b073121c7413cdaaf75besewardj   tagw = 0;
12990c2cb623cca372a2b42b073121c7413cdaaf75besewardj   for (r = 0; r < 8; r++) {
13000c2cb623cca372a2b42b073121c7413cdaaf75besewardj      if (vexTags[r] == 0) {
13010c2cb623cca372a2b42b073121c7413cdaaf75besewardj         /* register is empty */
13020c2cb623cca372a2b42b073121c7413cdaaf75besewardj         tagw |= (3 << (2*r));
13030c2cb623cca372a2b42b073121c7413cdaaf75besewardj         convert_f64le_to_f80le( (UChar*)&vexRegs[r], &x87->reg[FP_REG(r)] );
13040c2cb623cca372a2b42b073121c7413cdaaf75besewardj      } else {
13050c2cb623cca372a2b42b073121c7413cdaaf75besewardj         /* register is full. */
13060c2cb623cca372a2b42b073121c7413cdaaf75besewardj         tagw |= (0 << (2*r));
13070c2cb623cca372a2b42b073121c7413cdaaf75besewardj         convert_f64le_to_f80le( (UChar*)&vexRegs[r],  &x87->reg[FP_REG(r)] );
13080c2cb623cca372a2b42b073121c7413cdaaf75besewardj      }
13090c2cb623cca372a2b42b073121c7413cdaaf75besewardj   }
13100c2cb623cca372a2b42b073121c7413cdaaf75besewardj   x87->env[FP_ENV_TAG] = tagw;
13110c2cb623cca372a2b42b073121c7413cdaaf75besewardj}
13120c2cb623cca372a2b42b073121c7413cdaaf75besewardj
13130c2cb623cca372a2b42b073121c7413cdaaf75besewardj
1314f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj/* VISIBLE TO LIBVEX CLIENT */
131576bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardjvoid LibVEX_GuestX86_put_eflags ( UInt eflags_native,
131676bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj                                  /*OUT*/VexGuestX86State* vex_state )
1317f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj{
1318f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj   vex_state->guest_DFLAG
1319f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj      = (eflags_native & (1<<10)) ? 0xFFFFFFFF : 0x00000001;
1320006a6a2f15f48f705895a516d4883e8f8142e910sewardj   vex_state->guest_IDFLAG
1321006a6a2f15f48f705895a516d4883e8f8142e910sewardj      = (eflags_native & (1<<21)) ? 1 : 0;
1322f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj
1323f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj   /* Mask out everything except O S Z A C P. */
1324f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj   eflags_native
1325f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj      &= (CC_MASK_C | CC_MASK_P | CC_MASK_A
1326f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj          | CC_MASK_Z | CC_MASK_S | CC_MASK_O);
1327f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj
1328f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj   vex_state->guest_CC_OP  = CC_OP_COPY;
1329f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj   vex_state->guest_CC_DST = 0;
1330f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj   vex_state->guest_CC_DST = eflags_native;
1331f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj}
1332f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj
1333f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj
1334f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj/* VISIBLE TO LIBVEX CLIENT */
133576bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardjUInt LibVEX_GuestX86_get_eflags ( /*IN*/VexGuestX86State* vex_state )
1336f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj{
1337f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj   UInt eflags = calculate_eflags_all(
1338f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj                    vex_state->guest_CC_OP,
1339f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj                    vex_state->guest_CC_SRC,
1340f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj                    vex_state->guest_CC_DST
1341f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj                 );
1342f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj   UInt dflag = vex_state->guest_DFLAG;
1343f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj   vassert(dflag == 1 || dflag == 0xFFFFFFFF);
1344f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj   if (dflag == 0xFFFFFFFF)
1345f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj      eflags |= (1<<10);
1346006a6a2f15f48f705895a516d4883e8f8142e910sewardj   if (vex_state->guest_IDFLAG == 1)
1347006a6a2f15f48f705895a516d4883e8f8142e910sewardj      eflags |= (1<<21);
1348f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj
1349f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj   return eflags;
1350f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj}
1351f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj
1352dda7a4c98be4c7c6f11eab4e1cad6ab275aed79csewardj/* VISIBLE TO LIBVEX CLIENT */
135376bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardjvoid LibVEX_GuestX86_initialise ( /*OUT*/VexGuestX86State* vex_state )
1354dda7a4c98be4c7c6f11eab4e1cad6ab275aed79csewardj{
1355dda7a4c98be4c7c6f11eab4e1cad6ab275aed79csewardj   Int i;
135676bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj
135776bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj   vex_state->guest_EAX = 0;
135876bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj   vex_state->guest_ECX = 0;
135976bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj   vex_state->guest_EDX = 0;
136076bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj   vex_state->guest_EBX = 0;
136176bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj   vex_state->guest_ESP = 0;
136276bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj   vex_state->guest_EBP = 0;
136376bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj   vex_state->guest_ESI = 0;
136476bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj   vex_state->guest_EDI = 0;
136576bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj
136676bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj   vex_state->guest_CC_OP  = CC_OP_COPY;
136776bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj   vex_state->guest_CC_SRC = 0;
136876bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj   vex_state->guest_CC_DST = 0;
136976bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj   vex_state->guest_DFLAG  = 1; /* forwards */
1370006a6a2f15f48f705895a516d4883e8f8142e910sewardj   vex_state->guest_IDFLAG = 0;
137176bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj
137276bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj   vex_state->guest_EIP = 0;
137376bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj
137476bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj   vex_state->guest_FTOP = 0;
1375dda7a4c98be4c7c6f11eab4e1cad6ab275aed79csewardj   for (i = 0; i < 8; i++) {
1376dda7a4c98be4c7c6f11eab4e1cad6ab275aed79csewardj      vex_state->guest_FPTAG[i] = 0; /* empty */
1377dda7a4c98be4c7c6f11eab4e1cad6ab275aed79csewardj      vex_state->guest_FPREG[i] = 0; /* IEEE754 64-bit zero */
1378dda7a4c98be4c7c6f11eab4e1cad6ab275aed79csewardj   }
1379dda7a4c98be4c7c6f11eab4e1cad6ab275aed79csewardj   /* The default setting: all fp exceptions masked, rounding to
1380dda7a4c98be4c7c6f11eab4e1cad6ab275aed79csewardj      nearest, precision to 64 bits */
1381dda7a4c98be4c7c6f11eab4e1cad6ab275aed79csewardj   vex_state->guest_FPUCW = 0x03F7;
138276bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj   vex_state->guest_FC3210 = 0;
138376bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj
138476bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj   vex_state->guest_CS = 0;
138576bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj   vex_state->guest_DS = 0;
138676bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj   vex_state->guest_ES = 0;
138776bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj   vex_state->guest_FS = 0;
138876bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj   vex_state->guest_GS = 0;
138976bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj   vex_state->guest_SS = 0;
1390dda7a4c98be4c7c6f11eab4e1cad6ab275aed79csewardj}
1391f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj
1392f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj
13939aebb0c3f7a7f43313786826f31402f2b733badfsewardj/*----------------------------------------------*/
13949aebb0c3f7a7f43313786826f31402f2b733badfsewardj/*--- Misc integer helpers                   ---*/
13959aebb0c3f7a7f43313786826f31402f2b733badfsewardj/*----------------------------------------------*/
13969aebb0c3f7a7f43313786826f31402f2b733badfsewardj
13979aebb0c3f7a7f43313786826f31402f2b733badfsewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
13989aebb0c3f7a7f43313786826f31402f2b733badfsewardj/* Calculate both flags and value result for rotate right
13999aebb0c3f7a7f43313786826f31402f2b733badfsewardj   through the carry bit.  Result in low 32 bits,
14009aebb0c3f7a7f43313786826f31402f2b733badfsewardj   new flags (OSZACP) in high 32 bits.
14019aebb0c3f7a7f43313786826f31402f2b733badfsewardj*/
14029aebb0c3f7a7f43313786826f31402f2b733badfsewardjstatic ULong calculate_RCR ( UInt arg, UInt rot_amt, UInt eflags_in, UInt sz )
14039aebb0c3f7a7f43313786826f31402f2b733badfsewardj{
14049aebb0c3f7a7f43313786826f31402f2b733badfsewardj   UInt tempCOUNT = rot_amt & 0x1F, cf=0, of=0, tempcf;
14059aebb0c3f7a7f43313786826f31402f2b733badfsewardj
14069aebb0c3f7a7f43313786826f31402f2b733badfsewardj   switch (sz) {
14079aebb0c3f7a7f43313786826f31402f2b733badfsewardj      case 4:
14089aebb0c3f7a7f43313786826f31402f2b733badfsewardj         cf        = (eflags_in >> CC_SHIFT_C) & 1;
14099aebb0c3f7a7f43313786826f31402f2b733badfsewardj         of        = ((arg >> 31) ^ cf) & 1;
14109aebb0c3f7a7f43313786826f31402f2b733badfsewardj         while (tempCOUNT > 0) {
14119aebb0c3f7a7f43313786826f31402f2b733badfsewardj            tempcf = arg & 1;
14129aebb0c3f7a7f43313786826f31402f2b733badfsewardj            arg    = (arg >> 1) | (cf << 31);
14139aebb0c3f7a7f43313786826f31402f2b733badfsewardj            cf     = tempcf;
14149aebb0c3f7a7f43313786826f31402f2b733badfsewardj            tempCOUNT--;
14159aebb0c3f7a7f43313786826f31402f2b733badfsewardj         }
14169aebb0c3f7a7f43313786826f31402f2b733badfsewardj         break;
14179aebb0c3f7a7f43313786826f31402f2b733badfsewardj      case 2:
14189aebb0c3f7a7f43313786826f31402f2b733badfsewardj         while (tempCOUNT >= 17) tempCOUNT -= 17;
14199aebb0c3f7a7f43313786826f31402f2b733badfsewardj         cf        = (eflags_in >> CC_SHIFT_C) & 1;
14209aebb0c3f7a7f43313786826f31402f2b733badfsewardj         of        = ((arg >> 15) ^ cf) & 1;
14219aebb0c3f7a7f43313786826f31402f2b733badfsewardj         while (tempCOUNT > 0) {
14229aebb0c3f7a7f43313786826f31402f2b733badfsewardj            tempcf = arg & 1;
14239aebb0c3f7a7f43313786826f31402f2b733badfsewardj            arg    = ((arg >> 1) & 0x7FFF) | (cf << 15);
14249aebb0c3f7a7f43313786826f31402f2b733badfsewardj            cf     = tempcf;
14259aebb0c3f7a7f43313786826f31402f2b733badfsewardj            tempCOUNT--;
14269aebb0c3f7a7f43313786826f31402f2b733badfsewardj         }
14279aebb0c3f7a7f43313786826f31402f2b733badfsewardj         break;
14289aebb0c3f7a7f43313786826f31402f2b733badfsewardj      case 1:
14299aebb0c3f7a7f43313786826f31402f2b733badfsewardj         while (tempCOUNT >= 9) tempCOUNT -= 9;
14309aebb0c3f7a7f43313786826f31402f2b733badfsewardj         cf        = (eflags_in >> CC_SHIFT_C) & 1;
14319aebb0c3f7a7f43313786826f31402f2b733badfsewardj         of        = ((arg >> 7) ^ cf) & 1;
14329aebb0c3f7a7f43313786826f31402f2b733badfsewardj         while (tempCOUNT > 0) {
14339aebb0c3f7a7f43313786826f31402f2b733badfsewardj            tempcf = arg & 1;
14349aebb0c3f7a7f43313786826f31402f2b733badfsewardj            arg    = ((arg >> 1) & 0x7F) | (cf << 7);
14359aebb0c3f7a7f43313786826f31402f2b733badfsewardj            cf     = tempcf;
14369aebb0c3f7a7f43313786826f31402f2b733badfsewardj            tempCOUNT--;
14379aebb0c3f7a7f43313786826f31402f2b733badfsewardj         }
14389aebb0c3f7a7f43313786826f31402f2b733badfsewardj         break;
14399aebb0c3f7a7f43313786826f31402f2b733badfsewardj      default:
14409aebb0c3f7a7f43313786826f31402f2b733badfsewardj         vpanic("calculate_RCR: invalid size");
14419aebb0c3f7a7f43313786826f31402f2b733badfsewardj   }
14429aebb0c3f7a7f43313786826f31402f2b733badfsewardj
14439aebb0c3f7a7f43313786826f31402f2b733badfsewardj   cf &= 1;
14449aebb0c3f7a7f43313786826f31402f2b733badfsewardj   of &= 1;
14459aebb0c3f7a7f43313786826f31402f2b733badfsewardj   eflags_in &= ~(CC_MASK_C | CC_MASK_O);
14469aebb0c3f7a7f43313786826f31402f2b733badfsewardj   eflags_in |= (cf << CC_SHIFT_C) | (of << CC_SHIFT_O);
14479aebb0c3f7a7f43313786826f31402f2b733badfsewardj
14489aebb0c3f7a7f43313786826f31402f2b733badfsewardj   return (((ULong)eflags_in) << 32) | ((ULong)arg);
14499aebb0c3f7a7f43313786826f31402f2b733badfsewardj}
14509aebb0c3f7a7f43313786826f31402f2b733badfsewardj
14517cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardj
14527cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardj/* CALLED FROM GENERATED CODE */
14537cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardj/* DIRTY HELPER (modifies guest state) */
14547cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardj/* Claim to be a P54C P133 (pre-MMX Pentium) */
14557cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardjstatic void dirtyhelper_CPUID ( VexGuestX86State* st )
14567cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardj{
14577cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardj   if (st->guest_EAX == 0) {
14587cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardj      st->guest_EAX = 0x1;
14597cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardj      st->guest_EBX = 0x756e6547;
14607cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardj      st->guest_ECX = 0x6c65746e;
14617cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardj      st->guest_EDX = 0x49656e69;
14627cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardj   } else {
14637cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardj      st->guest_EAX = 0x52b;
14647cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardj      st->guest_EBX = 0x0;
14657cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardj      st->guest_ECX = 0x0;
14667cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardj      st->guest_EDX = 0x1bf;
14677cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardj   }
14687cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardj}
14697cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardj
14708d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj/*-----------------------------------------------------------*/
14718d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj/*--- Describing the x86 guest state, for the benefit     ---*/
14728d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj/*--- of iropt and instrumenters.                         ---*/
14738d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj/*-----------------------------------------------------------*/
14748d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj
14758d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj/* Figure out if any part of the guest state contained in minoff
14768d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   .. maxoff requires precise memory exceptions.  If in doubt return
14778d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   True (but this is generates significantly slower code).
14788d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj
14798d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   We enforce precise exns for guest %ESP and %EIP only.
14808d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj*/
14818d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardjBool guest_x86_state_requires_precise_mem_exns ( Int minoff,
14828d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj                                                 Int maxoff)
14838d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj{
14848d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   Int esp_min = offsetof(VexGuestX86State, guest_ESP);
14858d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   Int esp_max = esp_min + 4 - 1;
14868d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   Int eip_min = offsetof(VexGuestX86State, guest_EIP);
14878d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   Int eip_max = eip_min + 4 - 1;
14888d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj
14898d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   if (maxoff < esp_min || minoff > esp_max) {
14908d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj     /* no overlap with esp */
14918d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   } else {
14928d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj     return True;
14938d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   }
14948d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj
14958d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   if (maxoff < eip_min || minoff > eip_max) {
14968d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj     /* no overlap with eip */
14978d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   } else {
14988d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj     return True;
14998d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   }
15008d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj
15018d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj   return False;
15028d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj}
15038d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj
15048d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj
150536ca51378f8851635df814230fa23f2c409b9eddsewardj/*---------------------------------------------------------------*/
1506c0ee2edb4563c90bc8f1a83a09984a1fda86d1d3sewardj/*--- end                                guest-x86/ghelpers.c ---*/
150736ca51378f8851635df814230fa23f2c409b9eddsewardj/*---------------------------------------------------------------*/
1508