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