guest_x86_helpers.c revision df22c1c8b9c7fb712e6471a391d2615c48afaa6d
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 --- */
1717442fe8094d0f82266e5a05509f62cac8f7539esewardj       UInt calculate_eflags_all ( UInt cc_op, UInt cc_src, UInt cc_dst );
1817442fe8094d0f82266e5a05509f62cac8f7539esewardjstatic UInt calculate_eflags_c   ( UInt cc_op, UInt cc_src, UInt cc_dst );
1917442fe8094d0f82266e5a05509f62cac8f7539esewardjstatic UInt calculate_condition  ( UInt/*Condcode*/ cond,
2017442fe8094d0f82266e5a05509f62cac8f7539esewardj                                   UInt cc_op, UInt cc_src, UInt cc_dst );
2117442fe8094d0f82266e5a05509f62cac8f7539esewardjstatic UInt calculate_FXAM ( UInt tag, ULong dbl );
2217442fe8094d0f82266e5a05509f62cac8f7539esewardjstatic ULong loadF80le ( UInt );
2317442fe8094d0f82266e5a05509f62cac8f7539esewardjstatic void  storeF80le ( UInt, ULong );
24c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
25c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
2636ca51378f8851635df814230fa23f2c409b9eddsewardj/* This file contains helper functions for x86 guest code.
2736ca51378f8851635df814230fa23f2c409b9eddsewardj   Calls to these functions are generated by the back end.
2836ca51378f8851635df814230fa23f2c409b9eddsewardj   These calls are of course in the host machine code and
2936ca51378f8851635df814230fa23f2c409b9eddsewardj   this file will be compiled to host machine code, so that
3036ca51378f8851635df814230fa23f2c409b9eddsewardj   all makes sense.
3136ca51378f8851635df814230fa23f2c409b9eddsewardj
3236ca51378f8851635df814230fa23f2c409b9eddsewardj   x86guest_findhelper() is the only exported function.
3336ca51378f8851635df814230fa23f2c409b9eddsewardj
3436ca51378f8851635df814230fa23f2c409b9eddsewardj   Only change the signatures of these helper functions very
3536ca51378f8851635df814230fa23f2c409b9eddsewardj   carefully.  If you change the signature here, you'll have to change
3636ca51378f8851635df814230fa23f2c409b9eddsewardj   the parameters passed to it in the IR calls constructed by
3789050e58e7bee40892662fe94231aefc33768cf5sewardj   x86toIR.c.
3889050e58e7bee40892662fe94231aefc33768cf5sewardj
3989050e58e7bee40892662fe94231aefc33768cf5sewardj   Some of this code/logic is derived from QEMU, which is copyright
4089050e58e7bee40892662fe94231aefc33768cf5sewardj   Fabrice Bellard, licensed under the LGPL.  It is used with
4189050e58e7bee40892662fe94231aefc33768cf5sewardj   permission.
4236ca51378f8851635df814230fa23f2c409b9eddsewardj*/
4336ca51378f8851635df814230fa23f2c409b9eddsewardj
4484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj/* Set to 1 to get detailed profiling info about use of the flag
4584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   machinery. */
4684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#define PROFILE_EFLAGS 0
4784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
4884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
4914731f22bf7759d6d23383ca870ac89d9581f1e9sewardjtypedef UChar uint8_t;
50741153c4301023a420ab45b8a10b8e1bac968822sewardjtypedef UInt  uint32_t;
5114731f22bf7759d6d23383ca870ac89d9581f1e9sewardj
5214731f22bf7759d6d23383ca870ac89d9581f1e9sewardj#define CC_O CC_MASK_O
5314731f22bf7759d6d23383ca870ac89d9581f1e9sewardj#define CC_P CC_MASK_P
54741153c4301023a420ab45b8a10b8e1bac968822sewardj#define CC_C CC_MASK_C
5514731f22bf7759d6d23383ca870ac89d9581f1e9sewardj
5614731f22bf7759d6d23383ca870ac89d9581f1e9sewardj
5714731f22bf7759d6d23383ca870ac89d9581f1e9sewardjstatic const uint8_t parity_table[256] = {
5814731f22bf7759d6d23383ca870ac89d9581f1e9sewardj    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
5914731f22bf7759d6d23383ca870ac89d9581f1e9sewardj    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
6014731f22bf7759d6d23383ca870ac89d9581f1e9sewardj    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
6114731f22bf7759d6d23383ca870ac89d9581f1e9sewardj    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
6214731f22bf7759d6d23383ca870ac89d9581f1e9sewardj    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
6314731f22bf7759d6d23383ca870ac89d9581f1e9sewardj    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
6414731f22bf7759d6d23383ca870ac89d9581f1e9sewardj    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
6514731f22bf7759d6d23383ca870ac89d9581f1e9sewardj    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
6614731f22bf7759d6d23383ca870ac89d9581f1e9sewardj    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
6714731f22bf7759d6d23383ca870ac89d9581f1e9sewardj    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
6814731f22bf7759d6d23383ca870ac89d9581f1e9sewardj    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
6914731f22bf7759d6d23383ca870ac89d9581f1e9sewardj    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
7014731f22bf7759d6d23383ca870ac89d9581f1e9sewardj    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
7114731f22bf7759d6d23383ca870ac89d9581f1e9sewardj    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
7214731f22bf7759d6d23383ca870ac89d9581f1e9sewardj    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
7314731f22bf7759d6d23383ca870ac89d9581f1e9sewardj    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
7414731f22bf7759d6d23383ca870ac89d9581f1e9sewardj    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
7514731f22bf7759d6d23383ca870ac89d9581f1e9sewardj    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
7614731f22bf7759d6d23383ca870ac89d9581f1e9sewardj    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
7714731f22bf7759d6d23383ca870ac89d9581f1e9sewardj    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
7814731f22bf7759d6d23383ca870ac89d9581f1e9sewardj    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
7914731f22bf7759d6d23383ca870ac89d9581f1e9sewardj    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
8014731f22bf7759d6d23383ca870ac89d9581f1e9sewardj    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
8114731f22bf7759d6d23383ca870ac89d9581f1e9sewardj    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
8214731f22bf7759d6d23383ca870ac89d9581f1e9sewardj    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
8314731f22bf7759d6d23383ca870ac89d9581f1e9sewardj    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
8414731f22bf7759d6d23383ca870ac89d9581f1e9sewardj    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
8514731f22bf7759d6d23383ca870ac89d9581f1e9sewardj    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
8614731f22bf7759d6d23383ca870ac89d9581f1e9sewardj    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
8714731f22bf7759d6d23383ca870ac89d9581f1e9sewardj    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
8814731f22bf7759d6d23383ca870ac89d9581f1e9sewardj    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
8914731f22bf7759d6d23383ca870ac89d9581f1e9sewardj    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
9014731f22bf7759d6d23383ca870ac89d9581f1e9sewardj};
9114731f22bf7759d6d23383ca870ac89d9581f1e9sewardj
9214731f22bf7759d6d23383ca870ac89d9581f1e9sewardj/* n must be a constant to be efficient */
93df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardjinline static Int lshift ( Int x, Int n )
9414731f22bf7759d6d23383ca870ac89d9581f1e9sewardj{
95df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   if (n >= 0)
96df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj      return x << n;
97df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   else
98df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj      return x >> (-n);
9914731f22bf7759d6d23383ca870ac89d9581f1e9sewardj}
10014731f22bf7759d6d23383ca870ac89d9581f1e9sewardj
10114731f22bf7759d6d23383ca870ac89d9581f1e9sewardj
102b9c5cf639b3b21b972599d27207a033afc76ef67sewardj#define PREAMBLE(__data_bits)					\
103df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   /* const */ UInt DATA_MASK 					\
104b9c5cf639b3b21b972599d27207a033afc76ef67sewardj      = __data_bits==8 ? 0xFF 					\
105b9c5cf639b3b21b972599d27207a033afc76ef67sewardj                       : (__data_bits==16 ? 0xFFFF 		\
106b9c5cf639b3b21b972599d27207a033afc76ef67sewardj                                          : 0xFFFFFFFF); 	\
107df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   /* const */ UInt SIGN_MASK = 1 << (__data_bits - 1);		\
108df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   /* const */ UInt CC_DST = cc_dst_formal;			\
109df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   /* const */ UInt CC_SRC = cc_src_formal;			\
110df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   /* Three bogus assignments, which hopefully gcc can    */	\
111df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   /* optimise away, and which stop it complaining about  */	\
112df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   /* unused variables.                                   */	\
113df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   SIGN_MASK = SIGN_MASK;					\
114df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   DATA_MASK = DATA_MASK;					\
115df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   CC_SRC = CC_SRC;
116df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj
11714731f22bf7759d6d23383ca870ac89d9581f1e9sewardj
118b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
119b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
120df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_ADD(DATA_BITS,DATA_UTYPE)			\
121b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
122b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
123b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   int cf, pf, af, zf, sf, of;					\
124b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   int src1, src2, dst;						\
125b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   src1 = CC_SRC;						\
126b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   src2 = CC_DST;						\
127b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   dst  = src1 + src2;						\
128df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   cf = (DATA_UTYPE)dst < (DATA_UTYPE)src1;			\
129b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   pf = parity_table[(uint8_t)dst];				\
130b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   af = (dst ^ src1 ^ src2) & 0x10;				\
131df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   zf = ((DATA_UTYPE)dst == 0) << 6;				\
132b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   sf = lshift(dst, 8 - DATA_BITS) & 0x80;			\
133b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   of = lshift((src1 ^ src2 ^ -1) & (src1 ^ dst), 		\
134b9c5cf639b3b21b972599d27207a033afc76ef67sewardj               12 - DATA_BITS) & CC_O;				\
135b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   return cf | pf | af | zf | sf | of;				\
1362ef5f2a829433c4ca17f33e1bf993cf16b9e347dsewardj}
1372ef5f2a829433c4ca17f33e1bf993cf16b9e347dsewardj
138b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
139b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
140df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_ADC(DATA_BITS,DATA_UTYPE)			\
141b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
142b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
143b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   int cf, pf, af, zf, sf, of;					\
144b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   int src1, src2, dst;						\
145b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   src1 = CC_SRC;						\
146b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   src2 = CC_DST;						\
147b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   dst = src1 + src2 + 1;					\
148df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   cf = (DATA_UTYPE)dst <= (DATA_UTYPE)src1;			\
149b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   pf = parity_table[(uint8_t)dst];				\
150b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   af = (dst ^ src1 ^ src2) & 0x10;				\
151df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   zf = ((DATA_UTYPE)dst == 0) << 6;				\
152b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   sf = lshift(dst, 8 - DATA_BITS) & 0x80;			\
153b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   of = lshift((src1 ^ src2 ^ -1) & (src1 ^ dst), 		\
154b9c5cf639b3b21b972599d27207a033afc76ef67sewardj                12 - DATA_BITS) & CC_O;				\
155b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   return cf | pf | af | zf | sf | of;				\
1562ef5f2a829433c4ca17f33e1bf993cf16b9e347dsewardj}
1572ef5f2a829433c4ca17f33e1bf993cf16b9e347dsewardj
158b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
159b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
160df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_SUB(DATA_BITS,DATA_UTYPE)			\
161b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
162b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
163b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   int cf, pf, af, zf, sf, of;					\
164b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   int src1, src2, dst;						\
165b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   src1 = CC_DST;						\
166b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   src2 = CC_SRC;						\
167b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   dst = src1 - src2;						\
168df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   cf = (DATA_UTYPE)src1 < (DATA_UTYPE)src2;			\
169b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   pf = parity_table[(uint8_t)dst];				\
170b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   af = (dst ^ src1 ^ src2) & 0x10;				\
171df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   zf = ((DATA_UTYPE)dst == 0) << 6;				\
172b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   sf = lshift(dst, 8 - DATA_BITS) & 0x80;			\
173b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   of = lshift((src1 ^ src2) & (src1 ^ dst),	 		\
174b9c5cf639b3b21b972599d27207a033afc76ef67sewardj               12 - DATA_BITS) & CC_O; 				\
175b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   return cf | pf | af | zf | sf | of;				\
1762ef5f2a829433c4ca17f33e1bf993cf16b9e347dsewardj}
1772ef5f2a829433c4ca17f33e1bf993cf16b9e347dsewardj
178b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
179b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
180df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_SBB(DATA_BITS,DATA_UTYPE)			\
181b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
182b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
183b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   int cf, pf, af, zf, sf, of;					\
184b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   int src1, src2, dst;						\
185b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   src1 = CC_DST;						\
186b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   src2 = CC_SRC;						\
187b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   dst = (src1 - src2) - 1;					\
188df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   cf = (DATA_UTYPE)src1 <= (DATA_UTYPE)src2;			\
189b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   pf = parity_table[(uint8_t)dst];				\
190b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   af = (dst ^ src1 ^ src2) & 0x10;				\
191df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   zf = ((DATA_UTYPE)dst == 0) << 6;				\
192b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   sf = lshift(dst, 8 - DATA_BITS) & 0x80;			\
193b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   of = lshift((src1 ^ src2) & (src1 ^ dst), 			\
194b9c5cf639b3b21b972599d27207a033afc76ef67sewardj               12 - DATA_BITS) & CC_O;				\
195b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   return cf | pf | af | zf | sf | of;				\
196a238471814bd386aeb58a76718b41e68b1a794b2sewardj}
197a238471814bd386aeb58a76718b41e68b1a794b2sewardj
198b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
199b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
200df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_LOGIC(DATA_BITS,DATA_UTYPE)			\
201b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
202b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
203b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   int cf, pf, af, zf, sf, of;					\
204b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   cf = 0;							\
205b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   pf = parity_table[(uint8_t)CC_DST];				\
206b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   af = 0;							\
207df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   zf = ((DATA_UTYPE)CC_DST == 0) << 6;				\
208b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;			\
209b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   of = 0;							\
210b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   return cf | pf | af | zf | sf | of;				\
211a238471814bd386aeb58a76718b41e68b1a794b2sewardj}
212a238471814bd386aeb58a76718b41e68b1a794b2sewardj
213b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
214b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
215df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_INC(DATA_BITS,DATA_UTYPE)			\
216b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
217b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
218b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   int cf, pf, af, zf, sf, of;					\
219b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   int src1, src2;						\
220b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   src1 = CC_DST - 1;						\
221b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   src2 = 1;							\
222b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   cf = CC_SRC;							\
223b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   pf = parity_table[(uint8_t)CC_DST];				\
224b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   af = (CC_DST ^ src1 ^ src2) & 0x10;				\
225df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   zf = ((DATA_UTYPE)CC_DST == 0) << 6;				\
226b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;			\
227b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   of = ((CC_DST & DATA_MASK) == SIGN_MASK) << 11;		\
228b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   return cf | pf | af | zf | sf | of;				\
22989050e58e7bee40892662fe94231aefc33768cf5sewardj}
23089050e58e7bee40892662fe94231aefc33768cf5sewardj
231b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
232b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
233df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_DEC(DATA_BITS,DATA_UTYPE)			\
234b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
235b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
236b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   int cf, pf, af, zf, sf, of;					\
237b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   int src1, src2;						\
238b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   src1 = CC_DST + 1;						\
239b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   src2 = 1;							\
240b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   cf = CC_SRC;							\
241b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   pf = parity_table[(uint8_t)CC_DST];				\
242b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   af = (CC_DST ^ src1 ^ src2) & 0x10;				\
243df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   zf = ((DATA_UTYPE)CC_DST == 0) << 6;				\
244b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;			\
245b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   of = ((CC_DST & DATA_MASK) 					\
246b9c5cf639b3b21b972599d27207a033afc76ef67sewardj        == ((uint32_t)SIGN_MASK - 1)) << 11;			\
247b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   return cf | pf | af | zf | sf | of;				\
24889050e58e7bee40892662fe94231aefc33768cf5sewardj}
24989050e58e7bee40892662fe94231aefc33768cf5sewardj
250b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
251b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
252df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_SHL(DATA_BITS,DATA_UTYPE)			\
253b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
254b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
255b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   int cf, pf, af, zf, sf, of;					\
256b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   cf = (CC_SRC >> (DATA_BITS - 1)) & CC_C;			\
257b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   pf = parity_table[(uint8_t)CC_DST];				\
258b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   af = 0; /* undefined */					\
259df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   zf = ((DATA_UTYPE)CC_DST == 0) << 6;				\
260b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;			\
261b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   /* of is defined if shift count == 1 */			\
262b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   of = lshift(CC_SRC ^ CC_DST, 12 - DATA_BITS) & CC_O;		\
263b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   return cf | pf | af | zf | sf | of;				\
2645f6303579435ddb8315e11c2f02c904b978782a0sewardj}
2655f6303579435ddb8315e11c2f02c904b978782a0sewardj
266b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
267b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
268df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_SAR(DATA_BITS,DATA_UTYPE)			\
269b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
270b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);  					\
271b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   int cf, pf, af, zf, sf, of;					\
272b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   cf = CC_SRC & 1;						\
273b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   pf = parity_table[(uint8_t)CC_DST];				\
274b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   af = 0; /* undefined */					\
275df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   zf = ((DATA_UTYPE)CC_DST == 0) << 6;				\
276b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;			\
277b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   /* of is defined if shift count == 1 */			\
278b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   of = lshift(CC_SRC ^ CC_DST, 12 - DATA_BITS) & CC_O;	 	\
279b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   return cf | pf | af | zf | sf | of;				\
2805f6303579435ddb8315e11c2f02c904b978782a0sewardj}
2815f6303579435ddb8315e11c2f02c904b978782a0sewardj
282b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
283b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
2848ee2de1f5f72c13120f59c0ca6ac8291219123dfsewardj/* ROL: cf' = lsb(result).  of' = msb(result) ^ lsb(result). */
2858c7f1abe9e022f6382634efea09c9cac89ec6336sewardj/* DST = result, SRC = old flags */
286df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_ROL(DATA_BITS,DATA_UTYPE)			\
287b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
288b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
289b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   int fl 							\
290b9c5cf639b3b21b972599d27207a033afc76ef67sewardj      = (CC_SRC & ~(CC_O | CC_C))				\
291b9c5cf639b3b21b972599d27207a033afc76ef67sewardj        | (CC_C & CC_DST)					\
292b9c5cf639b3b21b972599d27207a033afc76ef67sewardj        | (CC_O & (lshift(CC_DST, 11-(DATA_BITS-1)) 		\
293b9c5cf639b3b21b972599d27207a033afc76ef67sewardj                   ^ lshift(CC_DST, 11)));			\
294b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   return fl;							\
2958c7f1abe9e022f6382634efea09c9cac89ec6336sewardj}
2968c7f1abe9e022f6382634efea09c9cac89ec6336sewardj
297b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
298b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
2991813dbeb912870e9a544cae17a3fadbf8d2b0d55sewardj/* ROR: cf' = msb(result).  of' = msb(result) ^ msb-1(result). */
3001813dbeb912870e9a544cae17a3fadbf8d2b0d55sewardj/* DST = result, SRC = old flags */
301df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_ROR(DATA_BITS,DATA_UTYPE)			\
302b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
303b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
304b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   int fl 							\
305b9c5cf639b3b21b972599d27207a033afc76ef67sewardj      = (CC_SRC & ~(CC_O | CC_C))				\
306b9c5cf639b3b21b972599d27207a033afc76ef67sewardj        | (CC_C & (CC_DST >> (DATA_BITS-1)))			\
307b9c5cf639b3b21b972599d27207a033afc76ef67sewardj        | (CC_O & (lshift(CC_DST, 11-(DATA_BITS-1)) 		\
308b9c5cf639b3b21b972599d27207a033afc76ef67sewardj                   ^ lshift(CC_DST, 11-(DATA_BITS-1)+1)));	\
309b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   return fl;							\
3101813dbeb912870e9a544cae17a3fadbf8d2b0d55sewardj}
3111813dbeb912870e9a544cae17a3fadbf8d2b0d55sewardj
312b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
313b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
314df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_UMUL(DATA_BITS,DATA_UTYPE,DATA_U2TYPE)		\
315b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
316b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
317b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   int cf, pf, af, zf, sf, of;					\
318df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   DATA_UTYPE  hi;						\
319df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   DATA_UTYPE  lo = ((DATA_UTYPE)CC_SRC) * ((DATA_UTYPE)CC_DST);\
320df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   DATA_U2TYPE rr = ((DATA_U2TYPE)((DATA_UTYPE)CC_SRC))		\
321df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj                    * ((DATA_U2TYPE)((DATA_UTYPE)CC_DST));	\
322df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   hi = (DATA_UTYPE)(rr >>/*u*/ DATA_BITS);			\
323df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   cf = (hi != 0);						\
324b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   pf = parity_table[(uint8_t)lo];				\
325b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   af = 0; /* undefined */					\
326df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   zf = (lo == 0) << 6;				  	     	\
327b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   sf = lshift(lo, 8 - DATA_BITS) & 0x80;			\
328b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   of = cf << 11;						\
329b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   return cf | pf | af | zf | sf | of;				\
33056296d80c9e15ec59eebecf1c3aea9ebd4dac115sewardj}
33156296d80c9e15ec59eebecf1c3aea9ebd4dac115sewardj
332b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/
333b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
334df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_SMUL(DATA_BITS,DATA_STYPE,DATA_S2TYPE)		\
335b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{								\
336b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   PREAMBLE(DATA_BITS);						\
337b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   int cf, pf, af, zf, sf, of;					\
338df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   DATA_STYPE  hi;						\
339df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   DATA_STYPE  lo = ((DATA_STYPE)CC_SRC) * ((DATA_STYPE)CC_DST);\
340df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   DATA_S2TYPE rr = ((DATA_S2TYPE)((DATA_STYPE)CC_SRC))		\
341df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj                    * ((DATA_S2TYPE)((DATA_STYPE)CC_DST));	\
342df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   hi = (DATA_STYPE)(rr >>/*s*/ DATA_BITS);			\
343df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   cf = (hi != (lo >>/*s*/ (DATA_BITS-1)));			\
344b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   pf = parity_table[(uint8_t)lo];				\
345b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   af = 0; /* undefined */					\
346df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj   zf = (lo == 0) << 6;						\
347b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   sf = lshift(lo, 8 - DATA_BITS) & 0x80;			\
348b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   of = cf << 11;						\
349b9c5cf639b3b21b972599d27207a033afc76ef67sewardj   return cf | pf | af | zf | sf | of;				\
3507ed2295459ac5e788a98dd5570fef0d4645c27d4sewardj}
351741153c4301023a420ab45b8a10b8e1bac968822sewardj
35236ca51378f8851635df814230fa23f2c409b9eddsewardj
35384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
35484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#define CC_SHIFT_C 0
35584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#define CC_SHIFT_P 2
35684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#define CC_SHIFT_A 4
35784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#define CC_SHIFT_Z 6
35884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#define CC_SHIFT_S 7
359b9c5cf639b3b21b972599d27207a033afc76ef67sewardj#define CC_SHIFT_O 11
36084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
36184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#if PROFILE_EFLAGS
36284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
36384ff0657940e62f38e618ea18bac6f27ce0e741fsewardjstatic UInt tabc[CC_OP_NUMBER];
36484ff0657940e62f38e618ea18bac6f27ce0e741fsewardjstatic UInt tab[CC_OP_NUMBER][16];
3659eab588e223e52b1e7b710ff1c0da7b032ab2837sewardjstatic Bool initted     = False;
36684ff0657940e62f38e618ea18bac6f27ce0e741fsewardjstatic UInt n_calc_cond = 0;
36784ff0657940e62f38e618ea18bac6f27ce0e741fsewardjstatic UInt n_calc_all  = 0;
36884ff0657940e62f38e618ea18bac6f27ce0e741fsewardjstatic UInt n_calc_c    = 0;
36984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
37084ff0657940e62f38e618ea18bac6f27ce0e741fsewardjstatic void showCounts ( void )
37184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj{
37284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   Int op, co;
37384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   Char ch;
3749eab588e223e52b1e7b710ff1c0da7b032ab2837sewardj   vex_printf("\nALL=%d  COND=%d   C=%d\n",
37584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj              n_calc_all-n_calc_cond-n_calc_c, n_calc_cond, n_calc_c);
37684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   vex_printf("      CARRY    O   NO    B   NB    Z   NZ   BE  NBE"
37784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj              "    S   NS    P   NP    L   NL   LE  NLE\n");
37884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   vex_printf("     ----------------------------------------------"
37984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj              "----------------------------------------\n");
38084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   for (op = 0; op < CC_OP_NUMBER; op++) {
38184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
38284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      ch = ' ';
38384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      if (op > 0 && (op-1) % 3 == 2)
38484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         ch = 'L';
38584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
38684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      vex_printf("%2d%c: ", op, ch);
38784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      vex_printf("%6d ", tabc[op]);
38884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      for (co = 0; co < 16; co++) {
38984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         Int n = tab[op][co];
39084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         if (n >= 1000) {
39184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj            vex_printf(" %3dK", n / 1000);
39284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         } else
39384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         if (n >= 0) {
39484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj           vex_printf(" %3d ", n );
39584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         } else {
39684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj            vex_printf("     ");
39784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         }
39884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
39984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      vex_printf("\n");
40084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   }
40184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   vex_printf("\n");
40284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj}
40384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
40484ff0657940e62f38e618ea18bac6f27ce0e741fsewardjstatic void initCounts ( void )
40584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj{
40684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   Int op, co;
40784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   initted = True;
40884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   for (op = 0; op < CC_OP_NUMBER; op++) {
40984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      tabc[op] = 0;
41084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      for (co = 0; co < 16; co++)
41184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         tab[op][co] = 0;
41284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   }
41384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj}
41484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
41584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#endif /* PROFILE_EFLAGS */
41684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
4176e9964d701fda887cddd0fd579fc27fd18bbfc0fsewardj/* CALLED FROM GENERATED CODE */
418b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/* Calculate all the 6 flags from the supplied thunk parameters. */
419df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj/*static*/
420df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardjUInt calculate_eflags_all ( UInt cc_op, UInt cc_src_formal, UInt cc_dst_formal )
42136ca51378f8851635df814230fa23f2c409b9eddsewardj{
42284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  if PROFILE_EFLAGS
42384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   n_calc_all++;
42484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  endif
42536ca51378f8851635df814230fa23f2c409b9eddsewardj   switch (cc_op) {
4261813dbeb912870e9a544cae17a3fadbf8d2b0d55sewardj      case CC_OP_COPY:
427df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj         return cc_src_formal
428df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj                & (CC_MASK_O | CC_MASK_S | CC_MASK_Z
429df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj                   | CC_MASK_A | CC_MASK_C | CC_MASK_P);
43014731f22bf7759d6d23383ca870ac89d9581f1e9sewardj
4318c7f1abe9e022f6382634efea09c9cac89ec6336sewardj      case CC_OP_ADDB:   ACTIONS_ADD( 8,  UChar  );
432a238471814bd386aeb58a76718b41e68b1a794b2sewardj      case CC_OP_ADDW:   ACTIONS_ADD( 16, UShort );
4338c7f1abe9e022f6382634efea09c9cac89ec6336sewardj      case CC_OP_ADDL:   ACTIONS_ADD( 32, UInt   );
434a238471814bd386aeb58a76718b41e68b1a794b2sewardj
4358c7f1abe9e022f6382634efea09c9cac89ec6336sewardj      case CC_OP_ADCB:   ACTIONS_ADC( 8,  UChar  );
436a238471814bd386aeb58a76718b41e68b1a794b2sewardj      case CC_OP_ADCW:   ACTIONS_ADC( 16, UShort );
4378c7f1abe9e022f6382634efea09c9cac89ec6336sewardj      case CC_OP_ADCL:   ACTIONS_ADC( 32, UInt   );
438a238471814bd386aeb58a76718b41e68b1a794b2sewardj
4398c7f1abe9e022f6382634efea09c9cac89ec6336sewardj      case CC_OP_SUBB:   ACTIONS_SUB(  8, UChar  );
440a238471814bd386aeb58a76718b41e68b1a794b2sewardj      case CC_OP_SUBW:   ACTIONS_SUB( 16, UShort );
4418c7f1abe9e022f6382634efea09c9cac89ec6336sewardj      case CC_OP_SUBL:   ACTIONS_SUB( 32, UInt   );
442afc5787e1c4b8e9678669577cf57ac509c6cd6b5sewardj
4438c7f1abe9e022f6382634efea09c9cac89ec6336sewardj      case CC_OP_SBBB:   ACTIONS_SBB(  8, UChar  );
444a238471814bd386aeb58a76718b41e68b1a794b2sewardj      case CC_OP_SBBW:   ACTIONS_SBB( 16, UShort );
4458c7f1abe9e022f6382634efea09c9cac89ec6336sewardj      case CC_OP_SBBL:   ACTIONS_SBB( 32, UInt   );
446741153c4301023a420ab45b8a10b8e1bac968822sewardj
4478c7f1abe9e022f6382634efea09c9cac89ec6336sewardj      case CC_OP_LOGICB: ACTIONS_LOGIC(  8, UChar  );
448a238471814bd386aeb58a76718b41e68b1a794b2sewardj      case CC_OP_LOGICW: ACTIONS_LOGIC( 16, UShort );
4498c7f1abe9e022f6382634efea09c9cac89ec6336sewardj      case CC_OP_LOGICL: ACTIONS_LOGIC( 32, UInt   );
4505f6303579435ddb8315e11c2f02c904b978782a0sewardj
4518c7f1abe9e022f6382634efea09c9cac89ec6336sewardj      case CC_OP_INCB:   ACTIONS_INC(  8, UChar  );
452a238471814bd386aeb58a76718b41e68b1a794b2sewardj      case CC_OP_INCW:   ACTIONS_INC( 16, UShort );
4538c7f1abe9e022f6382634efea09c9cac89ec6336sewardj      case CC_OP_INCL:   ACTIONS_INC( 32, UInt   );
4541813dbeb912870e9a544cae17a3fadbf8d2b0d55sewardj
4558c7f1abe9e022f6382634efea09c9cac89ec6336sewardj      case CC_OP_DECB:   ACTIONS_DEC(  8, UChar  );
456a238471814bd386aeb58a76718b41e68b1a794b2sewardj      case CC_OP_DECW:   ACTIONS_DEC( 16, UShort );
4578c7f1abe9e022f6382634efea09c9cac89ec6336sewardj      case CC_OP_DECL:   ACTIONS_DEC( 32, UInt   );
4588c7f1abe9e022f6382634efea09c9cac89ec6336sewardj
4598c7f1abe9e022f6382634efea09c9cac89ec6336sewardj      case CC_OP_SHLB:   ACTIONS_SHL(  8, UChar  );
4608c7f1abe9e022f6382634efea09c9cac89ec6336sewardj      case CC_OP_SHLW:   ACTIONS_SHL( 16, UShort );
4618c7f1abe9e022f6382634efea09c9cac89ec6336sewardj      case CC_OP_SHLL:   ACTIONS_SHL( 32, UInt   );
4628c7f1abe9e022f6382634efea09c9cac89ec6336sewardj
4638c7f1abe9e022f6382634efea09c9cac89ec6336sewardj      case CC_OP_SARB:   ACTIONS_SAR(  8, UChar  );
4648c7f1abe9e022f6382634efea09c9cac89ec6336sewardj      case CC_OP_SARW:   ACTIONS_SAR( 16, UShort );
4658c7f1abe9e022f6382634efea09c9cac89ec6336sewardj      case CC_OP_SARL:   ACTIONS_SAR( 32, UInt   );
4661813dbeb912870e9a544cae17a3fadbf8d2b0d55sewardj
4678c7f1abe9e022f6382634efea09c9cac89ec6336sewardj      case CC_OP_ROLB:   ACTIONS_ROL(  8, UChar  );
4688c7f1abe9e022f6382634efea09c9cac89ec6336sewardj      case CC_OP_ROLW:   ACTIONS_ROL( 16, UShort );
4698c7f1abe9e022f6382634efea09c9cac89ec6336sewardj      case CC_OP_ROLL:   ACTIONS_ROL( 32, UInt   );
470750f407b6be1aac303964a219acf0a6de8b8c4dasewardj
4718c7f1abe9e022f6382634efea09c9cac89ec6336sewardj      case CC_OP_RORB:   ACTIONS_ROR(  8, UChar  );
472a238471814bd386aeb58a76718b41e68b1a794b2sewardj      case CC_OP_RORW:   ACTIONS_ROR( 16, UShort );
4738c7f1abe9e022f6382634efea09c9cac89ec6336sewardj      case CC_OP_RORL:   ACTIONS_ROR( 32, UInt   );
4747ed2295459ac5e788a98dd5570fef0d4645c27d4sewardj
475b81f8b3e9110a5608094b8ec1a5c6d3c30a8e5aesewardj      case CC_OP_UMULB:  ACTIONS_UMUL(  8, UChar,  UShort );
476b81f8b3e9110a5608094b8ec1a5c6d3c30a8e5aesewardj      case CC_OP_UMULW:  ACTIONS_UMUL( 16, UShort, UInt   );
477b81f8b3e9110a5608094b8ec1a5c6d3c30a8e5aesewardj      case CC_OP_UMULL:  ACTIONS_UMUL( 32, UInt,   ULong  );
47856296d80c9e15ec59eebecf1c3aea9ebd4dac115sewardj
479b81f8b3e9110a5608094b8ec1a5c6d3c30a8e5aesewardj      case CC_OP_SMULB:  ACTIONS_SMUL(  8, Char,  Short );
480b81f8b3e9110a5608094b8ec1a5c6d3c30a8e5aesewardj      case CC_OP_SMULW:  ACTIONS_SMUL( 16, Short, Int   );
481b81f8b3e9110a5608094b8ec1a5c6d3c30a8e5aesewardj      case CC_OP_SMULL:  ACTIONS_SMUL( 32, Int,   Long  );
482741153c4301023a420ab45b8a10b8e1bac968822sewardj
48336ca51378f8851635df814230fa23f2c409b9eddsewardj      default:
48436ca51378f8851635df814230fa23f2c409b9eddsewardj         /* shouldn't really make these calls from generated code */
48514731f22bf7759d6d23383ca870ac89d9581f1e9sewardj         vex_printf("calculate_eflags_all( %d, 0x%x, 0x%x )\n",
486df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj                    cc_op, cc_src_formal, cc_dst_formal );
48736ca51378f8851635df814230fa23f2c409b9eddsewardj         vpanic("calculate_eflags_all");
48836ca51378f8851635df814230fa23f2c409b9eddsewardj   }
48936ca51378f8851635df814230fa23f2c409b9eddsewardj}
49036ca51378f8851635df814230fa23f2c409b9eddsewardj
491b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
4926e9964d701fda887cddd0fd579fc27fd18bbfc0fsewardj/* CALLED FROM GENERATED CODE */
493b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/* Calculate just the carry flag from the supplied thunk parameters. */
49436ca51378f8851635df814230fa23f2c409b9eddsewardjstatic UInt calculate_eflags_c ( UInt cc_op, UInt cc_src, UInt cc_dst )
49536ca51378f8851635df814230fa23f2c409b9eddsewardj{
4969eab588e223e52b1e7b710ff1c0da7b032ab2837sewardj   /* Fast-case some common ones. */
4979eab588e223e52b1e7b710ff1c0da7b032ab2837sewardj   if (cc_op == CC_OP_LOGICL)
4989eab588e223e52b1e7b710ff1c0da7b032ab2837sewardj      return 0;
4999eab588e223e52b1e7b710ff1c0da7b032ab2837sewardj   if (cc_op == CC_OP_DECL)
5009eab588e223e52b1e7b710ff1c0da7b032ab2837sewardj      return cc_src;
5019eab588e223e52b1e7b710ff1c0da7b032ab2837sewardj
50284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  if PROFILE_EFLAGS
50384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   if (!initted)
50484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      initCounts();
50584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   tabc[cc_op]++;
50684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
50784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   n_calc_c++;
50884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  endif
50936ca51378f8851635df814230fa23f2c409b9eddsewardj   return calculate_eflags_all(cc_op,cc_src,cc_dst) & CC_MASK_C;
51036ca51378f8851635df814230fa23f2c409b9eddsewardj}
51136ca51378f8851635df814230fa23f2c409b9eddsewardj
51236ca51378f8851635df814230fa23f2c409b9eddsewardj
51384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj/* CALLED FROM GENERATED CODE */
51484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj/* returns 1 or 0 */
51584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj/*static*/ UInt calculate_condition ( UInt/*Condcode*/ cond,
51684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj                                      UInt cc_op, UInt cc_src, UInt cc_dst )
51784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj{
51884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   UInt eflags = calculate_eflags_all(cc_op, cc_src, cc_dst);
51984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   UInt of,sf,zf,cf,pf;
52084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   UInt inv = cond & 1;
52184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
52284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  if PROFILE_EFLAGS
52384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   if (!initted)
52484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj     initCounts();
52584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
52684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   tab[cc_op][cond]++;
52784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   n_calc_cond++;
52884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
52946ccb51aff085d180120d310c0be2fe6c86e1b65sewardj   if (0 == ((n_calc_all+n_calc_c) & 0x3FFF)) showCounts();
53084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  endif
53184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
53284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   switch (cond) {
53384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      case CondNO:
53484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      case CondO: /* OF == 1 */
53584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         of = eflags >> CC_SHIFT_O;
53684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return 1 & (inv ^ of);
53784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
53884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      case CondNZ:
53984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      case CondZ: /* ZF == 1 */
54084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         zf = eflags >> CC_SHIFT_Z;
54184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return 1 & (inv ^ zf);
54284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
54384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      case CondNB:
54484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      case CondB: /* CF == 1 */
54584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         cf = eflags >> CC_SHIFT_C;
54684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return 1 & (inv ^ cf);
54784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         break;
54884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
54984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      case CondNBE:
55084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      case CondBE: /* (CF or ZF) == 1 */
55184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         cf = eflags >> CC_SHIFT_C;
55284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         zf = eflags >> CC_SHIFT_Z;
55384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return 1 & (inv ^ (cf | zf));
55484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         break;
55584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
55684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      case CondNS:
55784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      case CondS: /* SF == 1 */
55884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         sf = eflags >> CC_SHIFT_S;
55984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return 1 & (inv ^ sf);
56084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
56184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      case CondNP:
56284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      case CondP: /* PF == 1 */
56384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         pf = eflags >> CC_SHIFT_P;
56484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return 1 & (inv ^ pf);
56584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
56684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      case CondNL:
56784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      case CondL: /* (SF xor OF) == 1 */
56884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         sf = eflags >> CC_SHIFT_S;
56984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         of = eflags >> CC_SHIFT_O;
57084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return 1 & (inv ^ (sf ^ of));
57184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         break;
57284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
57384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      case CondNLE:
57484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      case CondLE: /* ((SF xor OF) or ZF)  == 1 */
57584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         sf = eflags >> CC_SHIFT_S;
57684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         of = eflags >> CC_SHIFT_O;
57784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         zf = eflags >> CC_SHIFT_Z;
57884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return 1 & (inv ^ ((sf ^ of) | zf));
57984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         break;
58084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
58184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      default:
58284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         /* shouldn't really make these calls from generated code */
58384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         vex_printf("calculate_condition( %d, %d, 0x%x, 0x%x )\n",
58484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj                    cond, cc_op, cc_src, cc_dst );
58584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         vpanic("calculate_condition");
58684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   }
58784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj}
58884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
58984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
59036ca51378f8851635df814230fa23f2c409b9eddsewardjAddr64 x86guest_findhelper ( Char* function_name )
59136ca51378f8851635df814230fa23f2c409b9eddsewardj{
59284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   if (vex_streq(function_name, "calculate_condition"))
59384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      return (Addr64)(& calculate_condition);
59417442fe8094d0f82266e5a05509f62cac8f7539esewardj   if (vex_streq(function_name, "calculate_eflags_c"))
59517442fe8094d0f82266e5a05509f62cac8f7539esewardj      return (Addr64)(& calculate_eflags_c);
59617442fe8094d0f82266e5a05509f62cac8f7539esewardj   if (vex_streq(function_name, "calculate_eflags_all"))
59717442fe8094d0f82266e5a05509f62cac8f7539esewardj      return (Addr64)(& calculate_eflags_all);
598c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   if (vex_streq(function_name, "calculate_FXAM"))
599c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      return (Addr64)(& calculate_FXAM);
60017442fe8094d0f82266e5a05509f62cac8f7539esewardj   if (vex_streq(function_name, "storeF80le"))
60117442fe8094d0f82266e5a05509f62cac8f7539esewardj      return (Addr64)(& storeF80le);
60217442fe8094d0f82266e5a05509f62cac8f7539esewardj   if (vex_streq(function_name, "loadF80le"))
60317442fe8094d0f82266e5a05509f62cac8f7539esewardj      return (Addr64)(& loadF80le);
60436ca51378f8851635df814230fa23f2c409b9eddsewardj   vex_printf("\nx86 guest: can't find helper: %s\n", function_name);
60536ca51378f8851635df814230fa23f2c409b9eddsewardj   vpanic("x86guest_findhelper");
60636ca51378f8851635df814230fa23f2c409b9eddsewardj}
60736ca51378f8851635df814230fa23f2c409b9eddsewardj
60884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj/* Used by the optimiser to try specialisations.  Returns an
60984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   equivalent expression, or NULL if none. */
61084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
61184ff0657940e62f38e618ea18bac6f27ce0e741fsewardjstatic Bool isU32 ( IRExpr* e, UInt n )
61284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj{
61384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   return e->tag == Iex_Const
61484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj          && e->Iex.Const.con->tag == Ico_U32
61584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj          && e->Iex.Const.con->Ico.U32 == n;
61684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj}
61784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
61884ff0657940e62f38e618ea18bac6f27ce0e741fsewardjIRExpr* x86guest_spechelper ( Char* function_name,
61984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj                              IRExpr** args )
62084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj{
62184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  define unop(_op,_a1) IRExpr_Unop((_op),(_a1))
62284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  define binop(_op,_a1,_a2) IRExpr_Binop((_op),(_a1),(_a2))
62384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  define mkU32(_n) IRExpr_Const(IRConst_U32(_n))
62484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
62584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   Int i, arity = 0;
62684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   for (i = 0; args[i]; i++)
62784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      arity++;
62884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  if 0
62984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   vex_printf("spec request:\n");
63084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   vex_printf("   %s  ", function_name);
63184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   for (i = 0; i < arity; i++) {
63284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      vex_printf("  ");
63384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      ppIRExpr(args[i]);
63484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   }
63584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   vex_printf("\n");
63684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  endif
63784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
63884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   if (vex_streq(function_name, "calculate_eflags_c")) {
63984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      /* specialise calls to above "calculate_eflags_c" function */
64084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      IRExpr *cc_op, *cc_src, *cc_dst;
64184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      vassert(arity == 3);
64284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      cc_op = args[0];
64384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      cc_src = args[1];
64484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      cc_dst = args[2];
64584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
64684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      if (isU32(cc_op, CC_OP_LOGICL)) {
64784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         /* cflag after logic is zero */
64884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return mkU32(0);
64984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
65084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      if (isU32(cc_op, CC_OP_DECL) || isU32(cc_op, CC_OP_INCL)) {
65184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         /* If the thunk is dec or inc, the cflag is supplied as CC_SRC. */
65284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return cc_src;
65384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
65484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      if (isU32(cc_op, CC_OP_SUBL)) {
65584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         /* C after sub denotes unsigned less than */
65684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return unop(Iop_1Uto32,
657b9c5cf639b3b21b972599d27207a033afc76ef67sewardj                     binop(Iop_CmpLT32U, cc_dst, cc_src));
65884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
659b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
66084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#     if 0
66184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      if (cc_op->tag == Iex_Const) {
66284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         vex_printf("CFLAG "); ppIRExpr(cc_op); vex_printf("\n");
66384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
66484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#     endif
66584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
66684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      return NULL;
66784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   }
66884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
66984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   if (vex_streq(function_name, "calculate_condition")) {
67084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      /* specialise calls to above "calculate condition" function */
67184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      IRExpr *cond, *cc_op, *cc_src, *cc_dst;
67284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      vassert(arity == 4);
67384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      cond = args[0];
67484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      cc_op = args[1];
67584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      cc_src = args[2];
67684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      cc_dst = args[3];
67784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
67846ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      /*---------------- SUBL ----------------*/
67946ccb51aff085d180120d310c0be2fe6c86e1b65sewardj
68046ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      if (isU32(cc_op, CC_OP_SUBL) && isU32(cond, CondZ)) {
68146ccb51aff085d180120d310c0be2fe6c86e1b65sewardj         /* long sub/cmp, then Z --> test dst==src */
68284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return unop(Iop_1Uto32,
68346ccb51aff085d180120d310c0be2fe6c86e1b65sewardj                     binop(Iop_CmpEQ32, cc_dst, cc_src));
68446ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      }
68546ccb51aff085d180120d310c0be2fe6c86e1b65sewardj
68646ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      if (isU32(cc_op, CC_OP_SUBL) && isU32(cond, CondL)) {
68746ccb51aff085d180120d310c0be2fe6c86e1b65sewardj         /* long sub/cmp, then L (signed less than)
68846ccb51aff085d180120d310c0be2fe6c86e1b65sewardj            --> test dst <s src */
68946ccb51aff085d180120d310c0be2fe6c86e1b65sewardj         return unop(Iop_1Uto32,
69046ccb51aff085d180120d310c0be2fe6c86e1b65sewardj                     binop(Iop_CmpLT32S, cc_dst, cc_src));
69146ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      }
69246ccb51aff085d180120d310c0be2fe6c86e1b65sewardj
69346ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      if (isU32(cc_op, CC_OP_SUBL) && isU32(cond, CondLE)) {
69446ccb51aff085d180120d310c0be2fe6c86e1b65sewardj         /* long sub/cmp, then LE (signed less than or equal)
69546ccb51aff085d180120d310c0be2fe6c86e1b65sewardj            --> test dst <=s src */
69646ccb51aff085d180120d310c0be2fe6c86e1b65sewardj         return unop(Iop_1Uto32,
69746ccb51aff085d180120d310c0be2fe6c86e1b65sewardj                     binop(Iop_CmpLE32S, cc_dst, cc_src));
69846ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      }
69946ccb51aff085d180120d310c0be2fe6c86e1b65sewardj
70046ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      if (isU32(cc_op, CC_OP_SUBL) && isU32(cond, CondBE)) {
70146ccb51aff085d180120d310c0be2fe6c86e1b65sewardj         /* long sub/cmp, then BE (unsigned less than or equal)
70246ccb51aff085d180120d310c0be2fe6c86e1b65sewardj            --> test dst <=u src */
70346ccb51aff085d180120d310c0be2fe6c86e1b65sewardj         return unop(Iop_1Uto32,
70446ccb51aff085d180120d310c0be2fe6c86e1b65sewardj                     binop(Iop_CmpLE32U, cc_dst, cc_src));
70546ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      }
70646ccb51aff085d180120d310c0be2fe6c86e1b65sewardj
70746ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      if (isU32(cc_op, CC_OP_SUBL) && isU32(cond, CondB)) {
70846ccb51aff085d180120d310c0be2fe6c86e1b65sewardj         /* long sub/cmp, then B (unsigned less than)
70946ccb51aff085d180120d310c0be2fe6c86e1b65sewardj            --> test dst <u src */
71046ccb51aff085d180120d310c0be2fe6c86e1b65sewardj         return unop(Iop_1Uto32,
71146ccb51aff085d180120d310c0be2fe6c86e1b65sewardj                     binop(Iop_CmpLT32U, cc_dst, cc_src));
71284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
71384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
71446ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      /*---------------- SUBW ----------------*/
71546ccb51aff085d180120d310c0be2fe6c86e1b65sewardj
716b9c5cf639b3b21b972599d27207a033afc76ef67sewardj      if (isU32(cc_op, CC_OP_SUBW) && isU32(cond, CondZ)) {
717b9c5cf639b3b21b972599d27207a033afc76ef67sewardj         /* byte sub/cmp, then Z --> test dst==src */
718b9c5cf639b3b21b972599d27207a033afc76ef67sewardj         return unop(Iop_1Uto32,
719b9c5cf639b3b21b972599d27207a033afc76ef67sewardj                     binop(Iop_CmpEQ16,
720b9c5cf639b3b21b972599d27207a033afc76ef67sewardj                           unop(Iop_32to16,cc_dst),
721b9c5cf639b3b21b972599d27207a033afc76ef67sewardj                           unop(Iop_32to16,cc_src)));
722b9c5cf639b3b21b972599d27207a033afc76ef67sewardj      }
723b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
72446ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      /*---------------- SUBB ----------------*/
72546ccb51aff085d180120d310c0be2fe6c86e1b65sewardj
72684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      if (isU32(cc_op, CC_OP_SUBB) && isU32(cond, CondZ)) {
727b9c5cf639b3b21b972599d27207a033afc76ef67sewardj         /* byte sub/cmp, then Z --> test dst==src */
72884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return unop(Iop_1Uto32,
729b9c5cf639b3b21b972599d27207a033afc76ef67sewardj                     binop(Iop_CmpEQ8,
730b9c5cf639b3b21b972599d27207a033afc76ef67sewardj                           unop(Iop_32to8,cc_dst),
731b9c5cf639b3b21b972599d27207a033afc76ef67sewardj                           unop(Iop_32to8,cc_src)));
73284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
73384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
73484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      if (isU32(cc_op, CC_OP_SUBB) && isU32(cond, CondNZ)) {
735b9c5cf639b3b21b972599d27207a033afc76ef67sewardj         /* byte sub/cmp, then Z --> test dst!=src */
73684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return unop(Iop_1Uto32,
737b9c5cf639b3b21b972599d27207a033afc76ef67sewardj                     binop(Iop_CmpNE8,
738b9c5cf639b3b21b972599d27207a033afc76ef67sewardj                           unop(Iop_32to8,cc_dst),
739b9c5cf639b3b21b972599d27207a033afc76ef67sewardj                           unop(Iop_32to8,cc_src)));
740b9c5cf639b3b21b972599d27207a033afc76ef67sewardj      }
741b9c5cf639b3b21b972599d27207a033afc76ef67sewardj
742b9c5cf639b3b21b972599d27207a033afc76ef67sewardj      if (isU32(cc_op, CC_OP_SUBB) && isU32(cond, CondNBE)) {
743b9c5cf639b3b21b972599d27207a033afc76ef67sewardj         /* long sub/cmp, then NBE (unsigned greater than)
744b9c5cf639b3b21b972599d27207a033afc76ef67sewardj            --> test src <=u dst */
745b9c5cf639b3b21b972599d27207a033afc76ef67sewardj         return unop(Iop_1Uto32,
746b9c5cf639b3b21b972599d27207a033afc76ef67sewardj                     binop(Iop_CmpLT32U,
7476cd3a78ada41360f404ea124c4651eb80aef3ccfsewardj                           binop(Iop_And32,cc_src,mkU32(0xFF)),
7486cd3a78ada41360f404ea124c4651eb80aef3ccfsewardj			   binop(Iop_And32,cc_dst,mkU32(0xFF))));
74984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
75084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
75146ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      /*---------------- LOGICL ----------------*/
75246ccb51aff085d180120d310c0be2fe6c86e1b65sewardj
75384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      if (isU32(cc_op, CC_OP_LOGICL) && isU32(cond, CondZ)) {
75484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         /* long and/or/xor, then Z --> test dst==0 */
75584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return unop(Iop_1Uto32,binop(Iop_CmpEQ32, cc_dst, mkU32(0)));
75684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
75784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
758fae2ca7ef81549a4b28235618317d4352ca32ac2sewardj      if (isU32(cc_op, CC_OP_LOGICL) && isU32(cond, CondS)) {
759fae2ca7ef81549a4b28235618317d4352ca32ac2sewardj         /* long and/or/xor, then S --> test dst <s 0 */
760fae2ca7ef81549a4b28235618317d4352ca32ac2sewardj         return unop(Iop_1Uto32,binop(Iop_CmpLT32S, cc_dst, mkU32(0)));
761fae2ca7ef81549a4b28235618317d4352ca32ac2sewardj      }
762fae2ca7ef81549a4b28235618317d4352ca32ac2sewardj
76384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      if (isU32(cc_op, CC_OP_LOGICL) && isU32(cond, CondLE)) {
76484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         /* long and/or/xor, then LE
76584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj            This is pretty subtle.  LOGIC sets SF and ZF according to the
76684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj            result and makes OF be zero.  LE computes (SZ ^ OF) | ZF, but
76784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj            OF is zero, so this reduces to SZ | ZF -- which will be 1 iff
76884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj            the result is <=signed 0.  Hence ...
76984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         */
77084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return unop(Iop_1Uto32,binop(Iop_CmpLE32S, cc_dst, mkU32(0)));
77184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
77284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
77346ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      /*---------------- LOGICB ----------------*/
77484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
77546ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      if (isU32(cc_op, CC_OP_LOGICB) && isU32(cond, CondZ)) {
77646ccb51aff085d180120d310c0be2fe6c86e1b65sewardj         /* byte and/or/xor, then Z --> test dst==0 */
77784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return unop(Iop_1Uto32,
77846ccb51aff085d180120d310c0be2fe6c86e1b65sewardj                     binop(Iop_CmpEQ32, binop(Iop_And32,cc_dst,mkU32(255)),
77946ccb51aff085d180120d310c0be2fe6c86e1b65sewardj                                        mkU32(0)));
78084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
78184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
78246ccb51aff085d180120d310c0be2fe6c86e1b65sewardj      /*---------------- DECL ----------------*/
783af991dede2815b7570828b9d9174cf989e636254sewardj
78484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      if (isU32(cc_op, CC_OP_DECL) && isU32(cond, CondZ)) {
78584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         /* dec L, then Z --> test dst == 0 */
78684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj         return unop(Iop_1Uto32,binop(Iop_CmpEQ32, cc_dst, mkU32(0)));
78784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      }
78884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
789fae2ca7ef81549a4b28235618317d4352ca32ac2sewardj      if (isU32(cc_op, CC_OP_DECL) && isU32(cond, CondS)) {
790fae2ca7ef81549a4b28235618317d4352ca32ac2sewardj         /* dec L, then S --> compare DST <s 0 */
791fae2ca7ef81549a4b28235618317d4352ca32ac2sewardj         return unop(Iop_1Uto32,binop(Iop_CmpLT32S, cc_dst, mkU32(0)));
792fae2ca7ef81549a4b28235618317d4352ca32ac2sewardj      }
793fae2ca7ef81549a4b28235618317d4352ca32ac2sewardj
79484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      return NULL;
79584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   }
79684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
79784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  undef unop
79884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  undef binop
79984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#  undef mkU32
80084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
80184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   return NULL;
80284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj}
80384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
80436ca51378f8851635df814230fa23f2c409b9eddsewardj
8050c2cb623cca372a2b42b073121c7413cdaaf75besewardj/*-----------------------------------------------------------*/
8060c2cb623cca372a2b42b073121c7413cdaaf75besewardj/*--- Utility functions for x87 FPU conversions.          ---*/
8070c2cb623cca372a2b42b073121c7413cdaaf75besewardj/*-----------------------------------------------------------*/
8080c2cb623cca372a2b42b073121c7413cdaaf75besewardj
8090c2cb623cca372a2b42b073121c7413cdaaf75besewardj
8100c2cb623cca372a2b42b073121c7413cdaaf75besewardj/* 80 and 64-bit floating point formats:
8110c2cb623cca372a2b42b073121c7413cdaaf75besewardj
8120c2cb623cca372a2b42b073121c7413cdaaf75besewardj   80-bit:
8130c2cb623cca372a2b42b073121c7413cdaaf75besewardj
8140c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  0       0-------0      zero
8150c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  0       0X------X      denormals
8160c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  1-7FFE  1X------X      normals (all normals have leading 1)
8170c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  7FFF    10------0      infinity
8180c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  7FFF    10X-----X      snan
8190c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  7FFF    11X-----X      qnan
8200c2cb623cca372a2b42b073121c7413cdaaf75besewardj
8210c2cb623cca372a2b42b073121c7413cdaaf75besewardj   S is the sign bit.  For runs X----X, at least one of the Xs must be
8220c2cb623cca372a2b42b073121c7413cdaaf75besewardj   nonzero.  Exponent is 15 bits, fractional part is 63 bits, and
8230c2cb623cca372a2b42b073121c7413cdaaf75besewardj   there is an explicitly represented leading 1, and a sign bit,
8240c2cb623cca372a2b42b073121c7413cdaaf75besewardj   giving 80 in total.
8250c2cb623cca372a2b42b073121c7413cdaaf75besewardj
8260c2cb623cca372a2b42b073121c7413cdaaf75besewardj   64-bit avoids the confusion of an explicitly represented leading 1
8270c2cb623cca372a2b42b073121c7413cdaaf75besewardj   and so is simpler:
8280c2cb623cca372a2b42b073121c7413cdaaf75besewardj
8290c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  0      0------0   zero
8300c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  0      X------X   denormals
8310c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  1-7FE  any        normals
8320c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  7FF    0------0   infinity
8330c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  7FF    0X-----X   snan
8340c2cb623cca372a2b42b073121c7413cdaaf75besewardj    S  7FF    1X-----X   qnan
8350c2cb623cca372a2b42b073121c7413cdaaf75besewardj
8360c2cb623cca372a2b42b073121c7413cdaaf75besewardj   Exponent is 11 bits, fractional part is 52 bits, and there is a
8370c2cb623cca372a2b42b073121c7413cdaaf75besewardj   sign bit, giving 64 in total.
8380c2cb623cca372a2b42b073121c7413cdaaf75besewardj*/
8390c2cb623cca372a2b42b073121c7413cdaaf75besewardj
840c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardjstatic inline Bool host_is_little_endian ( void )
841c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj{
842c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   UInt x = 0x76543210;
843c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   UChar* p = (UChar*)(&x);
844c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   return (*p == 0x10);
845c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj}
846c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
84717442fe8094d0f82266e5a05509f62cac8f7539esewardjstatic UInt calculate_FXAM ( UInt tag, ULong dbl )
848c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj{
849c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   Bool   mantissaIsZero;
850c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   Int    bexp;
851c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   UChar  sign;
852c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   UInt   c1;
853c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   UChar* f64;
854c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
855f5e36670bf70ac2d23f6336d7f46889bf996cfdfsewardj   if (!host_is_little_endian()) {
856c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      vassert(0);
857c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   }
858c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
859c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   /* vex_printf("calculate_FXAM ( %d, %llx ) .. ", tag, dbl ); */
860c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
861c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   f64  = (UChar*)(&dbl);
862c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   sign = (f64[7] >> 7) & 1;
863c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
864c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   /* First off, if the tag indicates the register was empty,
865c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      return 1,0,sign,1 */
866c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   if (tag == 0) {
867c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      /* vex_printf("Empty\n"); */
868c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      return FC_MASK_C3 | 0 | sign | FC_MASK_C0;
869c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   }
870c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
871c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   bexp = (f64[7] << 4) | ((f64[6] >> 4) & 0x0F);
872c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   bexp &= 0x7FF;
873c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
874c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   c1 = ((UInt)sign) << 9;
875c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
876c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   mantissaIsZero
877c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      = (f64[6] & 0x0F) == 0
878c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj        && (f64[5] | f64[4] | f64[3] | f64[2] | f64[1] | f64[0]) == 0;
879c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
880c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   /* If both exponent and mantissa are zero, the value is zero.
881c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      Return 1,0,sign,0. */
882c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   if (bexp == 0 && mantissaIsZero) {
883c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      /* vex_printf("Zero\n"); */
884c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      return FC_MASK_C3 | 0 | sign | 0;
885c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   }
886c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
887c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   /* If exponent is zero but mantissa isn't, it's a denormal.
888c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      Return 1,1,sign,0. */
889c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   if (bexp == 0 && !mantissaIsZero) {
890c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      /* vex_printf("Denormal\n"); */
891c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      return FC_MASK_C3 | FC_MASK_C2 | sign | 0;
892c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   }
893c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
894c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   /* If the exponent is 7FF and the mantissa is zero, this is an infinity.
895c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      Return 0,1,sign,1. */
896c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   if (bexp == 0x7FF && mantissaIsZero) {
897c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      /* vex_printf("Inf\n"); */
898c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      return 0 | FC_MASK_C2 | sign | FC_MASK_C0;
899c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   }
900c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
901c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   /* If the exponent is 7FF and the mantissa isn't zero, this is a NaN.
902c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      Return 0,0,sign,1. */
903c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   if (bexp == 0x7FF && !mantissaIsZero) {
904c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      /* vex_printf("NaN\n"); */
905c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      return 0 | 0 | sign | FC_MASK_C0;
906c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   }
907c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
908c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   /* Uh, ok, we give up.  It must be a normal finite number.
909c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj      Return 0,1,sign,0.
910c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   */
911c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   /* vex_printf("normal\n"); */
912c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   return 0 | FC_MASK_C2 | sign | 0;
913c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj}
914c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj
9150c2cb623cca372a2b42b073121c7413cdaaf75besewardj
9160c2cb623cca372a2b42b073121c7413cdaaf75besewardj/* Convert a IEEE754 double (64-bit) into an x87 extended double
9170c2cb623cca372a2b42b073121c7413cdaaf75besewardj   (80-bit), mimicing the hardware fairly closely.  Both numbers are
9180c2cb623cca372a2b42b073121c7413cdaaf75besewardj   stored little-endian.  Limitations, all of which could be fixed,
9190c2cb623cca372a2b42b073121c7413cdaaf75besewardj   given some level of hassle:
9200c2cb623cca372a2b42b073121c7413cdaaf75besewardj
9210c2cb623cca372a2b42b073121c7413cdaaf75besewardj   * Does not handle double precision denormals.  As a result, values
9220c2cb623cca372a2b42b073121c7413cdaaf75besewardj     with magnitudes less than 1e-308 are flushed to zero when they
9230c2cb623cca372a2b42b073121c7413cdaaf75besewardj     need not be.
9240c2cb623cca372a2b42b073121c7413cdaaf75besewardj
9250c2cb623cca372a2b42b073121c7413cdaaf75besewardj   * Identity of NaNs is not preserved.
9260c2cb623cca372a2b42b073121c7413cdaaf75besewardj
9270c2cb623cca372a2b42b073121c7413cdaaf75besewardj   See comments in the code for more details.
9280c2cb623cca372a2b42b073121c7413cdaaf75besewardj*/
9290c2cb623cca372a2b42b073121c7413cdaaf75besewardjstatic void convert_f64le_to_f80le ( /*IN*/UChar* f64, /*OUT*/UChar* f80 )
9300c2cb623cca372a2b42b073121c7413cdaaf75besewardj{
9310c2cb623cca372a2b42b073121c7413cdaaf75besewardj   Bool  isInf;
9320c2cb623cca372a2b42b073121c7413cdaaf75besewardj   Int   bexp;
9330c2cb623cca372a2b42b073121c7413cdaaf75besewardj   UChar sign;
9340c2cb623cca372a2b42b073121c7413cdaaf75besewardj
9350c2cb623cca372a2b42b073121c7413cdaaf75besewardj   sign = (f64[7] >> 7) & 1;
9360c2cb623cca372a2b42b073121c7413cdaaf75besewardj   bexp = (f64[7] << 4) | ((f64[6] >> 4) & 0x0F);
9370c2cb623cca372a2b42b073121c7413cdaaf75besewardj   bexp &= 0x7FF;
9380c2cb623cca372a2b42b073121c7413cdaaf75besewardj
9390c2cb623cca372a2b42b073121c7413cdaaf75besewardj   /* If the exponent is zero, either we have a zero or a denormal.
9400c2cb623cca372a2b42b073121c7413cdaaf75besewardj      Produce a zero.  This is a hack in that it forces denormals to
9410c2cb623cca372a2b42b073121c7413cdaaf75besewardj      zero.  Could do better. */
9420c2cb623cca372a2b42b073121c7413cdaaf75besewardj   if (bexp == 0) {
9430c2cb623cca372a2b42b073121c7413cdaaf75besewardj      f80[9] = sign << 7;
9440c2cb623cca372a2b42b073121c7413cdaaf75besewardj      f80[8] = f80[7] = f80[6] = f80[5] = f80[4]
9450c2cb623cca372a2b42b073121c7413cdaaf75besewardj             = f80[3] = f80[2] = f80[1] = f80[0] = 0;
9460c2cb623cca372a2b42b073121c7413cdaaf75besewardj      return;
9470c2cb623cca372a2b42b073121c7413cdaaf75besewardj   }
9480c2cb623cca372a2b42b073121c7413cdaaf75besewardj
9490c2cb623cca372a2b42b073121c7413cdaaf75besewardj   /* If the exponent is 7FF, this is either an Infinity, a SNaN or
9500c2cb623cca372a2b42b073121c7413cdaaf75besewardj      QNaN, as determined by examining bits 51:0, thus:
9510c2cb623cca372a2b42b073121c7413cdaaf75besewardj          0  ... 0    Inf
9520c2cb623cca372a2b42b073121c7413cdaaf75besewardj          0X ... X    SNaN
9530c2cb623cca372a2b42b073121c7413cdaaf75besewardj          1X ... X    QNaN
9540c2cb623cca372a2b42b073121c7413cdaaf75besewardj      where at least one of the Xs is not zero.
9550c2cb623cca372a2b42b073121c7413cdaaf75besewardj   */
9560c2cb623cca372a2b42b073121c7413cdaaf75besewardj   if (bexp == 0x7FF) {
9570c2cb623cca372a2b42b073121c7413cdaaf75besewardj      isInf = (f64[6] & 0x0F) == 0
9580c2cb623cca372a2b42b073121c7413cdaaf75besewardj              && f64[5] == 0 && f64[4] == 0 && f64[3] == 0
9590c2cb623cca372a2b42b073121c7413cdaaf75besewardj              && f64[2] == 0 && f64[1] == 0 && f64[0] == 0;
9600c2cb623cca372a2b42b073121c7413cdaaf75besewardj      if (isInf) {
9610c2cb623cca372a2b42b073121c7413cdaaf75besewardj         /* Produce an appropriately signed infinity:
9620c2cb623cca372a2b42b073121c7413cdaaf75besewardj            S 1--1 (15)  1  0--0 (63)
9630c2cb623cca372a2b42b073121c7413cdaaf75besewardj         */
9640c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f80[9] = (sign << 7) | 0x7F;
9650c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f80[8] = 0xFF;
9660c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f80[7] = 0x80;
9670c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f80[6] = f80[5] = f80[4] = f80[3]
9680c2cb623cca372a2b42b073121c7413cdaaf75besewardj                = f80[2] = f80[1] = f80[0] = 0;
9690c2cb623cca372a2b42b073121c7413cdaaf75besewardj         return;
9700c2cb623cca372a2b42b073121c7413cdaaf75besewardj      }
9710c2cb623cca372a2b42b073121c7413cdaaf75besewardj      /* So it's either a QNaN or SNaN.  Distinguish by considering
9720c2cb623cca372a2b42b073121c7413cdaaf75besewardj         bit 51.  Note, this destroys all the trailing bits
9730c2cb623cca372a2b42b073121c7413cdaaf75besewardj         (identity?) of the NaN.  IEEE754 doesn't require preserving
9740c2cb623cca372a2b42b073121c7413cdaaf75besewardj         these (it only requires that there be one QNaN value and one
9750c2cb623cca372a2b42b073121c7413cdaaf75besewardj         SNaN value), but x87 does seem to have some ability to
9760c2cb623cca372a2b42b073121c7413cdaaf75besewardj         preserve them.  Anyway, here, the NaN's identity is
9770c2cb623cca372a2b42b073121c7413cdaaf75besewardj         destroyed.  Could be improved. */
9780c2cb623cca372a2b42b073121c7413cdaaf75besewardj      if (f64[6] & 8) {
9790c2cb623cca372a2b42b073121c7413cdaaf75besewardj         /* QNaN.  Make a QNaN:
9800c2cb623cca372a2b42b073121c7413cdaaf75besewardj            S 1--1 (15)  1  1--1 (63)
9810c2cb623cca372a2b42b073121c7413cdaaf75besewardj         */
9820c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f80[9] = (sign << 7) | 0x7F;
9830c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f80[8] = 0xFF;
9840c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f80[7] = 0xFF;
9850c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f80[6] = f80[5] = f80[4] = f80[3]
9860c2cb623cca372a2b42b073121c7413cdaaf75besewardj                = f80[2] = f80[1] = f80[0] = 0xFF;
9870c2cb623cca372a2b42b073121c7413cdaaf75besewardj      } else {
9880c2cb623cca372a2b42b073121c7413cdaaf75besewardj         /* SNaN.  Make a SNaN:
9890c2cb623cca372a2b42b073121c7413cdaaf75besewardj            S 1--1 (15)  0  1--1 (63)
9900c2cb623cca372a2b42b073121c7413cdaaf75besewardj         */
9910c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f80[9] = (sign << 7) | 0x7F;
9920c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f80[8] = 0xFF;
9930c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f80[7] = 0x7F;
9940c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f80[6] = f80[5] = f80[4] = f80[3]
9950c2cb623cca372a2b42b073121c7413cdaaf75besewardj                = f80[2] = f80[1] = f80[0] = 0xFF;
9960c2cb623cca372a2b42b073121c7413cdaaf75besewardj      }
9970c2cb623cca372a2b42b073121c7413cdaaf75besewardj      return;
9980c2cb623cca372a2b42b073121c7413cdaaf75besewardj   }
9990c2cb623cca372a2b42b073121c7413cdaaf75besewardj
10000c2cb623cca372a2b42b073121c7413cdaaf75besewardj   /* It's not a zero, denormal, infinity or nan.  So it must be a
10010c2cb623cca372a2b42b073121c7413cdaaf75besewardj      normalised number.  Rebias the exponent and build the new
10020c2cb623cca372a2b42b073121c7413cdaaf75besewardj      number.  */
10030c2cb623cca372a2b42b073121c7413cdaaf75besewardj   bexp += (16383 - 1023);
10040c2cb623cca372a2b42b073121c7413cdaaf75besewardj
10050c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f80[9] = (sign << 7) | ((bexp >> 8) & 0xFF);
10060c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f80[8] = bexp & 0xFF;
10070c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f80[7] = (1 << 7) | ((f64[6] << 3) & 0x78) | ((f64[5] >> 5) & 7);
10080c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f80[6] = ((f64[5] << 3) & 0xF8) | ((f64[4] >> 5) & 7);
10090c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f80[5] = ((f64[4] << 3) & 0xF8) | ((f64[3] >> 5) & 7);
10100c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f80[4] = ((f64[3] << 3) & 0xF8) | ((f64[2] >> 5) & 7);
10110c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f80[3] = ((f64[2] << 3) & 0xF8) | ((f64[1] >> 5) & 7);
10120c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f80[2] = ((f64[1] << 3) & 0xF8) | ((f64[0] >> 5) & 7);
10130c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f80[1] = ((f64[0] << 3) & 0xF8);
10140c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f80[0] = 0;
10150c2cb623cca372a2b42b073121c7413cdaaf75besewardj}
10160c2cb623cca372a2b42b073121c7413cdaaf75besewardj
10170c2cb623cca372a2b42b073121c7413cdaaf75besewardj
10180c2cb623cca372a2b42b073121c7413cdaaf75besewardj/////////////////////////////////////////////////////////////////
10190c2cb623cca372a2b42b073121c7413cdaaf75besewardj
10200c2cb623cca372a2b42b073121c7413cdaaf75besewardj/* Convert a x87 extended double (80-bit) into an IEEE 754 double
10210c2cb623cca372a2b42b073121c7413cdaaf75besewardj   (64-bit), mimicing the hardware fairly closely.  Both numbers are
10220c2cb623cca372a2b42b073121c7413cdaaf75besewardj   stored little-endian.  Limitations, all of which could be fixed,
10230c2cb623cca372a2b42b073121c7413cdaaf75besewardj   given some level of hassle:
10240c2cb623cca372a2b42b073121c7413cdaaf75besewardj
10250c2cb623cca372a2b42b073121c7413cdaaf75besewardj   * Does not create double precision denormals.  As a result, values
10260c2cb623cca372a2b42b073121c7413cdaaf75besewardj     with magnitudes less than 1e-308 are flushed to zero when they
10270c2cb623cca372a2b42b073121c7413cdaaf75besewardj     need not be.
10280c2cb623cca372a2b42b073121c7413cdaaf75besewardj
10290c2cb623cca372a2b42b073121c7413cdaaf75besewardj   * Rounding following truncation could be a bit better.
10300c2cb623cca372a2b42b073121c7413cdaaf75besewardj
10310c2cb623cca372a2b42b073121c7413cdaaf75besewardj   * Identity of NaNs is not preserved.
10320c2cb623cca372a2b42b073121c7413cdaaf75besewardj
10330c2cb623cca372a2b42b073121c7413cdaaf75besewardj   See comments in the code for more details.
10340c2cb623cca372a2b42b073121c7413cdaaf75besewardj*/
10350c2cb623cca372a2b42b073121c7413cdaaf75besewardjstatic void convert_f80le_to_f64le ( /*IN*/UChar* f80, /*OUT*/UChar* f64 )
10360c2cb623cca372a2b42b073121c7413cdaaf75besewardj{
10370c2cb623cca372a2b42b073121c7413cdaaf75besewardj   Bool  isInf;
10380c2cb623cca372a2b42b073121c7413cdaaf75besewardj   Int   bexp;
10390c2cb623cca372a2b42b073121c7413cdaaf75besewardj   UChar sign;
10400c2cb623cca372a2b42b073121c7413cdaaf75besewardj
10410c2cb623cca372a2b42b073121c7413cdaaf75besewardj   sign = (f80[9] >> 7) & 1;
10420c2cb623cca372a2b42b073121c7413cdaaf75besewardj   bexp = (((UInt)f80[9]) << 8) | (UInt)f80[8];
10430c2cb623cca372a2b42b073121c7413cdaaf75besewardj   bexp &= 0x7FFF;
10440c2cb623cca372a2b42b073121c7413cdaaf75besewardj
10450c2cb623cca372a2b42b073121c7413cdaaf75besewardj   /* If the exponent is zero, either we have a zero or a denormal.
10460c2cb623cca372a2b42b073121c7413cdaaf75besewardj      But an extended precision denormal becomes a double precision
10470c2cb623cca372a2b42b073121c7413cdaaf75besewardj      zero, so in either case, just produce the appropriately signed
10480c2cb623cca372a2b42b073121c7413cdaaf75besewardj      zero. */
10490c2cb623cca372a2b42b073121c7413cdaaf75besewardj   if (bexp == 0) {
10500c2cb623cca372a2b42b073121c7413cdaaf75besewardj      f64[7] = sign << 7;
10510c2cb623cca372a2b42b073121c7413cdaaf75besewardj      f64[6] = f64[5] = f64[4] = f64[3] = f64[2] = f64[1] = f64[0] = 0;
10520c2cb623cca372a2b42b073121c7413cdaaf75besewardj      return;
10530c2cb623cca372a2b42b073121c7413cdaaf75besewardj   }
10540c2cb623cca372a2b42b073121c7413cdaaf75besewardj
10550c2cb623cca372a2b42b073121c7413cdaaf75besewardj   /* If the exponent is 7FFF, this is either an Infinity, a SNaN or
10560c2cb623cca372a2b42b073121c7413cdaaf75besewardj      QNaN, as determined by examining bits 62:0, thus:
10570c2cb623cca372a2b42b073121c7413cdaaf75besewardj          0  ... 0    Inf
10580c2cb623cca372a2b42b073121c7413cdaaf75besewardj          0X ... X    SNaN
10590c2cb623cca372a2b42b073121c7413cdaaf75besewardj          1X ... X    QNaN
10600c2cb623cca372a2b42b073121c7413cdaaf75besewardj      where at least one of the Xs is not zero.
10610c2cb623cca372a2b42b073121c7413cdaaf75besewardj   */
10620c2cb623cca372a2b42b073121c7413cdaaf75besewardj   if (bexp == 0x7FFF) {
10630c2cb623cca372a2b42b073121c7413cdaaf75besewardj      isInf = (f80[7] & 0x7F) == 0
10640c2cb623cca372a2b42b073121c7413cdaaf75besewardj              && f80[6] == 0 && f80[5] == 0 && f80[4] == 0
10650c2cb623cca372a2b42b073121c7413cdaaf75besewardj              && f80[3] == 0 && f80[2] == 0 && f80[1] == 0 && f80[0] == 0;
10660c2cb623cca372a2b42b073121c7413cdaaf75besewardj      if (isInf) {
10670c2cb623cca372a2b42b073121c7413cdaaf75besewardj         if (0 == (f80[7] & 0x80))
10680c2cb623cca372a2b42b073121c7413cdaaf75besewardj            goto wierd_NaN;
10690c2cb623cca372a2b42b073121c7413cdaaf75besewardj         /* Produce an appropriately signed infinity:
10700c2cb623cca372a2b42b073121c7413cdaaf75besewardj            S 1--1 (11)  0--0 (52)
10710c2cb623cca372a2b42b073121c7413cdaaf75besewardj         */
10720c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f64[7] = (sign << 7) | 0x7F;
10730c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f64[6] = 0xF0;
10740c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f64[5] = f64[4] = f64[3] = f64[2] = f64[1] = f64[0] = 0;
10750c2cb623cca372a2b42b073121c7413cdaaf75besewardj         return;
10760c2cb623cca372a2b42b073121c7413cdaaf75besewardj      }
10770c2cb623cca372a2b42b073121c7413cdaaf75besewardj      /* So it's either a QNaN or SNaN.  Distinguish by considering
10780c2cb623cca372a2b42b073121c7413cdaaf75besewardj         bit 62.  Note, this destroys all the trailing bits
10790c2cb623cca372a2b42b073121c7413cdaaf75besewardj         (identity?) of the NaN.  IEEE754 doesn't require preserving
10800c2cb623cca372a2b42b073121c7413cdaaf75besewardj         these (it only requires that there be one QNaN value and one
10810c2cb623cca372a2b42b073121c7413cdaaf75besewardj         SNaN value), but x87 does seem to have some ability to
10820c2cb623cca372a2b42b073121c7413cdaaf75besewardj         preserve them.  Anyway, here, the NaN's identity is
10830c2cb623cca372a2b42b073121c7413cdaaf75besewardj         destroyed.  Could be improved. */
10840c2cb623cca372a2b42b073121c7413cdaaf75besewardj      if (f80[8] & 0x40) {
10850c2cb623cca372a2b42b073121c7413cdaaf75besewardj         /* QNaN.  Make a QNaN:
10860c2cb623cca372a2b42b073121c7413cdaaf75besewardj            S 1--1 (11)  1  1--1 (51)
10870c2cb623cca372a2b42b073121c7413cdaaf75besewardj         */
10880c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f64[7] = (sign << 7) | 0x7F;
10890c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f64[6] = 0xFF;
10900c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f64[5] = f64[4] = f64[3] = f64[2] = f64[1] = f64[0] = 0xFF;
10910c2cb623cca372a2b42b073121c7413cdaaf75besewardj      } else {
10920c2cb623cca372a2b42b073121c7413cdaaf75besewardj         /* SNaN.  Make a SNaN:
10930c2cb623cca372a2b42b073121c7413cdaaf75besewardj            S 1--1 (11)  0  1--1 (51)
10940c2cb623cca372a2b42b073121c7413cdaaf75besewardj         */
10950c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f64[7] = (sign << 7) | 0x7F;
10960c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f64[6] = 0xF7;
10970c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f64[5] = f64[4] = f64[3] = f64[2] = f64[1] = f64[0] = 0xFF;
10980c2cb623cca372a2b42b073121c7413cdaaf75besewardj      }
10990c2cb623cca372a2b42b073121c7413cdaaf75besewardj      return;
11000c2cb623cca372a2b42b073121c7413cdaaf75besewardj   }
11010c2cb623cca372a2b42b073121c7413cdaaf75besewardj
11020c2cb623cca372a2b42b073121c7413cdaaf75besewardj   /* If it's not a Zero, NaN or Inf, and the integer part (bit 62) is
11030c2cb623cca372a2b42b073121c7413cdaaf75besewardj      zero, the x87 FPU appears to consider the number denormalised
11040c2cb623cca372a2b42b073121c7413cdaaf75besewardj      and converts it to a QNaN. */
11050c2cb623cca372a2b42b073121c7413cdaaf75besewardj   if (0 == (f80[7] & 0x80)) {
11060c2cb623cca372a2b42b073121c7413cdaaf75besewardj      wierd_NaN:
11070c2cb623cca372a2b42b073121c7413cdaaf75besewardj      /* Strange hardware QNaN:
11080c2cb623cca372a2b42b073121c7413cdaaf75besewardj         S 1--1 (11)  1  0--0 (51)
11090c2cb623cca372a2b42b073121c7413cdaaf75besewardj      */
11100c2cb623cca372a2b42b073121c7413cdaaf75besewardj      /* On a PIII, these QNaNs always appear with sign==1.  I have
11110c2cb623cca372a2b42b073121c7413cdaaf75besewardj         no idea why. */
11120c2cb623cca372a2b42b073121c7413cdaaf75besewardj      f64[7] = (1 /*sign*/ << 7) | 0x7F;
11130c2cb623cca372a2b42b073121c7413cdaaf75besewardj      f64[6] = 0xF8;
11140c2cb623cca372a2b42b073121c7413cdaaf75besewardj      f64[5] = f64[4] = f64[3] = f64[2] = f64[1] = f64[0] = 0;
11150c2cb623cca372a2b42b073121c7413cdaaf75besewardj      return;
11160c2cb623cca372a2b42b073121c7413cdaaf75besewardj   }
11170c2cb623cca372a2b42b073121c7413cdaaf75besewardj
11180c2cb623cca372a2b42b073121c7413cdaaf75besewardj   /* It's not a zero, denormal, infinity or nan.  So it must be a
11190c2cb623cca372a2b42b073121c7413cdaaf75besewardj      normalised number.  Rebias the exponent and consider. */
11200c2cb623cca372a2b42b073121c7413cdaaf75besewardj   bexp -= (16383 - 1023);
11210c2cb623cca372a2b42b073121c7413cdaaf75besewardj   if (bexp >= 0x7FF) {
11220c2cb623cca372a2b42b073121c7413cdaaf75besewardj      /* It's too big for a double.  Construct an infinity. */
11230c2cb623cca372a2b42b073121c7413cdaaf75besewardj      f64[7] = (sign << 7) | 0x7F;
11240c2cb623cca372a2b42b073121c7413cdaaf75besewardj      f64[6] = 0xF0;
11250c2cb623cca372a2b42b073121c7413cdaaf75besewardj      f64[5] = f64[4] = f64[3] = f64[2] = f64[1] = f64[0] = 0;
11260c2cb623cca372a2b42b073121c7413cdaaf75besewardj      return;
11270c2cb623cca372a2b42b073121c7413cdaaf75besewardj   }
11280c2cb623cca372a2b42b073121c7413cdaaf75besewardj
11290c2cb623cca372a2b42b073121c7413cdaaf75besewardj   if (bexp < 0) {
11300c2cb623cca372a2b42b073121c7413cdaaf75besewardj   /* It's too small for a double.  Construct a zero.  Note, this
11310c2cb623cca372a2b42b073121c7413cdaaf75besewardj      is a kludge since we could conceivably create a
11320c2cb623cca372a2b42b073121c7413cdaaf75besewardj      denormalised number for bexp in -1 to -51, but we don't
11330c2cb623cca372a2b42b073121c7413cdaaf75besewardj      bother.  This means the conversion flushes values
11340c2cb623cca372a2b42b073121c7413cdaaf75besewardj      approximately in the range 1e-309 to 1e-324 ish to zero
11350c2cb623cca372a2b42b073121c7413cdaaf75besewardj      when it doesn't actually need to.  This could be
11360c2cb623cca372a2b42b073121c7413cdaaf75besewardj      improved. */
11370c2cb623cca372a2b42b073121c7413cdaaf75besewardj      f64[7] = sign << 7;
11380c2cb623cca372a2b42b073121c7413cdaaf75besewardj      f64[6] = f64[5] = f64[4] = f64[3] = f64[2] = f64[1] = f64[0] = 0;
11390c2cb623cca372a2b42b073121c7413cdaaf75besewardj      return;
11400c2cb623cca372a2b42b073121c7413cdaaf75besewardj   }
11410c2cb623cca372a2b42b073121c7413cdaaf75besewardj
11420c2cb623cca372a2b42b073121c7413cdaaf75besewardj   /* Ok, it's a normalised number which is representable as a double.
11430c2cb623cca372a2b42b073121c7413cdaaf75besewardj      Copy the exponent and mantissa into place. */
11440c2cb623cca372a2b42b073121c7413cdaaf75besewardj   /*
11450c2cb623cca372a2b42b073121c7413cdaaf75besewardj   for (i = 0; i < 52; i++)
11460c2cb623cca372a2b42b073121c7413cdaaf75besewardj      write_bit_array ( f64,
11470c2cb623cca372a2b42b073121c7413cdaaf75besewardj                        i,
11480c2cb623cca372a2b42b073121c7413cdaaf75besewardj                        read_bit_array ( f80, i+11 ) );
11490c2cb623cca372a2b42b073121c7413cdaaf75besewardj   */
11500c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f64[0] = (f80[1] >> 3) | (f80[2] << 5);
11510c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f64[1] = (f80[2] >> 3) | (f80[3] << 5);
11520c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f64[2] = (f80[3] >> 3) | (f80[4] << 5);
11530c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f64[3] = (f80[4] >> 3) | (f80[5] << 5);
11540c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f64[4] = (f80[5] >> 3) | (f80[6] << 5);
11550c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f64[5] = (f80[6] >> 3) | (f80[7] << 5);
11560c2cb623cca372a2b42b073121c7413cdaaf75besewardj
11570c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f64[6] = ((bexp << 4) & 0xF0) | ((f80[7] >> 3) & 0x0F);
11580c2cb623cca372a2b42b073121c7413cdaaf75besewardj
11590c2cb623cca372a2b42b073121c7413cdaaf75besewardj   f64[7] = (sign << 7) | ((bexp >> 4) & 0x7F);
11600c2cb623cca372a2b42b073121c7413cdaaf75besewardj
11610c2cb623cca372a2b42b073121c7413cdaaf75besewardj   /* Now consider any rounding that needs to happen as a result of
11620c2cb623cca372a2b42b073121c7413cdaaf75besewardj      truncating the mantissa. */
11630c2cb623cca372a2b42b073121c7413cdaaf75besewardj   if (f80[1] & 4) /* read_bit_array(f80, 10) == 1) */ {
11640c2cb623cca372a2b42b073121c7413cdaaf75besewardj      /* Round upwards.  This is a kludge.  Once in every 64k
11650c2cb623cca372a2b42b073121c7413cdaaf75besewardj         roundings (statistically) the bottom two bytes are both 0xFF
11660c2cb623cca372a2b42b073121c7413cdaaf75besewardj         and so we don't round at all.  Could be improved. */
11670c2cb623cca372a2b42b073121c7413cdaaf75besewardj      if (f64[0] != 0xFF) {
11680c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f64[0]++;
11690c2cb623cca372a2b42b073121c7413cdaaf75besewardj      }
11700c2cb623cca372a2b42b073121c7413cdaaf75besewardj      else
11710c2cb623cca372a2b42b073121c7413cdaaf75besewardj      if (f64[0] == 0xFF && f64[1] != 0xFF) {
11720c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f64[0] = 0;
11730c2cb623cca372a2b42b073121c7413cdaaf75besewardj         f64[1]++;
11740c2cb623cca372a2b42b073121c7413cdaaf75besewardj      }
11750c2cb623cca372a2b42b073121c7413cdaaf75besewardj      /* else we don't round, but we should. */
11760c2cb623cca372a2b42b073121c7413cdaaf75besewardj   }
11770c2cb623cca372a2b42b073121c7413cdaaf75besewardj}
11780c2cb623cca372a2b42b073121c7413cdaaf75besewardj
117917442fe8094d0f82266e5a05509f62cac8f7539esewardj/* CALLED FROM GENERATED CODE */
118017442fe8094d0f82266e5a05509f62cac8f7539esewardj/* DIRTY HELPER (reads guest memory) */
118117442fe8094d0f82266e5a05509f62cac8f7539esewardjstatic ULong loadF80le ( UInt addrU )
118217442fe8094d0f82266e5a05509f62cac8f7539esewardj{
118317442fe8094d0f82266e5a05509f62cac8f7539esewardj   ULong f64;
118417442fe8094d0f82266e5a05509f62cac8f7539esewardj   convert_f80le_to_f64le ( (UChar*)addrU, (UChar*)&f64 );
118517442fe8094d0f82266e5a05509f62cac8f7539esewardj   return f64;
118617442fe8094d0f82266e5a05509f62cac8f7539esewardj}
118717442fe8094d0f82266e5a05509f62cac8f7539esewardj
118817442fe8094d0f82266e5a05509f62cac8f7539esewardj/* CALLED FROM GENERATED CODE */
118917442fe8094d0f82266e5a05509f62cac8f7539esewardj/* DIRTY HELPER (writes guest memory) */
119017442fe8094d0f82266e5a05509f62cac8f7539esewardjstatic void storeF80le ( UInt addrU, ULong f64 )
119117442fe8094d0f82266e5a05509f62cac8f7539esewardj{
119217442fe8094d0f82266e5a05509f62cac8f7539esewardj   convert_f64le_to_f80le( (UChar*)&f64, (UChar*)addrU );
119317442fe8094d0f82266e5a05509f62cac8f7539esewardj}
119417442fe8094d0f82266e5a05509f62cac8f7539esewardj
11950c2cb623cca372a2b42b073121c7413cdaaf75besewardj
11960c2cb623cca372a2b42b073121c7413cdaaf75besewardj/*----------------------------------------------*/
11970c2cb623cca372a2b42b073121c7413cdaaf75besewardj/*--- The exported fns ..                    ---*/
11980c2cb623cca372a2b42b073121c7413cdaaf75besewardj/*----------------------------------------------*/
11990c2cb623cca372a2b42b073121c7413cdaaf75besewardj
12000c2cb623cca372a2b42b073121c7413cdaaf75besewardj/* Layout of the real x87 state. */
12010c2cb623cca372a2b42b073121c7413cdaaf75besewardj
12020c2cb623cca372a2b42b073121c7413cdaaf75besewardjtypedef
12030c2cb623cca372a2b42b073121c7413cdaaf75besewardj   struct {
12040c2cb623cca372a2b42b073121c7413cdaaf75besewardj      UShort env[14];
12050c2cb623cca372a2b42b073121c7413cdaaf75besewardj      UChar  reg[80];
12060c2cb623cca372a2b42b073121c7413cdaaf75besewardj   }
12070c2cb623cca372a2b42b073121c7413cdaaf75besewardj   Fpu_State;
12080c2cb623cca372a2b42b073121c7413cdaaf75besewardj
12090c2cb623cca372a2b42b073121c7413cdaaf75besewardj/* Offsets, in 16-bit ints, into the FPU environment (env) area. */
12100c2cb623cca372a2b42b073121c7413cdaaf75besewardj#define FP_ENV_CTRL   0
12110c2cb623cca372a2b42b073121c7413cdaaf75besewardj#define FP_ENV_STAT   2
12120c2cb623cca372a2b42b073121c7413cdaaf75besewardj#define FP_ENV_TAG    4
12130c2cb623cca372a2b42b073121c7413cdaaf75besewardj#define FP_ENV_IP     6 /* and 7 */
12140c2cb623cca372a2b42b073121c7413cdaaf75besewardj#define FP_ENV_CS     8
12150c2cb623cca372a2b42b073121c7413cdaaf75besewardj#define FP_ENV_OPOFF  10 /* and 11 */
12160c2cb623cca372a2b42b073121c7413cdaaf75besewardj#define FP_ENV_OPSEL  12
12170c2cb623cca372a2b42b073121c7413cdaaf75besewardj#define FP_REG(ii)    (10*(7-(ii)))
12180c2cb623cca372a2b42b073121c7413cdaaf75besewardj
12190c2cb623cca372a2b42b073121c7413cdaaf75besewardj
12200c2cb623cca372a2b42b073121c7413cdaaf75besewardj/* VISIBLE TO LIBVEX CLIENT */
12210c2cb623cca372a2b42b073121c7413cdaaf75besewardjvoid x87_to_vex ( /*IN*/UChar* x87_state, /*OUT*/UChar* vex_state )
12220c2cb623cca372a2b42b073121c7413cdaaf75besewardj{
12230c2cb623cca372a2b42b073121c7413cdaaf75besewardj   Int        r;
12240c2cb623cca372a2b42b073121c7413cdaaf75besewardj   UInt       tag;
12250c2cb623cca372a2b42b073121c7413cdaaf75besewardj   Double*    vexRegs = (Double*)(vex_state + OFFB_F0);
12260c2cb623cca372a2b42b073121c7413cdaaf75besewardj   UChar*     vexTags = (UChar*)(vex_state + OFFB_FTAG0);
12270c2cb623cca372a2b42b073121c7413cdaaf75besewardj   Fpu_State* x87     = (Fpu_State*)x87_state;
12280c2cb623cca372a2b42b073121c7413cdaaf75besewardj   UInt       ftop    = (x87->env[FP_ENV_STAT] >> 11) & 7;
12290c2cb623cca372a2b42b073121c7413cdaaf75besewardj   UInt       tagw    = x87->env[FP_ENV_TAG];
12306e0dbda4f7ea53dd29996d4d429d3c5c92ee3640sewardj   UInt       fpucw   = x87->env[FP_ENV_CTRL];
1231c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   UInt       c3210   = x87->env[FP_ENV_STAT] & 0x4700;
12320c2cb623cca372a2b42b073121c7413cdaaf75besewardj
12330c2cb623cca372a2b42b073121c7413cdaaf75besewardj   /* Copy registers and tags */
12340c2cb623cca372a2b42b073121c7413cdaaf75besewardj   for (r = 0; r < 8; r++) {
12350c2cb623cca372a2b42b073121c7413cdaaf75besewardj      tag = (tagw >> (2*r)) & 3;
12360c2cb623cca372a2b42b073121c7413cdaaf75besewardj      if (tag == 3) {
12370c2cb623cca372a2b42b073121c7413cdaaf75besewardj         /* register is empty */
12380c2cb623cca372a2b42b073121c7413cdaaf75besewardj         vexRegs[r] = 0.0;
12390c2cb623cca372a2b42b073121c7413cdaaf75besewardj         vexTags[r] = 0;
12400c2cb623cca372a2b42b073121c7413cdaaf75besewardj      } else {
12410c2cb623cca372a2b42b073121c7413cdaaf75besewardj         /* register is non-empty */
12420c2cb623cca372a2b42b073121c7413cdaaf75besewardj         convert_f80le_to_f64le( &x87->reg[FP_REG(r)], (UChar*)&vexRegs[r] );
12430c2cb623cca372a2b42b073121c7413cdaaf75besewardj         vexTags[r] = 1;
12440c2cb623cca372a2b42b073121c7413cdaaf75besewardj      }
12450c2cb623cca372a2b42b073121c7413cdaaf75besewardj   }
12460c2cb623cca372a2b42b073121c7413cdaaf75besewardj
12470c2cb623cca372a2b42b073121c7413cdaaf75besewardj   /* stack pointer */
12480c2cb623cca372a2b42b073121c7413cdaaf75besewardj   *(UInt*)(vex_state + OFFB_FTOP) = ftop;
12490c2cb623cca372a2b42b073121c7413cdaaf75besewardj
12506e0dbda4f7ea53dd29996d4d429d3c5c92ee3640sewardj   /* control word */
12516e0dbda4f7ea53dd29996d4d429d3c5c92ee3640sewardj   *(UInt*)(vex_state + OFFB_FPUCW) = fpucw;
12523f868e5262a8d2488f41cc49058ba60c24843c3esewardj
12533f868e5262a8d2488f41cc49058ba60c24843c3esewardj   /* status word */
1254c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   *(UInt*)(vex_state + OFFB_FC3210) = c3210;
12550c2cb623cca372a2b42b073121c7413cdaaf75besewardj}
12560c2cb623cca372a2b42b073121c7413cdaaf75besewardj
12576e0dbda4f7ea53dd29996d4d429d3c5c92ee3640sewardj
12580c2cb623cca372a2b42b073121c7413cdaaf75besewardj/* VISIBLE TO LIBVEX CLIENT */
12590c2cb623cca372a2b42b073121c7413cdaaf75besewardjvoid vex_to_x87 ( /*IN*/UChar* vex_state, /*OUT*/UChar* x87_state )
12600c2cb623cca372a2b42b073121c7413cdaaf75besewardj{
12610c2cb623cca372a2b42b073121c7413cdaaf75besewardj   Int        i, r;
12620c2cb623cca372a2b42b073121c7413cdaaf75besewardj   UInt       tagw;
12630c2cb623cca372a2b42b073121c7413cdaaf75besewardj   Double*    vexRegs = (Double*)(vex_state + OFFB_F0);
12640c2cb623cca372a2b42b073121c7413cdaaf75besewardj   UChar*     vexTags = (UChar*)(vex_state + OFFB_FTAG0);
12650c2cb623cca372a2b42b073121c7413cdaaf75besewardj   Fpu_State* x87     = (Fpu_State*)x87_state;
12660c2cb623cca372a2b42b073121c7413cdaaf75besewardj   UInt       ftop    = *(UInt*)(vex_state + OFFB_FTOP);
1267c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   UInt       c3210   = *(UInt*)(vex_state + OFFB_FC3210);
12680c2cb623cca372a2b42b073121c7413cdaaf75besewardj
12690c2cb623cca372a2b42b073121c7413cdaaf75besewardj   for (i = 0; i < 14; i++)
12700c2cb623cca372a2b42b073121c7413cdaaf75besewardj      x87->env[i] = 0;
12710c2cb623cca372a2b42b073121c7413cdaaf75besewardj
12720c2cb623cca372a2b42b073121c7413cdaaf75besewardj   x87->env[1] = x87->env[3] = x87->env[5] = x87->env[13] = 0xFFFF;
12736e0dbda4f7ea53dd29996d4d429d3c5c92ee3640sewardj   x87->env[FP_ENV_CTRL] = (UShort)( *(UInt*)(vex_state + OFFB_FPUCW) );
1274c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj   x87->env[FP_ENV_STAT] = ((ftop & 7) << 11) | (c3210 & 0x4700);
12750c2cb623cca372a2b42b073121c7413cdaaf75besewardj
12760c2cb623cca372a2b42b073121c7413cdaaf75besewardj   tagw = 0;
12770c2cb623cca372a2b42b073121c7413cdaaf75besewardj   for (r = 0; r < 8; r++) {
12780c2cb623cca372a2b42b073121c7413cdaaf75besewardj      if (vexTags[r] == 0) {
12790c2cb623cca372a2b42b073121c7413cdaaf75besewardj         /* register is empty */
12800c2cb623cca372a2b42b073121c7413cdaaf75besewardj         tagw |= (3 << (2*r));
12810c2cb623cca372a2b42b073121c7413cdaaf75besewardj         convert_f64le_to_f80le( (UChar*)&vexRegs[r], &x87->reg[FP_REG(r)] );
12820c2cb623cca372a2b42b073121c7413cdaaf75besewardj      } else {
12830c2cb623cca372a2b42b073121c7413cdaaf75besewardj         /* register is full. */
12840c2cb623cca372a2b42b073121c7413cdaaf75besewardj         tagw |= (0 << (2*r));
12850c2cb623cca372a2b42b073121c7413cdaaf75besewardj         convert_f64le_to_f80le( (UChar*)&vexRegs[r],  &x87->reg[FP_REG(r)] );
12860c2cb623cca372a2b42b073121c7413cdaaf75besewardj      }
12870c2cb623cca372a2b42b073121c7413cdaaf75besewardj   }
12880c2cb623cca372a2b42b073121c7413cdaaf75besewardj   x87->env[FP_ENV_TAG] = tagw;
12890c2cb623cca372a2b42b073121c7413cdaaf75besewardj}
12900c2cb623cca372a2b42b073121c7413cdaaf75besewardj
12910c2cb623cca372a2b42b073121c7413cdaaf75besewardj
129236ca51378f8851635df814230fa23f2c409b9eddsewardj/*---------------------------------------------------------------*/
1293c0ee2edb4563c90bc8f1a83a09984a1fda86d1d3sewardj/*--- end                                guest-x86/ghelpers.c ---*/
129436ca51378f8851635df814230fa23f2c409b9eddsewardj/*---------------------------------------------------------------*/
1295