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