guest_x86_helpers.c revision e9ba4328f2afb94bc8474e9a7205e50ed9ac73fc
136ca51378f8851635df814230fa23f2c409b9eddsewardj 236ca51378f8851635df814230fa23f2c409b9eddsewardj/*---------------------------------------------------------------*/ 336ca51378f8851635df814230fa23f2c409b9eddsewardj/*--- ---*/ 4c0ee2edb4563c90bc8f1a83a09984a1fda86d1d3sewardj/*--- This file (guest-x86/ghelpers.c) is ---*/ 536ca51378f8851635df814230fa23f2c409b9eddsewardj/*--- Copyright (c) 2004 OpenWorks LLP. All rights reserved. ---*/ 636ca51378f8851635df814230fa23f2c409b9eddsewardj/*--- ---*/ 736ca51378f8851635df814230fa23f2c409b9eddsewardj/*---------------------------------------------------------------*/ 836ca51378f8851635df814230fa23f2c409b9eddsewardj 9f8ed9d874a7b8651654591c68c6d431c758d787csewardj/* 10f8ed9d874a7b8651654591c68c6d431c758d787csewardj This file is part of LibVEX, a library for dynamic binary 11f8ed9d874a7b8651654591c68c6d431c758d787csewardj instrumentation and translation. 12f8ed9d874a7b8651654591c68c6d431c758d787csewardj 13f8ed9d874a7b8651654591c68c6d431c758d787csewardj Copyright (C) 2004 OpenWorks, LLP. 14f8ed9d874a7b8651654591c68c6d431c758d787csewardj 15f8ed9d874a7b8651654591c68c6d431c758d787csewardj This program is free software; you can redistribute it and/or modify 16f8ed9d874a7b8651654591c68c6d431c758d787csewardj it under the terms of the GNU General Public License as published by 17f8ed9d874a7b8651654591c68c6d431c758d787csewardj the Free Software Foundation; Version 2 dated June 1991 of the 18f8ed9d874a7b8651654591c68c6d431c758d787csewardj license. 19f8ed9d874a7b8651654591c68c6d431c758d787csewardj 20f8ed9d874a7b8651654591c68c6d431c758d787csewardj This program is distributed in the hope that it will be useful, 21f8ed9d874a7b8651654591c68c6d431c758d787csewardj but WITHOUT ANY WARRANTY; without even the implied warranty of 22f8ed9d874a7b8651654591c68c6d431c758d787csewardj MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or liability 23f8ed9d874a7b8651654591c68c6d431c758d787csewardj for damages. See the GNU General Public License for more details. 24f8ed9d874a7b8651654591c68c6d431c758d787csewardj 25f8ed9d874a7b8651654591c68c6d431c758d787csewardj Neither the names of the U.S. Department of Energy nor the 26f8ed9d874a7b8651654591c68c6d431c758d787csewardj University of California nor the names of its contributors may be 27f8ed9d874a7b8651654591c68c6d431c758d787csewardj used to endorse or promote products derived from this software 28f8ed9d874a7b8651654591c68c6d431c758d787csewardj without prior written permission. 29f8ed9d874a7b8651654591c68c6d431c758d787csewardj 30f8ed9d874a7b8651654591c68c6d431c758d787csewardj You should have received a copy of the GNU General Public License 31f8ed9d874a7b8651654591c68c6d431c758d787csewardj along with this program; if not, write to the Free Software 32f8ed9d874a7b8651654591c68c6d431c758d787csewardj Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 33f8ed9d874a7b8651654591c68c6d431c758d787csewardj USA. 34f8ed9d874a7b8651654591c68c6d431c758d787csewardj*/ 35f8ed9d874a7b8651654591c68c6d431c758d787csewardj 3636ca51378f8851635df814230fa23f2c409b9eddsewardj#include "libvex_basictypes.h" 37893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj#include "libvex_emwarn.h" 380c2cb623cca372a2b42b073121c7413cdaaf75besewardj#include "libvex_guest_x86.h" 3936ca51378f8851635df814230fa23f2c409b9eddsewardj#include "libvex_ir.h" 4049651f4b59b1ab7e0e70cccd34001630eafbe957sewardj#include "libvex.h" 41c0ee2edb4563c90bc8f1a83a09984a1fda86d1d3sewardj 42c0ee2edb4563c90bc8f1a83a09984a1fda86d1d3sewardj#include "main/vex_util.h" 43c0ee2edb4563c90bc8f1a83a09984a1fda86d1d3sewardj#include "guest-x86/gdefs.h" 4436ca51378f8851635df814230fa23f2c409b9eddsewardj 45c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj 4636ca51378f8851635df814230fa23f2c409b9eddsewardj/* This file contains helper functions for x86 guest code. 4736ca51378f8851635df814230fa23f2c409b9eddsewardj Calls to these functions are generated by the back end. 4836ca51378f8851635df814230fa23f2c409b9eddsewardj These calls are of course in the host machine code and 4936ca51378f8851635df814230fa23f2c409b9eddsewardj this file will be compiled to host machine code, so that 5036ca51378f8851635df814230fa23f2c409b9eddsewardj all makes sense. 5136ca51378f8851635df814230fa23f2c409b9eddsewardj 5236ca51378f8851635df814230fa23f2c409b9eddsewardj Only change the signatures of these helper functions very 5336ca51378f8851635df814230fa23f2c409b9eddsewardj carefully. If you change the signature here, you'll have to change 5436ca51378f8851635df814230fa23f2c409b9eddsewardj the parameters passed to it in the IR calls constructed by 552a9ad023890d3b34cf45e429df2a8ae88b419128sewardj guest-x86/toIR.c. 5689050e58e7bee40892662fe94231aefc33768cf5sewardj 5789050e58e7bee40892662fe94231aefc33768cf5sewardj Some of this code/logic is derived from QEMU, which is copyright 5889050e58e7bee40892662fe94231aefc33768cf5sewardj Fabrice Bellard, licensed under the LGPL. It is used with 5989050e58e7bee40892662fe94231aefc33768cf5sewardj permission. 6036ca51378f8851635df814230fa23f2c409b9eddsewardj*/ 6136ca51378f8851635df814230fa23f2c409b9eddsewardj 6284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj/* Set to 1 to get detailed profiling info about use of the flag 6384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj machinery. */ 6484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#define PROFILE_EFLAGS 0 6584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj 6684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj 67d44bc6e6692dfb0881dcc249bd4ba3d8f8e97fcasewardjstatic const UChar parity_table[256] = { 682a9ad023890d3b34cf45e429df2a8ae88b419128sewardj X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, 692a9ad023890d3b34cf45e429df2a8ae88b419128sewardj 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 702a9ad023890d3b34cf45e429df2a8ae88b419128sewardj 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 712a9ad023890d3b34cf45e429df2a8ae88b419128sewardj X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, 722a9ad023890d3b34cf45e429df2a8ae88b419128sewardj 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 732a9ad023890d3b34cf45e429df2a8ae88b419128sewardj X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, 742a9ad023890d3b34cf45e429df2a8ae88b419128sewardj X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, 752a9ad023890d3b34cf45e429df2a8ae88b419128sewardj 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 762a9ad023890d3b34cf45e429df2a8ae88b419128sewardj 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 772a9ad023890d3b34cf45e429df2a8ae88b419128sewardj X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, 782a9ad023890d3b34cf45e429df2a8ae88b419128sewardj X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, 792a9ad023890d3b34cf45e429df2a8ae88b419128sewardj 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 802a9ad023890d3b34cf45e429df2a8ae88b419128sewardj X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, 812a9ad023890d3b34cf45e429df2a8ae88b419128sewardj 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 822a9ad023890d3b34cf45e429df2a8ae88b419128sewardj 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 832a9ad023890d3b34cf45e429df2a8ae88b419128sewardj X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, 842a9ad023890d3b34cf45e429df2a8ae88b419128sewardj 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 852a9ad023890d3b34cf45e429df2a8ae88b419128sewardj X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, 862a9ad023890d3b34cf45e429df2a8ae88b419128sewardj X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, 872a9ad023890d3b34cf45e429df2a8ae88b419128sewardj 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 882a9ad023890d3b34cf45e429df2a8ae88b419128sewardj X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, 892a9ad023890d3b34cf45e429df2a8ae88b419128sewardj 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 902a9ad023890d3b34cf45e429df2a8ae88b419128sewardj 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 912a9ad023890d3b34cf45e429df2a8ae88b419128sewardj X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, 922a9ad023890d3b34cf45e429df2a8ae88b419128sewardj X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, 932a9ad023890d3b34cf45e429df2a8ae88b419128sewardj 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 942a9ad023890d3b34cf45e429df2a8ae88b419128sewardj 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 952a9ad023890d3b34cf45e429df2a8ae88b419128sewardj X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, 962a9ad023890d3b34cf45e429df2a8ae88b419128sewardj 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 972a9ad023890d3b34cf45e429df2a8ae88b419128sewardj X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, 982a9ad023890d3b34cf45e429df2a8ae88b419128sewardj X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, 992a9ad023890d3b34cf45e429df2a8ae88b419128sewardj 0, X86G_CC_MASK_P, X86G_CC_MASK_P, 0, X86G_CC_MASK_P, 0, 0, X86G_CC_MASK_P, 10014731f22bf7759d6d23383ca870ac89d9581f1e9sewardj}; 10114731f22bf7759d6d23383ca870ac89d9581f1e9sewardj 10214731f22bf7759d6d23383ca870ac89d9581f1e9sewardj/* n must be a constant to be efficient */ 103df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardjinline static Int lshift ( Int x, Int n ) 10414731f22bf7759d6d23383ca870ac89d9581f1e9sewardj{ 105df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj if (n >= 0) 106df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj return x << n; 107df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj else 108df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj return x >> (-n); 10914731f22bf7759d6d23383ca870ac89d9581f1e9sewardj} 11014731f22bf7759d6d23383ca870ac89d9581f1e9sewardj 11114731f22bf7759d6d23383ca870ac89d9581f1e9sewardj 112b9c5cf639b3b21b972599d27207a033afc76ef67sewardj#define PREAMBLE(__data_bits) \ 113df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj /* const */ UInt DATA_MASK \ 114b9c5cf639b3b21b972599d27207a033afc76ef67sewardj = __data_bits==8 ? 0xFF \ 115b9c5cf639b3b21b972599d27207a033afc76ef67sewardj : (__data_bits==16 ? 0xFFFF \ 116b9c5cf639b3b21b972599d27207a033afc76ef67sewardj : 0xFFFFFFFF); \ 117df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj /* const */ UInt SIGN_MASK = 1 << (__data_bits - 1); \ 1182a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj /* const */ UInt CC_DEP1 = cc_dep1_formal; \ 1192a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj /* const */ UInt CC_DEP2 = cc_dep2_formal; \ 1202a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj /* const */ UInt CC_NDEP = cc_ndep_formal; \ 1212a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj /* Four bogus assignments, which hopefully gcc can */ \ 122df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj /* optimise away, and which stop it complaining about */ \ 123df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj /* unused variables. */ \ 124df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj SIGN_MASK = SIGN_MASK; \ 125df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj DATA_MASK = DATA_MASK; \ 1262a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj CC_DEP2 = CC_DEP2; \ 1272a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj CC_NDEP = CC_NDEP; 128df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj 12914731f22bf7759d6d23383ca870ac89d9581f1e9sewardj 130b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/ 131b9c5cf639b3b21b972599d27207a033afc76ef67sewardj 132df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_ADD(DATA_BITS,DATA_UTYPE) \ 133b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{ \ 134b9c5cf639b3b21b972599d27207a033afc76ef67sewardj PREAMBLE(DATA_BITS); \ 1358fc937421c954ff9f707254f028b1fa0410c473dsewardj { Int cf, pf, af, zf, sf, of; \ 1368fc937421c954ff9f707254f028b1fa0410c473dsewardj Int argL, argR, res; \ 1378fc937421c954ff9f707254f028b1fa0410c473dsewardj argL = CC_DEP1; \ 1388fc937421c954ff9f707254f028b1fa0410c473dsewardj argR = CC_DEP2; \ 1398fc937421c954ff9f707254f028b1fa0410c473dsewardj res = argL + argR; \ 1408fc937421c954ff9f707254f028b1fa0410c473dsewardj cf = (DATA_UTYPE)res < (DATA_UTYPE)argL; \ 1418fc937421c954ff9f707254f028b1fa0410c473dsewardj pf = parity_table[(UChar)res]; \ 1428fc937421c954ff9f707254f028b1fa0410c473dsewardj af = (res ^ argL ^ argR) & 0x10; \ 1438fc937421c954ff9f707254f028b1fa0410c473dsewardj zf = ((DATA_UTYPE)res == 0) << 6; \ 1448fc937421c954ff9f707254f028b1fa0410c473dsewardj sf = lshift(res, 8 - DATA_BITS) & 0x80; \ 1458fc937421c954ff9f707254f028b1fa0410c473dsewardj of = lshift((argL ^ argR ^ -1) & (argL ^ res), \ 1462a9ad023890d3b34cf45e429df2a8ae88b419128sewardj 12 - DATA_BITS) & X86G_CC_MASK_O; \ 1478fc937421c954ff9f707254f028b1fa0410c473dsewardj return cf | pf | af | zf | sf | of; \ 1488fc937421c954ff9f707254f028b1fa0410c473dsewardj } \ 1492ef5f2a829433c4ca17f33e1bf993cf16b9e347dsewardj} 1502ef5f2a829433c4ca17f33e1bf993cf16b9e347dsewardj 151b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/ 152b9c5cf639b3b21b972599d27207a033afc76ef67sewardj 1532a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj#define ACTIONS_SUB(DATA_BITS,DATA_UTYPE) \ 154b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{ \ 155b9c5cf639b3b21b972599d27207a033afc76ef67sewardj PREAMBLE(DATA_BITS); \ 1568fc937421c954ff9f707254f028b1fa0410c473dsewardj { Int cf, pf, af, zf, sf, of; \ 1578fc937421c954ff9f707254f028b1fa0410c473dsewardj Int argL, argR, res; \ 1588fc937421c954ff9f707254f028b1fa0410c473dsewardj argL = CC_DEP1; \ 1598fc937421c954ff9f707254f028b1fa0410c473dsewardj argR = CC_DEP2; \ 1608fc937421c954ff9f707254f028b1fa0410c473dsewardj res = argL - argR; \ 1618fc937421c954ff9f707254f028b1fa0410c473dsewardj cf = (DATA_UTYPE)argL < (DATA_UTYPE)argR; \ 1628fc937421c954ff9f707254f028b1fa0410c473dsewardj pf = parity_table[(UChar)res]; \ 1638fc937421c954ff9f707254f028b1fa0410c473dsewardj af = (res ^ argL ^ argR) & 0x10; \ 1648fc937421c954ff9f707254f028b1fa0410c473dsewardj zf = ((DATA_UTYPE)res == 0) << 6; \ 1658fc937421c954ff9f707254f028b1fa0410c473dsewardj sf = lshift(res, 8 - DATA_BITS) & 0x80; \ 1668fc937421c954ff9f707254f028b1fa0410c473dsewardj of = lshift((argL ^ argR) & (argL ^ res), \ 1672a9ad023890d3b34cf45e429df2a8ae88b419128sewardj 12 - DATA_BITS) & X86G_CC_MASK_O; \ 1688fc937421c954ff9f707254f028b1fa0410c473dsewardj return cf | pf | af | zf | sf | of; \ 1698fc937421c954ff9f707254f028b1fa0410c473dsewardj } \ 1702ef5f2a829433c4ca17f33e1bf993cf16b9e347dsewardj} 1712ef5f2a829433c4ca17f33e1bf993cf16b9e347dsewardj 172b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/ 173b9c5cf639b3b21b972599d27207a033afc76ef67sewardj 1742a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj#define ACTIONS_ADC(DATA_BITS,DATA_UTYPE) \ 175b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{ \ 176b9c5cf639b3b21b972599d27207a033afc76ef67sewardj PREAMBLE(DATA_BITS); \ 1778fc937421c954ff9f707254f028b1fa0410c473dsewardj { Int cf, pf, af, zf, sf, of; \ 1788fc937421c954ff9f707254f028b1fa0410c473dsewardj Int argL, argR, oldC, res; \ 1792a9ad023890d3b34cf45e429df2a8ae88b419128sewardj oldC = CC_NDEP & X86G_CC_MASK_C; \ 1808fc937421c954ff9f707254f028b1fa0410c473dsewardj argL = CC_DEP1; \ 1818fc937421c954ff9f707254f028b1fa0410c473dsewardj argR = CC_DEP2 ^ oldC; \ 1828fc937421c954ff9f707254f028b1fa0410c473dsewardj res = (argL + argR) + oldC; \ 1838fc937421c954ff9f707254f028b1fa0410c473dsewardj if (oldC) \ 1848fc937421c954ff9f707254f028b1fa0410c473dsewardj cf = (DATA_UTYPE)res <= (DATA_UTYPE)argL; \ 1858fc937421c954ff9f707254f028b1fa0410c473dsewardj else \ 1868fc937421c954ff9f707254f028b1fa0410c473dsewardj cf = (DATA_UTYPE)res < (DATA_UTYPE)argL; \ 1878fc937421c954ff9f707254f028b1fa0410c473dsewardj pf = parity_table[(UChar)res]; \ 1888fc937421c954ff9f707254f028b1fa0410c473dsewardj af = (res ^ argL ^ argR) & 0x10; \ 1898fc937421c954ff9f707254f028b1fa0410c473dsewardj zf = ((DATA_UTYPE)res == 0) << 6; \ 1908fc937421c954ff9f707254f028b1fa0410c473dsewardj sf = lshift(res, 8 - DATA_BITS) & 0x80; \ 1918fc937421c954ff9f707254f028b1fa0410c473dsewardj of = lshift((argL ^ argR ^ -1) & (argL ^ res), \ 1922a9ad023890d3b34cf45e429df2a8ae88b419128sewardj 12 - DATA_BITS) & X86G_CC_MASK_O; \ 1938fc937421c954ff9f707254f028b1fa0410c473dsewardj return cf | pf | af | zf | sf | of; \ 1948fc937421c954ff9f707254f028b1fa0410c473dsewardj } \ 1952ef5f2a829433c4ca17f33e1bf993cf16b9e347dsewardj} 1962ef5f2a829433c4ca17f33e1bf993cf16b9e347dsewardj 197b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/ 198b9c5cf639b3b21b972599d27207a033afc76ef67sewardj 199df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_SBB(DATA_BITS,DATA_UTYPE) \ 200b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{ \ 201b9c5cf639b3b21b972599d27207a033afc76ef67sewardj PREAMBLE(DATA_BITS); \ 2028fc937421c954ff9f707254f028b1fa0410c473dsewardj { Int cf, pf, af, zf, sf, of; \ 2038fc937421c954ff9f707254f028b1fa0410c473dsewardj Int argL, argR, oldC, res; \ 2042a9ad023890d3b34cf45e429df2a8ae88b419128sewardj oldC = CC_NDEP & X86G_CC_MASK_C; \ 2058fc937421c954ff9f707254f028b1fa0410c473dsewardj argL = CC_DEP1; \ 2068fc937421c954ff9f707254f028b1fa0410c473dsewardj argR = CC_DEP2 ^ oldC; \ 2078fc937421c954ff9f707254f028b1fa0410c473dsewardj res = (argL - argR) - oldC; \ 2088fc937421c954ff9f707254f028b1fa0410c473dsewardj if (oldC) \ 2098fc937421c954ff9f707254f028b1fa0410c473dsewardj cf = (DATA_UTYPE)argL <= (DATA_UTYPE)argR; \ 2108fc937421c954ff9f707254f028b1fa0410c473dsewardj else \ 2118fc937421c954ff9f707254f028b1fa0410c473dsewardj cf = (DATA_UTYPE)argL < (DATA_UTYPE)argR; \ 2128fc937421c954ff9f707254f028b1fa0410c473dsewardj pf = parity_table[(UChar)res]; \ 2138fc937421c954ff9f707254f028b1fa0410c473dsewardj af = (res ^ argL ^ argR) & 0x10; \ 2148fc937421c954ff9f707254f028b1fa0410c473dsewardj zf = ((DATA_UTYPE)res == 0) << 6; \ 2158fc937421c954ff9f707254f028b1fa0410c473dsewardj sf = lshift(res, 8 - DATA_BITS) & 0x80; \ 2168fc937421c954ff9f707254f028b1fa0410c473dsewardj of = lshift((argL ^ argR) & (argL ^ res), \ 2172a9ad023890d3b34cf45e429df2a8ae88b419128sewardj 12 - DATA_BITS) & X86G_CC_MASK_O; \ 2188fc937421c954ff9f707254f028b1fa0410c473dsewardj return cf | pf | af | zf | sf | of; \ 2198fc937421c954ff9f707254f028b1fa0410c473dsewardj } \ 220a238471814bd386aeb58a76718b41e68b1a794b2sewardj} 221a238471814bd386aeb58a76718b41e68b1a794b2sewardj 222b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/ 223b9c5cf639b3b21b972599d27207a033afc76ef67sewardj 224df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_LOGIC(DATA_BITS,DATA_UTYPE) \ 225b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{ \ 226b9c5cf639b3b21b972599d27207a033afc76ef67sewardj PREAMBLE(DATA_BITS); \ 2278fc937421c954ff9f707254f028b1fa0410c473dsewardj { Int cf, pf, af, zf, sf, of; \ 2288fc937421c954ff9f707254f028b1fa0410c473dsewardj cf = 0; \ 2298fc937421c954ff9f707254f028b1fa0410c473dsewardj pf = parity_table[(UChar)CC_DEP1]; \ 2308fc937421c954ff9f707254f028b1fa0410c473dsewardj af = 0; \ 2318fc937421c954ff9f707254f028b1fa0410c473dsewardj zf = ((DATA_UTYPE)CC_DEP1 == 0) << 6; \ 2328fc937421c954ff9f707254f028b1fa0410c473dsewardj sf = lshift(CC_DEP1, 8 - DATA_BITS) & 0x80; \ 2338fc937421c954ff9f707254f028b1fa0410c473dsewardj of = 0; \ 2348fc937421c954ff9f707254f028b1fa0410c473dsewardj return cf | pf | af | zf | sf | of; \ 2358fc937421c954ff9f707254f028b1fa0410c473dsewardj } \ 236a238471814bd386aeb58a76718b41e68b1a794b2sewardj} 237a238471814bd386aeb58a76718b41e68b1a794b2sewardj 238b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/ 239b9c5cf639b3b21b972599d27207a033afc76ef67sewardj 240df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_INC(DATA_BITS,DATA_UTYPE) \ 241b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{ \ 242b9c5cf639b3b21b972599d27207a033afc76ef67sewardj PREAMBLE(DATA_BITS); \ 2438fc937421c954ff9f707254f028b1fa0410c473dsewardj { Int cf, pf, af, zf, sf, of; \ 2448fc937421c954ff9f707254f028b1fa0410c473dsewardj Int argL, argR, res; \ 2458fc937421c954ff9f707254f028b1fa0410c473dsewardj res = CC_DEP1; \ 2468fc937421c954ff9f707254f028b1fa0410c473dsewardj argL = res - 1; \ 2478fc937421c954ff9f707254f028b1fa0410c473dsewardj argR = 1; \ 2482a9ad023890d3b34cf45e429df2a8ae88b419128sewardj cf = CC_NDEP & X86G_CC_MASK_C; \ 2498fc937421c954ff9f707254f028b1fa0410c473dsewardj pf = parity_table[(UChar)res]; \ 2508fc937421c954ff9f707254f028b1fa0410c473dsewardj af = (res ^ argL ^ argR) & 0x10; \ 2518fc937421c954ff9f707254f028b1fa0410c473dsewardj zf = ((DATA_UTYPE)res == 0) << 6; \ 2528fc937421c954ff9f707254f028b1fa0410c473dsewardj sf = lshift(res, 8 - DATA_BITS) & 0x80; \ 2538fc937421c954ff9f707254f028b1fa0410c473dsewardj of = ((res & DATA_MASK) == SIGN_MASK) << 11; \ 2548fc937421c954ff9f707254f028b1fa0410c473dsewardj return cf | pf | af | zf | sf | of; \ 2558fc937421c954ff9f707254f028b1fa0410c473dsewardj } \ 25689050e58e7bee40892662fe94231aefc33768cf5sewardj} 25789050e58e7bee40892662fe94231aefc33768cf5sewardj 258b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/ 259b9c5cf639b3b21b972599d27207a033afc76ef67sewardj 260df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_DEC(DATA_BITS,DATA_UTYPE) \ 261b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{ \ 262b9c5cf639b3b21b972599d27207a033afc76ef67sewardj PREAMBLE(DATA_BITS); \ 2638fc937421c954ff9f707254f028b1fa0410c473dsewardj { Int cf, pf, af, zf, sf, of; \ 2648fc937421c954ff9f707254f028b1fa0410c473dsewardj Int argL, argR, res; \ 2658fc937421c954ff9f707254f028b1fa0410c473dsewardj res = CC_DEP1; \ 2668fc937421c954ff9f707254f028b1fa0410c473dsewardj argL = res + 1; \ 2678fc937421c954ff9f707254f028b1fa0410c473dsewardj argR = 1; \ 2682a9ad023890d3b34cf45e429df2a8ae88b419128sewardj cf = CC_NDEP & X86G_CC_MASK_C; \ 2698fc937421c954ff9f707254f028b1fa0410c473dsewardj pf = parity_table[(UChar)res]; \ 2708fc937421c954ff9f707254f028b1fa0410c473dsewardj af = (res ^ argL ^ argR) & 0x10; \ 2718fc937421c954ff9f707254f028b1fa0410c473dsewardj zf = ((DATA_UTYPE)res == 0) << 6; \ 2728fc937421c954ff9f707254f028b1fa0410c473dsewardj sf = lshift(res, 8 - DATA_BITS) & 0x80; \ 2738fc937421c954ff9f707254f028b1fa0410c473dsewardj of = ((res & DATA_MASK) \ 2748fc937421c954ff9f707254f028b1fa0410c473dsewardj == ((UInt)SIGN_MASK - 1)) << 11; \ 2758fc937421c954ff9f707254f028b1fa0410c473dsewardj return cf | pf | af | zf | sf | of; \ 2768fc937421c954ff9f707254f028b1fa0410c473dsewardj } \ 27789050e58e7bee40892662fe94231aefc33768cf5sewardj} 27889050e58e7bee40892662fe94231aefc33768cf5sewardj 279b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/ 280b9c5cf639b3b21b972599d27207a033afc76ef67sewardj 281df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_SHL(DATA_BITS,DATA_UTYPE) \ 282b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{ \ 283b9c5cf639b3b21b972599d27207a033afc76ef67sewardj PREAMBLE(DATA_BITS); \ 2848fc937421c954ff9f707254f028b1fa0410c473dsewardj { Int cf, pf, af, zf, sf, of; \ 2852a9ad023890d3b34cf45e429df2a8ae88b419128sewardj cf = (CC_DEP2 >> (DATA_BITS - 1)) & X86G_CC_MASK_C; \ 2868fc937421c954ff9f707254f028b1fa0410c473dsewardj pf = parity_table[(UChar)CC_DEP1]; \ 2878fc937421c954ff9f707254f028b1fa0410c473dsewardj af = 0; /* undefined */ \ 2888fc937421c954ff9f707254f028b1fa0410c473dsewardj zf = ((DATA_UTYPE)CC_DEP1 == 0) << 6; \ 2898fc937421c954ff9f707254f028b1fa0410c473dsewardj sf = lshift(CC_DEP1, 8 - DATA_BITS) & 0x80; \ 2908fc937421c954ff9f707254f028b1fa0410c473dsewardj /* of is defined if shift count == 1 */ \ 2912a9ad023890d3b34cf45e429df2a8ae88b419128sewardj of = lshift(CC_DEP2 ^ CC_DEP1, 12 - DATA_BITS) \ 2922a9ad023890d3b34cf45e429df2a8ae88b419128sewardj & X86G_CC_MASK_O; \ 2938fc937421c954ff9f707254f028b1fa0410c473dsewardj return cf | pf | af | zf | sf | of; \ 2948fc937421c954ff9f707254f028b1fa0410c473dsewardj } \ 2955f6303579435ddb8315e11c2f02c904b978782a0sewardj} 2965f6303579435ddb8315e11c2f02c904b978782a0sewardj 297b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/ 298b9c5cf639b3b21b972599d27207a033afc76ef67sewardj 2992a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj#define ACTIONS_SHR(DATA_BITS,DATA_UTYPE) \ 300b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{ \ 301b9c5cf639b3b21b972599d27207a033afc76ef67sewardj PREAMBLE(DATA_BITS); \ 3028fc937421c954ff9f707254f028b1fa0410c473dsewardj { Int cf, pf, af, zf, sf, of; \ 3038fc937421c954ff9f707254f028b1fa0410c473dsewardj cf = CC_DEP2 & 1; \ 3048fc937421c954ff9f707254f028b1fa0410c473dsewardj pf = parity_table[(UChar)CC_DEP1]; \ 3058fc937421c954ff9f707254f028b1fa0410c473dsewardj af = 0; /* undefined */ \ 3068fc937421c954ff9f707254f028b1fa0410c473dsewardj zf = ((DATA_UTYPE)CC_DEP1 == 0) << 6; \ 3078fc937421c954ff9f707254f028b1fa0410c473dsewardj sf = lshift(CC_DEP1, 8 - DATA_BITS) & 0x80; \ 3088fc937421c954ff9f707254f028b1fa0410c473dsewardj /* of is defined if shift count == 1 */ \ 3092a9ad023890d3b34cf45e429df2a8ae88b419128sewardj of = lshift(CC_DEP2 ^ CC_DEP1, 12 - DATA_BITS) \ 3102a9ad023890d3b34cf45e429df2a8ae88b419128sewardj & X86G_CC_MASK_O; \ 3118fc937421c954ff9f707254f028b1fa0410c473dsewardj return cf | pf | af | zf | sf | of; \ 3128fc937421c954ff9f707254f028b1fa0410c473dsewardj } \ 3135f6303579435ddb8315e11c2f02c904b978782a0sewardj} 3145f6303579435ddb8315e11c2f02c904b978782a0sewardj 315b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/ 316b9c5cf639b3b21b972599d27207a033afc76ef67sewardj 3178ee2de1f5f72c13120f59c0ca6ac8291219123dfsewardj/* ROL: cf' = lsb(result). of' = msb(result) ^ lsb(result). */ 3182a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj/* DEP1 = result, NDEP = old flags */ 319df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_ROL(DATA_BITS,DATA_UTYPE) \ 320b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{ \ 321b9c5cf639b3b21b972599d27207a033afc76ef67sewardj PREAMBLE(DATA_BITS); \ 3228fc937421c954ff9f707254f028b1fa0410c473dsewardj { Int fl \ 3232a9ad023890d3b34cf45e429df2a8ae88b419128sewardj = (CC_NDEP & ~(X86G_CC_MASK_O | X86G_CC_MASK_C)) \ 3242a9ad023890d3b34cf45e429df2a8ae88b419128sewardj | (X86G_CC_MASK_C & CC_DEP1) \ 3252a9ad023890d3b34cf45e429df2a8ae88b419128sewardj | (X86G_CC_MASK_O & (lshift(CC_DEP1, \ 3262a9ad023890d3b34cf45e429df2a8ae88b419128sewardj 11-(DATA_BITS-1)) \ 3278fc937421c954ff9f707254f028b1fa0410c473dsewardj ^ lshift(CC_DEP1, 11))); \ 3288fc937421c954ff9f707254f028b1fa0410c473dsewardj return fl; \ 3298fc937421c954ff9f707254f028b1fa0410c473dsewardj } \ 3308c7f1abe9e022f6382634efea09c9cac89ec6336sewardj} 3318c7f1abe9e022f6382634efea09c9cac89ec6336sewardj 332b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/ 333b9c5cf639b3b21b972599d27207a033afc76ef67sewardj 3341813dbeb912870e9a544cae17a3fadbf8d2b0d55sewardj/* ROR: cf' = msb(result). of' = msb(result) ^ msb-1(result). */ 3352a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj/* DEP1 = result, NDEP = old flags */ 336df22c1c8b9c7fb712e6471a391d2615c48afaa6dsewardj#define ACTIONS_ROR(DATA_BITS,DATA_UTYPE) \ 337b9c5cf639b3b21b972599d27207a033afc76ef67sewardj{ \ 338b9c5cf639b3b21b972599d27207a033afc76ef67sewardj PREAMBLE(DATA_BITS); \ 3398fc937421c954ff9f707254f028b1fa0410c473dsewardj { Int fl \ 3402a9ad023890d3b34cf45e429df2a8ae88b419128sewardj = (CC_NDEP & ~(X86G_CC_MASK_O | X86G_CC_MASK_C)) \ 3412a9ad023890d3b34cf45e429df2a8ae88b419128sewardj | (X86G_CC_MASK_C & (CC_DEP1 >> (DATA_BITS-1))) \ 3422a9ad023890d3b34cf45e429df2a8ae88b419128sewardj | (X86G_CC_MASK_O & (lshift(CC_DEP1, \ 3432a9ad023890d3b34cf45e429df2a8ae88b419128sewardj 11-(DATA_BITS-1)) \ 3448fc937421c954ff9f707254f028b1fa0410c473dsewardj ^ lshift(CC_DEP1, 11-(DATA_BITS-1)+1))); \ 3458fc937421c954ff9f707254f028b1fa0410c473dsewardj return fl; \ 3468fc937421c954ff9f707254f028b1fa0410c473dsewardj } \ 3471813dbeb912870e9a544cae17a3fadbf8d2b0d55sewardj} 3481813dbeb912870e9a544cae17a3fadbf8d2b0d55sewardj 349b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/ 350b9c5cf639b3b21b972599d27207a033afc76ef67sewardj 3512a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj#define ACTIONS_UMUL(DATA_BITS,DATA_UTYPE,DATA_U2TYPE) \ 3522a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj{ \ 3532a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj PREAMBLE(DATA_BITS); \ 3548fc937421c954ff9f707254f028b1fa0410c473dsewardj { Int cf, pf, af, zf, sf, of; \ 3558fc937421c954ff9f707254f028b1fa0410c473dsewardj DATA_UTYPE hi; \ 3568fc937421c954ff9f707254f028b1fa0410c473dsewardj DATA_UTYPE lo = ((DATA_UTYPE)CC_DEP1) \ 3578fc937421c954ff9f707254f028b1fa0410c473dsewardj * ((DATA_UTYPE)CC_DEP2); \ 3588fc937421c954ff9f707254f028b1fa0410c473dsewardj DATA_U2TYPE rr = ((DATA_U2TYPE)((DATA_UTYPE)CC_DEP1)) \ 3598fc937421c954ff9f707254f028b1fa0410c473dsewardj * ((DATA_U2TYPE)((DATA_UTYPE)CC_DEP2)); \ 3608fc937421c954ff9f707254f028b1fa0410c473dsewardj hi = (DATA_UTYPE)(rr >>/*u*/ DATA_BITS); \ 3618fc937421c954ff9f707254f028b1fa0410c473dsewardj cf = (hi != 0); \ 3628fc937421c954ff9f707254f028b1fa0410c473dsewardj pf = parity_table[(UChar)lo]; \ 3638fc937421c954ff9f707254f028b1fa0410c473dsewardj af = 0; /* undefined */ \ 3648fc937421c954ff9f707254f028b1fa0410c473dsewardj zf = (lo == 0) << 6; \ 3658fc937421c954ff9f707254f028b1fa0410c473dsewardj sf = lshift(lo, 8 - DATA_BITS) & 0x80; \ 3668fc937421c954ff9f707254f028b1fa0410c473dsewardj of = cf << 11; \ 3678fc937421c954ff9f707254f028b1fa0410c473dsewardj return cf | pf | af | zf | sf | of; \ 3688fc937421c954ff9f707254f028b1fa0410c473dsewardj } \ 36956296d80c9e15ec59eebecf1c3aea9ebd4dac115sewardj} 37056296d80c9e15ec59eebecf1c3aea9ebd4dac115sewardj 371b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/*-------------------------------------------------------------*/ 372b9c5cf639b3b21b972599d27207a033afc76ef67sewardj 3732a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj#define ACTIONS_SMUL(DATA_BITS,DATA_STYPE,DATA_S2TYPE) \ 3742a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj{ \ 3752a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj PREAMBLE(DATA_BITS); \ 3768fc937421c954ff9f707254f028b1fa0410c473dsewardj { Int cf, pf, af, zf, sf, of; \ 3778fc937421c954ff9f707254f028b1fa0410c473dsewardj DATA_STYPE hi; \ 3788fc937421c954ff9f707254f028b1fa0410c473dsewardj DATA_STYPE lo = ((DATA_STYPE)CC_DEP1) \ 3798fc937421c954ff9f707254f028b1fa0410c473dsewardj * ((DATA_STYPE)CC_DEP2); \ 3808fc937421c954ff9f707254f028b1fa0410c473dsewardj DATA_S2TYPE rr = ((DATA_S2TYPE)((DATA_STYPE)CC_DEP1)) \ 3818fc937421c954ff9f707254f028b1fa0410c473dsewardj * ((DATA_S2TYPE)((DATA_STYPE)CC_DEP2)); \ 3828fc937421c954ff9f707254f028b1fa0410c473dsewardj hi = (DATA_STYPE)(rr >>/*s*/ DATA_BITS); \ 3838fc937421c954ff9f707254f028b1fa0410c473dsewardj cf = (hi != (lo >>/*s*/ (DATA_BITS-1))); \ 3848fc937421c954ff9f707254f028b1fa0410c473dsewardj pf = parity_table[(UChar)lo]; \ 3858fc937421c954ff9f707254f028b1fa0410c473dsewardj af = 0; /* undefined */ \ 3868fc937421c954ff9f707254f028b1fa0410c473dsewardj zf = (lo == 0) << 6; \ 3878fc937421c954ff9f707254f028b1fa0410c473dsewardj sf = lshift(lo, 8 - DATA_BITS) & 0x80; \ 3888fc937421c954ff9f707254f028b1fa0410c473dsewardj of = cf << 11; \ 3898fc937421c954ff9f707254f028b1fa0410c473dsewardj return cf | pf | af | zf | sf | of; \ 3908fc937421c954ff9f707254f028b1fa0410c473dsewardj } \ 3917ed2295459ac5e788a98dd5570fef0d4645c27d4sewardj} 392741153c4301023a420ab45b8a10b8e1bac968822sewardj 39336ca51378f8851635df814230fa23f2c409b9eddsewardj 39484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#if PROFILE_EFLAGS 39584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj 3962a9ad023890d3b34cf45e429df2a8ae88b419128sewardjstatic UInt tabc[X86G_CC_OP_NUMBER]; 3972a9ad023890d3b34cf45e429df2a8ae88b419128sewardjstatic UInt tab[X86G_CC_OP_NUMBER][16]; 3989eab588e223e52b1e7b710ff1c0da7b032ab2837sewardjstatic Bool initted = False; 39984ff0657940e62f38e618ea18bac6f27ce0e741fsewardjstatic UInt n_calc_cond = 0; 40084ff0657940e62f38e618ea18bac6f27ce0e741fsewardjstatic UInt n_calc_all = 0; 40184ff0657940e62f38e618ea18bac6f27ce0e741fsewardjstatic UInt n_calc_c = 0; 40284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj 40384ff0657940e62f38e618ea18bac6f27ce0e741fsewardjstatic void showCounts ( void ) 40484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj{ 40584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj Int op, co; 40684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj Char ch; 4079eab588e223e52b1e7b710ff1c0da7b032ab2837sewardj vex_printf("\nALL=%d COND=%d C=%d\n", 40884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj n_calc_all-n_calc_cond-n_calc_c, n_calc_cond, n_calc_c); 40984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj vex_printf(" CARRY O NO B NB Z NZ BE NBE" 41084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj " S NS P NP L NL LE NLE\n"); 41184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj vex_printf(" ----------------------------------------------" 41284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj "----------------------------------------\n"); 4132a9ad023890d3b34cf45e429df2a8ae88b419128sewardj for (op = 0; op < X86G_CC_OP_NUMBER; op++) { 41484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj 41584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj ch = ' '; 41693d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj if (op > 0 && (op-1) % 3 == 0) 41793d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj ch = 'B'; 41893d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj if (op > 0 && (op-1) % 3 == 1) 41993d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj ch = 'W'; 42084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj if (op > 0 && (op-1) % 3 == 2) 42184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj ch = 'L'; 42284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj 42384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj vex_printf("%2d%c: ", op, ch); 42484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj vex_printf("%6d ", tabc[op]); 42584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj for (co = 0; co < 16; co++) { 42684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj Int n = tab[op][co]; 42784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj if (n >= 1000) { 42884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj vex_printf(" %3dK", n / 1000); 42984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj } else 43084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj if (n >= 0) { 43184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj vex_printf(" %3d ", n ); 43284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj } else { 43384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj vex_printf(" "); 43484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj } 43584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj } 43684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj vex_printf("\n"); 43784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj } 43884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj vex_printf("\n"); 43984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj} 44084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj 44184ff0657940e62f38e618ea18bac6f27ce0e741fsewardjstatic void initCounts ( void ) 44284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj{ 44384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj Int op, co; 44484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj initted = True; 4452a9ad023890d3b34cf45e429df2a8ae88b419128sewardj for (op = 0; op < X86G_CC_OP_NUMBER; op++) { 44684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj tabc[op] = 0; 44784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj for (co = 0; co < 16; co++) 44884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj tab[op][co] = 0; 44984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj } 45084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj} 45184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj 45284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#endif /* PROFILE_EFLAGS */ 45384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj 4549aebb0c3f7a7f43313786826f31402f2b733badfsewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */ 455b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/* Calculate all the 6 flags from the supplied thunk parameters. */ 4562a9ad023890d3b34cf45e429df2a8ae88b419128sewardjUInt x86g_calculate_eflags_all ( UInt cc_op, 4572a9ad023890d3b34cf45e429df2a8ae88b419128sewardj UInt cc_dep1_formal, 4582a9ad023890d3b34cf45e429df2a8ae88b419128sewardj UInt cc_dep2_formal, 4592a9ad023890d3b34cf45e429df2a8ae88b419128sewardj UInt cc_ndep_formal ) 46036ca51378f8851635df814230fa23f2c409b9eddsewardj{ 46184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj# if PROFILE_EFLAGS 46284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj n_calc_all++; 46384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj# endif 46436ca51378f8851635df814230fa23f2c409b9eddsewardj switch (cc_op) { 4652a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86G_CC_OP_COPY: 4662a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj return cc_dep1_formal 4672a9ad023890d3b34cf45e429df2a8ae88b419128sewardj & (X86G_CC_MASK_O | X86G_CC_MASK_S | X86G_CC_MASK_Z 4682a9ad023890d3b34cf45e429df2a8ae88b419128sewardj | X86G_CC_MASK_A | X86G_CC_MASK_C | X86G_CC_MASK_P); 46914731f22bf7759d6d23383ca870ac89d9581f1e9sewardj 4702a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86G_CC_OP_ADDB: ACTIONS_ADD( 8, UChar ); 4712a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86G_CC_OP_ADDW: ACTIONS_ADD( 16, UShort ); 4722a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86G_CC_OP_ADDL: ACTIONS_ADD( 32, UInt ); 473a238471814bd386aeb58a76718b41e68b1a794b2sewardj 4742a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86G_CC_OP_ADCB: ACTIONS_ADC( 8, UChar ); 4752a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86G_CC_OP_ADCW: ACTIONS_ADC( 16, UShort ); 4762a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86G_CC_OP_ADCL: ACTIONS_ADC( 32, UInt ); 477a238471814bd386aeb58a76718b41e68b1a794b2sewardj 4782a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86G_CC_OP_SUBB: ACTIONS_SUB( 8, UChar ); 4792a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86G_CC_OP_SUBW: ACTIONS_SUB( 16, UShort ); 4802a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86G_CC_OP_SUBL: ACTIONS_SUB( 32, UInt ); 481afc5787e1c4b8e9678669577cf57ac509c6cd6b5sewardj 4822a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86G_CC_OP_SBBB: ACTIONS_SBB( 8, UChar ); 4832a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86G_CC_OP_SBBW: ACTIONS_SBB( 16, UShort ); 4842a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86G_CC_OP_SBBL: ACTIONS_SBB( 32, UInt ); 485741153c4301023a420ab45b8a10b8e1bac968822sewardj 4862a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86G_CC_OP_LOGICB: ACTIONS_LOGIC( 8, UChar ); 4872a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86G_CC_OP_LOGICW: ACTIONS_LOGIC( 16, UShort ); 4882a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86G_CC_OP_LOGICL: ACTIONS_LOGIC( 32, UInt ); 4895f6303579435ddb8315e11c2f02c904b978782a0sewardj 4902a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86G_CC_OP_INCB: ACTIONS_INC( 8, UChar ); 4912a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86G_CC_OP_INCW: ACTIONS_INC( 16, UShort ); 4922a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86G_CC_OP_INCL: ACTIONS_INC( 32, UInt ); 4931813dbeb912870e9a544cae17a3fadbf8d2b0d55sewardj 4942a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86G_CC_OP_DECB: ACTIONS_DEC( 8, UChar ); 4952a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86G_CC_OP_DECW: ACTIONS_DEC( 16, UShort ); 4962a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86G_CC_OP_DECL: ACTIONS_DEC( 32, UInt ); 4978c7f1abe9e022f6382634efea09c9cac89ec6336sewardj 4982a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86G_CC_OP_SHLB: ACTIONS_SHL( 8, UChar ); 4992a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86G_CC_OP_SHLW: ACTIONS_SHL( 16, UShort ); 5002a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86G_CC_OP_SHLL: ACTIONS_SHL( 32, UInt ); 5018c7f1abe9e022f6382634efea09c9cac89ec6336sewardj 5022a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86G_CC_OP_SHRB: ACTIONS_SHR( 8, UChar ); 5032a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86G_CC_OP_SHRW: ACTIONS_SHR( 16, UShort ); 5042a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86G_CC_OP_SHRL: ACTIONS_SHR( 32, UInt ); 5051813dbeb912870e9a544cae17a3fadbf8d2b0d55sewardj 5062a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86G_CC_OP_ROLB: ACTIONS_ROL( 8, UChar ); 5072a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86G_CC_OP_ROLW: ACTIONS_ROL( 16, UShort ); 5082a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86G_CC_OP_ROLL: ACTIONS_ROL( 32, UInt ); 509750f407b6be1aac303964a219acf0a6de8b8c4dasewardj 5102a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86G_CC_OP_RORB: ACTIONS_ROR( 8, UChar ); 5112a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86G_CC_OP_RORW: ACTIONS_ROR( 16, UShort ); 5122a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86G_CC_OP_RORL: ACTIONS_ROR( 32, UInt ); 5137ed2295459ac5e788a98dd5570fef0d4645c27d4sewardj 5142a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86G_CC_OP_UMULB: ACTIONS_UMUL( 8, UChar, UShort ); 5152a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86G_CC_OP_UMULW: ACTIONS_UMUL( 16, UShort, UInt ); 5162a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86G_CC_OP_UMULL: ACTIONS_UMUL( 32, UInt, ULong ); 51756296d80c9e15ec59eebecf1c3aea9ebd4dac115sewardj 5182a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86G_CC_OP_SMULB: ACTIONS_SMUL( 8, Char, Short ); 5192a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86G_CC_OP_SMULW: ACTIONS_SMUL( 16, Short, Int ); 5202a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86G_CC_OP_SMULL: ACTIONS_SMUL( 32, Int, Long ); 521741153c4301023a420ab45b8a10b8e1bac968822sewardj 52236ca51378f8851635df814230fa23f2c409b9eddsewardj default: 52336ca51378f8851635df814230fa23f2c409b9eddsewardj /* shouldn't really make these calls from generated code */ 5242a9ad023890d3b34cf45e429df2a8ae88b419128sewardj vex_printf("calculate_eflags_all(X86)( %d, 0x%x, 0x%x, 0x%x )\n", 5252a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj cc_op, cc_dep1_formal, cc_dep2_formal, cc_ndep_formal ); 5262a9ad023890d3b34cf45e429df2a8ae88b419128sewardj vpanic("calculate_eflags_all(X86)"); 52736ca51378f8851635df814230fa23f2c409b9eddsewardj } 52836ca51378f8851635df814230fa23f2c409b9eddsewardj} 52936ca51378f8851635df814230fa23f2c409b9eddsewardj 530b9c5cf639b3b21b972599d27207a033afc76ef67sewardj 5319aebb0c3f7a7f43313786826f31402f2b733badfsewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */ 532b9c5cf639b3b21b972599d27207a033afc76ef67sewardj/* Calculate just the carry flag from the supplied thunk parameters. */ 5332a9ad023890d3b34cf45e429df2a8ae88b419128sewardjUInt x86g_calculate_eflags_c ( UInt cc_op, 5342a9ad023890d3b34cf45e429df2a8ae88b419128sewardj UInt cc_dep1, 5352a9ad023890d3b34cf45e429df2a8ae88b419128sewardj UInt cc_dep2, 5362a9ad023890d3b34cf45e429df2a8ae88b419128sewardj UInt cc_ndep ) 53736ca51378f8851635df814230fa23f2c409b9eddsewardj{ 5389eab588e223e52b1e7b710ff1c0da7b032ab2837sewardj /* Fast-case some common ones. */ 53943c46951628d616290f7245c3af2f9a652180806sewardj switch (cc_op) { 5402a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86G_CC_OP_LOGICL: 5412a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86G_CC_OP_LOGICW: 5422a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86G_CC_OP_LOGICB: 54343c46951628d616290f7245c3af2f9a652180806sewardj return 0; 5442a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86G_CC_OP_SUBL: 54593d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj return ((UInt)cc_dep1) < ((UInt)cc_dep2) 5462a9ad023890d3b34cf45e429df2a8ae88b419128sewardj ? X86G_CC_MASK_C : 0; 5472a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86G_CC_OP_SUBB: 54893d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj return ((UInt)(cc_dep1 & 0xFF)) < ((UInt)(cc_dep2 & 0xFF)) 5492a9ad023890d3b34cf45e429df2a8ae88b419128sewardj ? X86G_CC_MASK_C : 0; 550e9ba4328f2afb94bc8474e9a7205e50ed9ac73fcsewardj case X86G_CC_OP_INCL: 5512a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86G_CC_OP_DECL: 552e9ba4328f2afb94bc8474e9a7205e50ed9ac73fcsewardj return cc_ndep & X86G_CC_MASK_C; 553e9ba4328f2afb94bc8474e9a7205e50ed9ac73fcsewardj#if 0 554e9ba4328f2afb94bc8474e9a7205e50ed9ac73fcsewardj /* unclear if these are correct or not */ 5552a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86G_CC_OP_ADDL: 55643c46951628d616290f7245c3af2f9a652180806sewardj return ( ((UInt)cc_src + (UInt)cc_dst) < ((UInt)cc_src) ) 5572a9ad023890d3b34cf45e429df2a8ae88b419128sewardj ? X86G_CC_MASK_C : 0; 5582a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86G_CC_OP_SUBB: 55943c46951628d616290f7245c3af2f9a652180806sewardj return ( ((UInt)(cc_src & 0xFF)) > ((UInt)(cc_dst & 0xFF)) ) 5602a9ad023890d3b34cf45e429df2a8ae88b419128sewardj ? X86G_CC_MASK_C : 0; 561948d48be23eca9df7b9d33be5dca499affb7cb3asewardj#endif 56243c46951628d616290f7245c3af2f9a652180806sewardj default: 56343c46951628d616290f7245c3af2f9a652180806sewardj break; 56443c46951628d616290f7245c3af2f9a652180806sewardj } 5659eab588e223e52b1e7b710ff1c0da7b032ab2837sewardj 56684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj# if PROFILE_EFLAGS 56784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj if (!initted) 56884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj initCounts(); 56984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj tabc[cc_op]++; 57084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj 57184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj n_calc_c++; 57284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj# endif 5732a9ad023890d3b34cf45e429df2a8ae88b419128sewardj return x86g_calculate_eflags_all(cc_op,cc_dep1,cc_dep2,cc_ndep) 5742a9ad023890d3b34cf45e429df2a8ae88b419128sewardj & X86G_CC_MASK_C; 57536ca51378f8851635df814230fa23f2c409b9eddsewardj} 57636ca51378f8851635df814230fa23f2c409b9eddsewardj 57736ca51378f8851635df814230fa23f2c409b9eddsewardj 5789aebb0c3f7a7f43313786826f31402f2b733badfsewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */ 57984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj/* returns 1 or 0 */ 5802a9ad023890d3b34cf45e429df2a8ae88b419128sewardjUInt x86g_calculate_condition ( UInt/*X86Condcode*/ cond, 5812a9ad023890d3b34cf45e429df2a8ae88b419128sewardj UInt cc_op, 5822a9ad023890d3b34cf45e429df2a8ae88b419128sewardj UInt cc_dep1, 5832a9ad023890d3b34cf45e429df2a8ae88b419128sewardj UInt cc_dep2, 5842a9ad023890d3b34cf45e429df2a8ae88b419128sewardj UInt cc_ndep ) 5852a9ad023890d3b34cf45e429df2a8ae88b419128sewardj{ 5862a9ad023890d3b34cf45e429df2a8ae88b419128sewardj UInt eflags = x86g_calculate_eflags_all(cc_op, cc_dep1, 5872a9ad023890d3b34cf45e429df2a8ae88b419128sewardj cc_dep2, cc_ndep); 58884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj UInt of,sf,zf,cf,pf; 58984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj UInt inv = cond & 1; 59084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj 59184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj# if PROFILE_EFLAGS 59284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj if (!initted) 59384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj initCounts(); 59484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj 59584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj tab[cc_op][cond]++; 59684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj n_calc_cond++; 59784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj 59893d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj if (0 == ((n_calc_all+n_calc_c) & 0x7FFFF)) showCounts(); 59984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj# endif 60084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj 60184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj switch (cond) { 6022a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86CondNO: 6032a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86CondO: /* OF == 1 */ 6042a9ad023890d3b34cf45e429df2a8ae88b419128sewardj of = eflags >> X86G_CC_SHIFT_O; 60584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj return 1 & (inv ^ of); 60684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj 6072a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86CondNZ: 6082a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86CondZ: /* ZF == 1 */ 6092a9ad023890d3b34cf45e429df2a8ae88b419128sewardj zf = eflags >> X86G_CC_SHIFT_Z; 61084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj return 1 & (inv ^ zf); 61184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj 6122a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86CondNB: 6132a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86CondB: /* CF == 1 */ 6142a9ad023890d3b34cf45e429df2a8ae88b419128sewardj cf = eflags >> X86G_CC_SHIFT_C; 61584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj return 1 & (inv ^ cf); 61684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj break; 61784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj 6182a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86CondNBE: 6192a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86CondBE: /* (CF or ZF) == 1 */ 6202a9ad023890d3b34cf45e429df2a8ae88b419128sewardj cf = eflags >> X86G_CC_SHIFT_C; 6212a9ad023890d3b34cf45e429df2a8ae88b419128sewardj zf = eflags >> X86G_CC_SHIFT_Z; 62284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj return 1 & (inv ^ (cf | zf)); 62384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj break; 62484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj 6252a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86CondNS: 6262a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86CondS: /* SF == 1 */ 6272a9ad023890d3b34cf45e429df2a8ae88b419128sewardj sf = eflags >> X86G_CC_SHIFT_S; 62884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj return 1 & (inv ^ sf); 62984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj 6302a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86CondNP: 6312a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86CondP: /* PF == 1 */ 6322a9ad023890d3b34cf45e429df2a8ae88b419128sewardj pf = eflags >> X86G_CC_SHIFT_P; 63384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj return 1 & (inv ^ pf); 63484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj 6352a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86CondNL: 6362a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86CondL: /* (SF xor OF) == 1 */ 6372a9ad023890d3b34cf45e429df2a8ae88b419128sewardj sf = eflags >> X86G_CC_SHIFT_S; 6382a9ad023890d3b34cf45e429df2a8ae88b419128sewardj of = eflags >> X86G_CC_SHIFT_O; 63984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj return 1 & (inv ^ (sf ^ of)); 64084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj break; 64184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj 6422a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86CondNLE: 6432a9ad023890d3b34cf45e429df2a8ae88b419128sewardj case X86CondLE: /* ((SF xor OF) or ZF) == 1 */ 6442a9ad023890d3b34cf45e429df2a8ae88b419128sewardj sf = eflags >> X86G_CC_SHIFT_S; 6452a9ad023890d3b34cf45e429df2a8ae88b419128sewardj of = eflags >> X86G_CC_SHIFT_O; 6462a9ad023890d3b34cf45e429df2a8ae88b419128sewardj zf = eflags >> X86G_CC_SHIFT_Z; 64784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj return 1 & (inv ^ ((sf ^ of) | zf)); 64884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj break; 64984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj 65084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj default: 65184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj /* shouldn't really make these calls from generated code */ 6522a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj vex_printf("calculate_condition( %d, %d, 0x%x, 0x%x, 0x%x )\n", 6532a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj cond, cc_op, cc_dep1, cc_dep2, cc_ndep ); 65484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj vpanic("calculate_condition"); 65584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj } 65684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj} 65784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj 65884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj 65984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj/* Used by the optimiser to try specialisations. Returns an 66084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj equivalent expression, or NULL if none. */ 66184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj 66284ff0657940e62f38e618ea18bac6f27ce0e741fsewardjstatic Bool isU32 ( IRExpr* e, UInt n ) 66384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj{ 66484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj return e->tag == Iex_Const 66584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj && e->Iex.Const.con->tag == Ico_U32 66684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj && e->Iex.Const.con->Ico.U32 == n; 66784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj} 66884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj 6692a9ad023890d3b34cf45e429df2a8ae88b419128sewardjIRExpr* guest_x86_spechelper ( Char* function_name, 6702a9ad023890d3b34cf45e429df2a8ae88b419128sewardj IRExpr** args ) 67184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj{ 67284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj# define unop(_op,_a1) IRExpr_Unop((_op),(_a1)) 67384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj# define binop(_op,_a1,_a2) IRExpr_Binop((_op),(_a1),(_a2)) 67484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj# define mkU32(_n) IRExpr_Const(IRConst_U32(_n)) 6754afab82eb869f21ccabc3efb5b93f31a5c343956sewardj# define mkU8(_n) IRExpr_Const(IRConst_U8(_n)) 67684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj 67784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj Int i, arity = 0; 67884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj for (i = 0; args[i]; i++) 67984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj arity++; 68084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj# if 0 68184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj vex_printf("spec request:\n"); 68284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj vex_printf(" %s ", function_name); 68384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj for (i = 0; i < arity; i++) { 68484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj vex_printf(" "); 68584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj ppIRExpr(args[i]); 68684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj } 68784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj vex_printf("\n"); 68884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj# endif 68993d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj 6903835288ac63bb755c0e1d2f3142a13416dcb64c6sewardj /* --------- specialising "x86g_calculate_eflags_c" --------- */ 69193d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj 6923835288ac63bb755c0e1d2f3142a13416dcb64c6sewardj if (vex_streq(function_name, "x86g_calculate_eflags_c")) { 69384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj /* specialise calls to above "calculate_eflags_c" function */ 69493d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj IRExpr *cc_op, *cc_dep1, *cc_dep2, *cc_ndep; 69593d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj vassert(arity == 4); 69693d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj cc_op = args[0]; 69793d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj cc_dep1 = args[1]; 69893d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj cc_dep2 = args[2]; 69993d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj cc_ndep = args[3]; 70084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj 7012a9ad023890d3b34cf45e429df2a8ae88b419128sewardj if (isU32(cc_op, X86G_CC_OP_SUBL)) { 70293d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj /* C after sub denotes unsigned less than */ 70393d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj return unop(Iop_1Uto32, 70493d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj binop(Iop_CmpLT32U, cc_dep1, cc_dep2)); 70593d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj } 706e9ba4328f2afb94bc8474e9a7205e50ed9ac73fcsewardj if (isU32(cc_op, X86G_CC_OP_SUBB)) { 707e9ba4328f2afb94bc8474e9a7205e50ed9ac73fcsewardj /* C after sub denotes unsigned less than */ 708e9ba4328f2afb94bc8474e9a7205e50ed9ac73fcsewardj return unop(Iop_1Uto32, 709e9ba4328f2afb94bc8474e9a7205e50ed9ac73fcsewardj binop(Iop_CmpLT32U, 710e9ba4328f2afb94bc8474e9a7205e50ed9ac73fcsewardj binop(Iop_And32,cc_dep1,mkU32(0xFF)), 711e9ba4328f2afb94bc8474e9a7205e50ed9ac73fcsewardj binop(Iop_And32,cc_dep2,mkU32(0xFF)))); 712e9ba4328f2afb94bc8474e9a7205e50ed9ac73fcsewardj } 7132a9ad023890d3b34cf45e429df2a8ae88b419128sewardj if (isU32(cc_op, X86G_CC_OP_LOGICL)) { 71484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj /* cflag after logic is zero */ 71584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj return mkU32(0); 71684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj } 7172a9ad023890d3b34cf45e429df2a8ae88b419128sewardj if (isU32(cc_op, X86G_CC_OP_DECL) || isU32(cc_op, X86G_CC_OP_INCL)) { 71822419b8f4f2c0104549ca9954f68e190b911d1a0sewardj /* If the thunk is dec or inc, the cflag is supplied as CC_NDEP. */ 719e7bd0686e5d90b22fe7fe12ae00afb8a71ab008asewardj return cc_ndep; 72084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj } 72107f284e78c5d8bb00e2f4fcaed5bb29571d6058asewardj if (isU32(cc_op, X86G_CC_OP_COPY)) { 72207f284e78c5d8bb00e2f4fcaed5bb29571d6058asewardj /* cflag after COPY is stored in DEP1. */ 72307f284e78c5d8bb00e2f4fcaed5bb29571d6058asewardj return 72407f284e78c5d8bb00e2f4fcaed5bb29571d6058asewardj binop( 72507f284e78c5d8bb00e2f4fcaed5bb29571d6058asewardj Iop_And32, 72607f284e78c5d8bb00e2f4fcaed5bb29571d6058asewardj binop(Iop_Shr32, cc_dep1, mkU8(X86G_CC_SHIFT_C)), 72707f284e78c5d8bb00e2f4fcaed5bb29571d6058asewardj mkU32(1) 72807f284e78c5d8bb00e2f4fcaed5bb29571d6058asewardj ); 72907f284e78c5d8bb00e2f4fcaed5bb29571d6058asewardj } 73084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj# if 0 73184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj if (cc_op->tag == Iex_Const) { 73284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj vex_printf("CFLAG "); ppIRExpr(cc_op); vex_printf("\n"); 73384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj } 73484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj# endif 73584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj 73684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj return NULL; 73784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj } 73884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj 7393835288ac63bb755c0e1d2f3142a13416dcb64c6sewardj /* --------- specialising "x86g_calculate_condition" --------- */ 74093d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj 7413835288ac63bb755c0e1d2f3142a13416dcb64c6sewardj if (vex_streq(function_name, "x86g_calculate_condition")) { 74284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj /* specialise calls to above "calculate condition" function */ 743a8415ffe6c6f0e73519301a55026a4071c701fd1sewardj IRExpr *cond, *cc_op, *cc_dep1, *cc_dep2; 74493d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj vassert(arity == 5); 74593d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj cond = args[0]; 74693d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj cc_op = args[1]; 74793d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj cc_dep1 = args[2]; 74893d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj cc_dep2 = args[3]; 74984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj 750d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj /*---------------- ADDL ----------------*/ 751d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj 7522a9ad023890d3b34cf45e429df2a8ae88b419128sewardj if (isU32(cc_op, X86G_CC_OP_ADDL) && isU32(cond, X86CondZ)) { 753d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj /* long add, then Z --> test (dst+src == 0) */ 754d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj return unop(Iop_1Uto32, 755d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj binop(Iop_CmpEQ32, 756d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj binop(Iop_Add32, cc_dep1, cc_dep2), 757d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj mkU32(0))); 758d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj } 759d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj 76046ccb51aff085d180120d310c0be2fe6c86e1b65sewardj /*---------------- SUBL ----------------*/ 76146ccb51aff085d180120d310c0be2fe6c86e1b65sewardj 7622a9ad023890d3b34cf45e429df2a8ae88b419128sewardj if (isU32(cc_op, X86G_CC_OP_SUBL) && isU32(cond, X86CondZ)) { 76346ccb51aff085d180120d310c0be2fe6c86e1b65sewardj /* long sub/cmp, then Z --> test dst==src */ 76484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj return unop(Iop_1Uto32, 76593d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj binop(Iop_CmpEQ32, cc_dep1, cc_dep2)); 76646ccb51aff085d180120d310c0be2fe6c86e1b65sewardj } 76746ccb51aff085d180120d310c0be2fe6c86e1b65sewardj 7682a9ad023890d3b34cf45e429df2a8ae88b419128sewardj if (isU32(cc_op, X86G_CC_OP_SUBL) && isU32(cond, X86CondL)) { 76946ccb51aff085d180120d310c0be2fe6c86e1b65sewardj /* long sub/cmp, then L (signed less than) 77046ccb51aff085d180120d310c0be2fe6c86e1b65sewardj --> test dst <s src */ 77146ccb51aff085d180120d310c0be2fe6c86e1b65sewardj return unop(Iop_1Uto32, 77293d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj binop(Iop_CmpLT32S, cc_dep1, cc_dep2)); 77346ccb51aff085d180120d310c0be2fe6c86e1b65sewardj } 77446ccb51aff085d180120d310c0be2fe6c86e1b65sewardj 7752a9ad023890d3b34cf45e429df2a8ae88b419128sewardj if (isU32(cc_op, X86G_CC_OP_SUBL) && isU32(cond, X86CondLE)) { 77646ccb51aff085d180120d310c0be2fe6c86e1b65sewardj /* long sub/cmp, then LE (signed less than or equal) 77746ccb51aff085d180120d310c0be2fe6c86e1b65sewardj --> test dst <=s src */ 77846ccb51aff085d180120d310c0be2fe6c86e1b65sewardj return unop(Iop_1Uto32, 77993d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj binop(Iop_CmpLE32S, cc_dep1, cc_dep2)); 78046ccb51aff085d180120d310c0be2fe6c86e1b65sewardj } 78146ccb51aff085d180120d310c0be2fe6c86e1b65sewardj 7822a9ad023890d3b34cf45e429df2a8ae88b419128sewardj if (isU32(cc_op, X86G_CC_OP_SUBL) && isU32(cond, X86CondBE)) { 78346ccb51aff085d180120d310c0be2fe6c86e1b65sewardj /* long sub/cmp, then BE (unsigned less than or equal) 78446ccb51aff085d180120d310c0be2fe6c86e1b65sewardj --> test dst <=u src */ 78546ccb51aff085d180120d310c0be2fe6c86e1b65sewardj return unop(Iop_1Uto32, 78693d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj binop(Iop_CmpLE32U, cc_dep1, cc_dep2)); 78746ccb51aff085d180120d310c0be2fe6c86e1b65sewardj } 788e664ec4b9f27ed7d7ca87a2d4188fd479059351csewardj 7892a9ad023890d3b34cf45e429df2a8ae88b419128sewardj if (isU32(cc_op, X86G_CC_OP_SUBL) && isU32(cond, X86CondB)) { 79046ccb51aff085d180120d310c0be2fe6c86e1b65sewardj /* long sub/cmp, then B (unsigned less than) 79146ccb51aff085d180120d310c0be2fe6c86e1b65sewardj --> test dst <u src */ 79246ccb51aff085d180120d310c0be2fe6c86e1b65sewardj return unop(Iop_1Uto32, 793e664ec4b9f27ed7d7ca87a2d4188fd479059351csewardj binop(Iop_CmpLT32U, cc_dep1, cc_dep2)); 79484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj } 795e664ec4b9f27ed7d7ca87a2d4188fd479059351csewardj 79646ccb51aff085d180120d310c0be2fe6c86e1b65sewardj /*---------------- SUBW ----------------*/ 79746ccb51aff085d180120d310c0be2fe6c86e1b65sewardj 7982a9ad023890d3b34cf45e429df2a8ae88b419128sewardj if (isU32(cc_op, X86G_CC_OP_SUBW) && isU32(cond, X86CondZ)) { 799b9c5cf639b3b21b972599d27207a033afc76ef67sewardj /* byte sub/cmp, then Z --> test dst==src */ 800b9c5cf639b3b21b972599d27207a033afc76ef67sewardj return unop(Iop_1Uto32, 801b9c5cf639b3b21b972599d27207a033afc76ef67sewardj binop(Iop_CmpEQ16, 8027e6644c38b3e0148ff95c2f6f4667f54148b611esewardj unop(Iop_32to16,cc_dep1), 8037e6644c38b3e0148ff95c2f6f4667f54148b611esewardj unop(Iop_32to16,cc_dep2))); 804b9c5cf639b3b21b972599d27207a033afc76ef67sewardj } 805b9c5cf639b3b21b972599d27207a033afc76ef67sewardj 80646ccb51aff085d180120d310c0be2fe6c86e1b65sewardj /*---------------- SUBB ----------------*/ 8077e6644c38b3e0148ff95c2f6f4667f54148b611esewardj 8082a9ad023890d3b34cf45e429df2a8ae88b419128sewardj if (isU32(cc_op, X86G_CC_OP_SUBB) && isU32(cond, X86CondZ)) { 809b9c5cf639b3b21b972599d27207a033afc76ef67sewardj /* byte sub/cmp, then Z --> test dst==src */ 81084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj return unop(Iop_1Uto32, 811b9c5cf639b3b21b972599d27207a033afc76ef67sewardj binop(Iop_CmpEQ8, 81293d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj unop(Iop_32to8,cc_dep1), 81393d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj unop(Iop_32to8,cc_dep2))); 81484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj } 81584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj 8162a9ad023890d3b34cf45e429df2a8ae88b419128sewardj if (isU32(cc_op, X86G_CC_OP_SUBB) && isU32(cond, X86CondNZ)) { 8177e5b7cdbfa65376488d58e4e6d8f13d974f7a8bcsewardj /* byte sub/cmp, then NZ --> test dst!=src */ 81884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj return unop(Iop_1Uto32, 819b9c5cf639b3b21b972599d27207a033afc76ef67sewardj binop(Iop_CmpNE8, 82093d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj unop(Iop_32to8,cc_dep1), 82193d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj unop(Iop_32to8,cc_dep2))); 822b9c5cf639b3b21b972599d27207a033afc76ef67sewardj } 82322419b8f4f2c0104549ca9954f68e190b911d1a0sewardj 8242a9ad023890d3b34cf45e429df2a8ae88b419128sewardj if (isU32(cc_op, X86G_CC_OP_SUBB) && isU32(cond, X86CondNBE)) { 825b9c5cf639b3b21b972599d27207a033afc76ef67sewardj /* long sub/cmp, then NBE (unsigned greater than) 826b9c5cf639b3b21b972599d27207a033afc76ef67sewardj --> test src <=u dst */ 8277e5b7cdbfa65376488d58e4e6d8f13d974f7a8bcsewardj /* Note, args are opposite way round from the usual */ 828b9c5cf639b3b21b972599d27207a033afc76ef67sewardj return unop(Iop_1Uto32, 829b9c5cf639b3b21b972599d27207a033afc76ef67sewardj binop(Iop_CmpLT32U, 8307e5b7cdbfa65376488d58e4e6d8f13d974f7a8bcsewardj binop(Iop_And32,cc_dep2,mkU32(0xFF)), 8317e5b7cdbfa65376488d58e4e6d8f13d974f7a8bcsewardj binop(Iop_And32,cc_dep1,mkU32(0xFF)))); 83284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj } 83384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj 83446ccb51aff085d180120d310c0be2fe6c86e1b65sewardj /*---------------- LOGICL ----------------*/ 83546ccb51aff085d180120d310c0be2fe6c86e1b65sewardj 8362a9ad023890d3b34cf45e429df2a8ae88b419128sewardj if (isU32(cc_op, X86G_CC_OP_LOGICL) && isU32(cond, X86CondZ)) { 83784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj /* long and/or/xor, then Z --> test dst==0 */ 83893d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj return unop(Iop_1Uto32,binop(Iop_CmpEQ32, cc_dep1, mkU32(0))); 83984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj } 84022419b8f4f2c0104549ca9954f68e190b911d1a0sewardj 8412a9ad023890d3b34cf45e429df2a8ae88b419128sewardj if (isU32(cc_op, X86G_CC_OP_LOGICL) && isU32(cond, X86CondS)) { 842fae2ca7ef81549a4b28235618317d4352ca32ac2sewardj /* long and/or/xor, then S --> test dst <s 0 */ 8437e6644c38b3e0148ff95c2f6f4667f54148b611esewardj return unop(Iop_1Uto32,binop(Iop_CmpLT32S, cc_dep1, mkU32(0))); 844fae2ca7ef81549a4b28235618317d4352ca32ac2sewardj } 84522419b8f4f2c0104549ca9954f68e190b911d1a0sewardj 8462a9ad023890d3b34cf45e429df2a8ae88b419128sewardj if (isU32(cc_op, X86G_CC_OP_LOGICL) && isU32(cond, X86CondLE)) { 84784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj /* long and/or/xor, then LE 84884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj This is pretty subtle. LOGIC sets SF and ZF according to the 84984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj result and makes OF be zero. LE computes (SZ ^ OF) | ZF, but 85084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj OF is zero, so this reduces to SZ | ZF -- which will be 1 iff 85184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj the result is <=signed 0. Hence ... 85284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj */ 85393d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj return unop(Iop_1Uto32,binop(Iop_CmpLE32S, cc_dep1, mkU32(0))); 85484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj } 85584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj 856d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj /*---------------- LOGICW ----------------*/ 857d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj 8582a9ad023890d3b34cf45e429df2a8ae88b419128sewardj if (isU32(cc_op, X86G_CC_OP_LOGICW) && isU32(cond, X86CondZ)) { 859d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj /* byte and/or/xor, then Z --> test dst==0 */ 860d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj return unop(Iop_1Uto32, 861d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj binop(Iop_CmpEQ32, binop(Iop_And32,cc_dep1,mkU32(0xFFFF)), 862d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj mkU32(0))); 863d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj } 864d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj 86546ccb51aff085d180120d310c0be2fe6c86e1b65sewardj /*---------------- LOGICB ----------------*/ 86684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj 8672a9ad023890d3b34cf45e429df2a8ae88b419128sewardj if (isU32(cc_op, X86G_CC_OP_LOGICB) && isU32(cond, X86CondZ)) { 86846ccb51aff085d180120d310c0be2fe6c86e1b65sewardj /* byte and/or/xor, then Z --> test dst==0 */ 86984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj return unop(Iop_1Uto32, 87093d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj binop(Iop_CmpEQ32, binop(Iop_And32,cc_dep1,mkU32(255)), 87146ccb51aff085d180120d310c0be2fe6c86e1b65sewardj mkU32(0))); 87284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj } 87384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj 87446ccb51aff085d180120d310c0be2fe6c86e1b65sewardj /*---------------- DECL ----------------*/ 875af991dede2815b7570828b9d9174cf989e636254sewardj 8762a9ad023890d3b34cf45e429df2a8ae88b419128sewardj if (isU32(cc_op, X86G_CC_OP_DECL) && isU32(cond, X86CondZ)) { 87784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj /* dec L, then Z --> test dst == 0 */ 87893d96e91167fc72c5ec1b8d615cd0f96674110b0sewardj return unop(Iop_1Uto32,binop(Iop_CmpEQ32, cc_dep1, mkU32(0))); 87984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj } 88022419b8f4f2c0104549ca9954f68e190b911d1a0sewardj 8812a9ad023890d3b34cf45e429df2a8ae88b419128sewardj if (isU32(cc_op, X86G_CC_OP_DECL) && isU32(cond, X86CondS)) { 882fae2ca7ef81549a4b28235618317d4352ca32ac2sewardj /* dec L, then S --> compare DST <s 0 */ 8837e6644c38b3e0148ff95c2f6f4667f54148b611esewardj return unop(Iop_1Uto32,binop(Iop_CmpLT32S, cc_dep1, mkU32(0))); 884fae2ca7ef81549a4b28235618317d4352ca32ac2sewardj } 885fae2ca7ef81549a4b28235618317d4352ca32ac2sewardj 886d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj /*---------------- SHRL ----------------*/ 887d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj 8882a9ad023890d3b34cf45e429df2a8ae88b419128sewardj if (isU32(cc_op, X86G_CC_OP_SHRL) && isU32(cond, X86CondZ)) { 889d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj /* SHRL, then Z --> test dep1 == 0 */ 890d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj return unop(Iop_1Uto32,binop(Iop_CmpEQ32, cc_dep1, mkU32(0))); 891d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj } 892d8e2dbf8298ebf9d8d512d24f56966685bc51faasewardj 8934afab82eb869f21ccabc3efb5b93f31a5c343956sewardj /*---------------- COPY ----------------*/ 8944afab82eb869f21ccabc3efb5b93f31a5c343956sewardj /* This can happen, as a result of x87 FP compares: "fcom ... ; 8954afab82eb869f21ccabc3efb5b93f31a5c343956sewardj fnstsw %ax ; sahf ; jbe" for example. */ 8964afab82eb869f21ccabc3efb5b93f31a5c343956sewardj 8974afab82eb869f21ccabc3efb5b93f31a5c343956sewardj if (isU32(cc_op, X86G_CC_OP_COPY) && isU32(cond, X86CondBE)) { 8984afab82eb869f21ccabc3efb5b93f31a5c343956sewardj /* COPY, then BE --> extract C and Z from dep1, and test (C 8994afab82eb869f21ccabc3efb5b93f31a5c343956sewardj or Z == 1). */ 9004afab82eb869f21ccabc3efb5b93f31a5c343956sewardj return 9014afab82eb869f21ccabc3efb5b93f31a5c343956sewardj unop( 9024afab82eb869f21ccabc3efb5b93f31a5c343956sewardj Iop_1Uto32, 9034afab82eb869f21ccabc3efb5b93f31a5c343956sewardj binop( 9044afab82eb869f21ccabc3efb5b93f31a5c343956sewardj Iop_CmpNE32, 9054afab82eb869f21ccabc3efb5b93f31a5c343956sewardj binop( 9064afab82eb869f21ccabc3efb5b93f31a5c343956sewardj Iop_And32, 9074afab82eb869f21ccabc3efb5b93f31a5c343956sewardj binop( 9084afab82eb869f21ccabc3efb5b93f31a5c343956sewardj Iop_Or32, 9094afab82eb869f21ccabc3efb5b93f31a5c343956sewardj binop(Iop_Shr32, cc_dep1, mkU8(X86G_CC_SHIFT_C)), 9104afab82eb869f21ccabc3efb5b93f31a5c343956sewardj binop(Iop_Shr32, cc_dep1, mkU8(X86G_CC_SHIFT_Z)) 9114afab82eb869f21ccabc3efb5b93f31a5c343956sewardj ), 9124afab82eb869f21ccabc3efb5b93f31a5c343956sewardj mkU32(1) 9134afab82eb869f21ccabc3efb5b93f31a5c343956sewardj ), 9144afab82eb869f21ccabc3efb5b93f31a5c343956sewardj mkU32(0) 9154afab82eb869f21ccabc3efb5b93f31a5c343956sewardj ) 9164afab82eb869f21ccabc3efb5b93f31a5c343956sewardj ); 9174afab82eb869f21ccabc3efb5b93f31a5c343956sewardj } 9184afab82eb869f21ccabc3efb5b93f31a5c343956sewardj 9194afab82eb869f21ccabc3efb5b93f31a5c343956sewardj if (isU32(cc_op, X86G_CC_OP_COPY) && isU32(cond, X86CondB)) { 9204afab82eb869f21ccabc3efb5b93f31a5c343956sewardj /* COPY, then B --> extract C dep1, and test (C == 1). */ 9214afab82eb869f21ccabc3efb5b93f31a5c343956sewardj return 9224afab82eb869f21ccabc3efb5b93f31a5c343956sewardj unop( 9234afab82eb869f21ccabc3efb5b93f31a5c343956sewardj Iop_1Uto32, 9244afab82eb869f21ccabc3efb5b93f31a5c343956sewardj binop( 9254afab82eb869f21ccabc3efb5b93f31a5c343956sewardj Iop_CmpNE32, 9264afab82eb869f21ccabc3efb5b93f31a5c343956sewardj binop( 9274afab82eb869f21ccabc3efb5b93f31a5c343956sewardj Iop_And32, 9284afab82eb869f21ccabc3efb5b93f31a5c343956sewardj binop(Iop_Shr32, cc_dep1, mkU8(X86G_CC_SHIFT_C)), 9294afab82eb869f21ccabc3efb5b93f31a5c343956sewardj mkU32(1) 9304afab82eb869f21ccabc3efb5b93f31a5c343956sewardj ), 9314afab82eb869f21ccabc3efb5b93f31a5c343956sewardj mkU32(0) 9324afab82eb869f21ccabc3efb5b93f31a5c343956sewardj ) 9334afab82eb869f21ccabc3efb5b93f31a5c343956sewardj ); 9344afab82eb869f21ccabc3efb5b93f31a5c343956sewardj } 9354afab82eb869f21ccabc3efb5b93f31a5c343956sewardj 93684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj return NULL; 93784ff0657940e62f38e618ea18bac6f27ce0e741fsewardj } 93884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj 93984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj# undef unop 94084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj# undef binop 94184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj# undef mkU32 9424afab82eb869f21ccabc3efb5b93f31a5c343956sewardj# undef mkU8 94384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj 94484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj return NULL; 94584ff0657940e62f38e618ea18bac6f27ce0e741fsewardj} 94684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj 94736ca51378f8851635df814230fa23f2c409b9eddsewardj 9480c2cb623cca372a2b42b073121c7413cdaaf75besewardj/*-----------------------------------------------------------*/ 9490c2cb623cca372a2b42b073121c7413cdaaf75besewardj/*--- Utility functions for x87 FPU conversions. ---*/ 9500c2cb623cca372a2b42b073121c7413cdaaf75besewardj/*-----------------------------------------------------------*/ 9510c2cb623cca372a2b42b073121c7413cdaaf75besewardj 9520c2cb623cca372a2b42b073121c7413cdaaf75besewardj 9530c2cb623cca372a2b42b073121c7413cdaaf75besewardj/* 80 and 64-bit floating point formats: 9540c2cb623cca372a2b42b073121c7413cdaaf75besewardj 9550c2cb623cca372a2b42b073121c7413cdaaf75besewardj 80-bit: 9560c2cb623cca372a2b42b073121c7413cdaaf75besewardj 9570c2cb623cca372a2b42b073121c7413cdaaf75besewardj S 0 0-------0 zero 9580c2cb623cca372a2b42b073121c7413cdaaf75besewardj S 0 0X------X denormals 9590c2cb623cca372a2b42b073121c7413cdaaf75besewardj S 1-7FFE 1X------X normals (all normals have leading 1) 9600c2cb623cca372a2b42b073121c7413cdaaf75besewardj S 7FFF 10------0 infinity 9610c2cb623cca372a2b42b073121c7413cdaaf75besewardj S 7FFF 10X-----X snan 9620c2cb623cca372a2b42b073121c7413cdaaf75besewardj S 7FFF 11X-----X qnan 9630c2cb623cca372a2b42b073121c7413cdaaf75besewardj 9640c2cb623cca372a2b42b073121c7413cdaaf75besewardj S is the sign bit. For runs X----X, at least one of the Xs must be 9650c2cb623cca372a2b42b073121c7413cdaaf75besewardj nonzero. Exponent is 15 bits, fractional part is 63 bits, and 9660c2cb623cca372a2b42b073121c7413cdaaf75besewardj there is an explicitly represented leading 1, and a sign bit, 9670c2cb623cca372a2b42b073121c7413cdaaf75besewardj giving 80 in total. 9680c2cb623cca372a2b42b073121c7413cdaaf75besewardj 9690c2cb623cca372a2b42b073121c7413cdaaf75besewardj 64-bit avoids the confusion of an explicitly represented leading 1 9700c2cb623cca372a2b42b073121c7413cdaaf75besewardj and so is simpler: 9710c2cb623cca372a2b42b073121c7413cdaaf75besewardj 9720c2cb623cca372a2b42b073121c7413cdaaf75besewardj S 0 0------0 zero 9730c2cb623cca372a2b42b073121c7413cdaaf75besewardj S 0 X------X denormals 9740c2cb623cca372a2b42b073121c7413cdaaf75besewardj S 1-7FE any normals 9750c2cb623cca372a2b42b073121c7413cdaaf75besewardj S 7FF 0------0 infinity 9760c2cb623cca372a2b42b073121c7413cdaaf75besewardj S 7FF 0X-----X snan 9770c2cb623cca372a2b42b073121c7413cdaaf75besewardj S 7FF 1X-----X qnan 9780c2cb623cca372a2b42b073121c7413cdaaf75besewardj 9790c2cb623cca372a2b42b073121c7413cdaaf75besewardj Exponent is 11 bits, fractional part is 52 bits, and there is a 9800c2cb623cca372a2b42b073121c7413cdaaf75besewardj sign bit, giving 64 in total. 9810c2cb623cca372a2b42b073121c7413cdaaf75besewardj*/ 9820c2cb623cca372a2b42b073121c7413cdaaf75besewardj 983c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardjstatic inline Bool host_is_little_endian ( void ) 984c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj{ 985c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj UInt x = 0x76543210; 986c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj UChar* p = (UChar*)(&x); 987c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj return (*p == 0x10); 988c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj} 989c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj 9909aebb0c3f7a7f43313786826f31402f2b733badfsewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */ 9912a9ad023890d3b34cf45e429df2a8ae88b419128sewardjUInt x86g_calculate_FXAM ( UInt tag, ULong dbl ) 992c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj{ 993c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj Bool mantissaIsZero; 994c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj Int bexp; 995c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj UChar sign; 996c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj UChar* f64; 997c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj 998a0e83b06f304527e3e9aec527c344e35e7023d76sewardj vassert(host_is_little_endian()); 999c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj 1000c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj /* vex_printf("calculate_FXAM ( %d, %llx ) .. ", tag, dbl ); */ 1001c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj 1002c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj f64 = (UChar*)(&dbl); 1003c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj sign = (f64[7] >> 7) & 1; 1004c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj 1005c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj /* First off, if the tag indicates the register was empty, 1006c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj return 1,0,sign,1 */ 1007c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj if (tag == 0) { 1008c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj /* vex_printf("Empty\n"); */ 10092a9ad023890d3b34cf45e429df2a8ae88b419128sewardj return X86G_FC_MASK_C3 | 0 | sign | X86G_FC_MASK_C0; 1010c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj } 1011c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj 1012c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj bexp = (f64[7] << 4) | ((f64[6] >> 4) & 0x0F); 1013c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj bexp &= 0x7FF; 1014c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj 1015c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj mantissaIsZero 1016c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj = (f64[6] & 0x0F) == 0 1017c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj && (f64[5] | f64[4] | f64[3] | f64[2] | f64[1] | f64[0]) == 0; 1018c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj 1019c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj /* If both exponent and mantissa are zero, the value is zero. 1020c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj Return 1,0,sign,0. */ 1021c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj if (bexp == 0 && mantissaIsZero) { 1022c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj /* vex_printf("Zero\n"); */ 10232a9ad023890d3b34cf45e429df2a8ae88b419128sewardj return X86G_FC_MASK_C3 | 0 | sign | 0; 1024c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj } 1025c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj 1026c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj /* If exponent is zero but mantissa isn't, it's a denormal. 1027c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj Return 1,1,sign,0. */ 1028c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj if (bexp == 0 && !mantissaIsZero) { 1029c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj /* vex_printf("Denormal\n"); */ 10302a9ad023890d3b34cf45e429df2a8ae88b419128sewardj return X86G_FC_MASK_C3 | X86G_FC_MASK_C2 | sign | 0; 1031c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj } 1032c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj 1033c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj /* If the exponent is 7FF and the mantissa is zero, this is an infinity. 1034c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj Return 0,1,sign,1. */ 1035c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj if (bexp == 0x7FF && mantissaIsZero) { 1036c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj /* vex_printf("Inf\n"); */ 10372a9ad023890d3b34cf45e429df2a8ae88b419128sewardj return 0 | X86G_FC_MASK_C2 | sign | X86G_FC_MASK_C0; 1038c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj } 1039c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj 1040c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj /* If the exponent is 7FF and the mantissa isn't zero, this is a NaN. 1041c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj Return 0,0,sign,1. */ 1042c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj if (bexp == 0x7FF && !mantissaIsZero) { 1043c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj /* vex_printf("NaN\n"); */ 10442a9ad023890d3b34cf45e429df2a8ae88b419128sewardj return 0 | 0 | sign | X86G_FC_MASK_C0; 1045c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj } 1046c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj 1047c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj /* Uh, ok, we give up. It must be a normal finite number. 1048c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj Return 0,1,sign,0. 1049c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj */ 1050c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj /* vex_printf("normal\n"); */ 10512a9ad023890d3b34cf45e429df2a8ae88b419128sewardj return 0 | X86G_FC_MASK_C2 | sign | 0; 1052c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj} 1053c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj 10540c2cb623cca372a2b42b073121c7413cdaaf75besewardj 105514d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj///////////////////////////////////////////////////////////////// 105614d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj 105714d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardjstatic inline 105814d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardjUInt read_bit_array ( UChar* arr, UInt n ) 105914d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj{ 106014d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj UChar c = arr[n >> 3]; 106114d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj c >>= (n&7); 106214d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj return c & 1; 106314d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj} 106414d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj 106514d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardjstatic inline 106614d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardjvoid write_bit_array ( UChar* arr, UInt n, UInt b ) 106714d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj{ 106814d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj UChar c = arr[n >> 3]; 106914d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj c &= ~(1 << (n&7)); 107014d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj c |= ((b&1) << (n&7)); 107114d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj arr[n >> 3] = c; 107214d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj} 107314d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj 107414d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj 10750c2cb623cca372a2b42b073121c7413cdaaf75besewardj/* Convert a IEEE754 double (64-bit) into an x87 extended double 10760c2cb623cca372a2b42b073121c7413cdaaf75besewardj (80-bit), mimicing the hardware fairly closely. Both numbers are 10770c2cb623cca372a2b42b073121c7413cdaaf75besewardj stored little-endian. Limitations, all of which could be fixed, 10780c2cb623cca372a2b42b073121c7413cdaaf75besewardj given some level of hassle: 10790c2cb623cca372a2b42b073121c7413cdaaf75besewardj 10800c2cb623cca372a2b42b073121c7413cdaaf75besewardj * Identity of NaNs is not preserved. 10810c2cb623cca372a2b42b073121c7413cdaaf75besewardj 10820c2cb623cca372a2b42b073121c7413cdaaf75besewardj See comments in the code for more details. 10830c2cb623cca372a2b42b073121c7413cdaaf75besewardj*/ 10840c2cb623cca372a2b42b073121c7413cdaaf75besewardjstatic void convert_f64le_to_f80le ( /*IN*/UChar* f64, /*OUT*/UChar* f80 ) 10850c2cb623cca372a2b42b073121c7413cdaaf75besewardj{ 108614d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj Bool mantissaIsZero; 108714d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj Int bexp, i, j, shift; 10880c2cb623cca372a2b42b073121c7413cdaaf75besewardj UChar sign; 10890c2cb623cca372a2b42b073121c7413cdaaf75besewardj 10900c2cb623cca372a2b42b073121c7413cdaaf75besewardj sign = (f64[7] >> 7) & 1; 10910c2cb623cca372a2b42b073121c7413cdaaf75besewardj bexp = (f64[7] << 4) | ((f64[6] >> 4) & 0x0F); 10920c2cb623cca372a2b42b073121c7413cdaaf75besewardj bexp &= 0x7FF; 10930c2cb623cca372a2b42b073121c7413cdaaf75besewardj 109414d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj mantissaIsZero = False; 109514d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj if (bexp == 0 || bexp == 0x7FF) { 109614d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj /* We'll need to know whether or not the mantissa (bits 51:0) is 109714d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj all zeroes in order to handle these cases. So figure it 109814d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj out. */ 109914d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj mantissaIsZero 110014d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj = (f64[6] & 0x0F) == 0 110114d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj && f64[5] == 0 && f64[4] == 0 && f64[3] == 0 110214d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj && f64[2] == 0 && f64[1] == 0 && f64[0] == 0; 110314d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj } 110414d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj 11050c2cb623cca372a2b42b073121c7413cdaaf75besewardj /* If the exponent is zero, either we have a zero or a denormal. 11060c2cb623cca372a2b42b073121c7413cdaaf75besewardj Produce a zero. This is a hack in that it forces denormals to 11070c2cb623cca372a2b42b073121c7413cdaaf75besewardj zero. Could do better. */ 11080c2cb623cca372a2b42b073121c7413cdaaf75besewardj if (bexp == 0) { 11090c2cb623cca372a2b42b073121c7413cdaaf75besewardj f80[9] = sign << 7; 11100c2cb623cca372a2b42b073121c7413cdaaf75besewardj f80[8] = f80[7] = f80[6] = f80[5] = f80[4] 11110c2cb623cca372a2b42b073121c7413cdaaf75besewardj = f80[3] = f80[2] = f80[1] = f80[0] = 0; 111214d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj 111314d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj if (mantissaIsZero) 111414d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj /* It really is zero, so that's all we can do. */ 111514d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj return; 111614d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj 111714d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj /* There is at least one 1-bit in the mantissa. So it's a 111814d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj potentially denormalised double -- but we can produce a 111914d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj normalised long double. Count the leading zeroes in the 112014d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj mantissa so as to decide how much to bump the exponent down 112114d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj by. Note, this is SLOW. */ 112214d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj shift = 0; 112314d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj for (i = 51; i >= 0; i--) { 112414d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj if (read_bit_array(f64, i)) 112514d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj break; 112614d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj shift++; 112714d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj } 112814d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj 112914d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj /* and copy into place as many bits as we can get our hands on. */ 113014d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj j = 63; 113114d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj for (i = 51 - shift; i >= 0; i--) { 113214d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj write_bit_array( f80, j, 113314d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj read_bit_array( f64, i ) ); 113414d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj j--; 113514d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj } 113614d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj 113714d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj /* Set the exponent appropriately, and we're done. */ 113814d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj bexp -= shift; 113914d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj bexp += (16383 - 1023); 114014d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj f80[9] = (sign << 7) | ((bexp >> 8) & 0xFF); 114114d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj f80[8] = bexp & 0xFF; 11420c2cb623cca372a2b42b073121c7413cdaaf75besewardj return; 11430c2cb623cca372a2b42b073121c7413cdaaf75besewardj } 114414d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj 11450c2cb623cca372a2b42b073121c7413cdaaf75besewardj /* If the exponent is 7FF, this is either an Infinity, a SNaN or 11460c2cb623cca372a2b42b073121c7413cdaaf75besewardj QNaN, as determined by examining bits 51:0, thus: 11470c2cb623cca372a2b42b073121c7413cdaaf75besewardj 0 ... 0 Inf 11480c2cb623cca372a2b42b073121c7413cdaaf75besewardj 0X ... X SNaN 11490c2cb623cca372a2b42b073121c7413cdaaf75besewardj 1X ... X QNaN 11500c2cb623cca372a2b42b073121c7413cdaaf75besewardj where at least one of the Xs is not zero. 11510c2cb623cca372a2b42b073121c7413cdaaf75besewardj */ 11520c2cb623cca372a2b42b073121c7413cdaaf75besewardj if (bexp == 0x7FF) { 115314d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj if (mantissaIsZero) { 11540c2cb623cca372a2b42b073121c7413cdaaf75besewardj /* Produce an appropriately signed infinity: 11550c2cb623cca372a2b42b073121c7413cdaaf75besewardj S 1--1 (15) 1 0--0 (63) 11560c2cb623cca372a2b42b073121c7413cdaaf75besewardj */ 11570c2cb623cca372a2b42b073121c7413cdaaf75besewardj f80[9] = (sign << 7) | 0x7F; 11580c2cb623cca372a2b42b073121c7413cdaaf75besewardj f80[8] = 0xFF; 11590c2cb623cca372a2b42b073121c7413cdaaf75besewardj f80[7] = 0x80; 11600c2cb623cca372a2b42b073121c7413cdaaf75besewardj f80[6] = f80[5] = f80[4] = f80[3] 11610c2cb623cca372a2b42b073121c7413cdaaf75besewardj = f80[2] = f80[1] = f80[0] = 0; 11620c2cb623cca372a2b42b073121c7413cdaaf75besewardj return; 11630c2cb623cca372a2b42b073121c7413cdaaf75besewardj } 11640c2cb623cca372a2b42b073121c7413cdaaf75besewardj /* So it's either a QNaN or SNaN. Distinguish by considering 11650c2cb623cca372a2b42b073121c7413cdaaf75besewardj bit 51. Note, this destroys all the trailing bits 11660c2cb623cca372a2b42b073121c7413cdaaf75besewardj (identity?) of the NaN. IEEE754 doesn't require preserving 11670c2cb623cca372a2b42b073121c7413cdaaf75besewardj these (it only requires that there be one QNaN value and one 11680c2cb623cca372a2b42b073121c7413cdaaf75besewardj SNaN value), but x87 does seem to have some ability to 11690c2cb623cca372a2b42b073121c7413cdaaf75besewardj preserve them. Anyway, here, the NaN's identity is 11700c2cb623cca372a2b42b073121c7413cdaaf75besewardj destroyed. Could be improved. */ 11710c2cb623cca372a2b42b073121c7413cdaaf75besewardj if (f64[6] & 8) { 11720c2cb623cca372a2b42b073121c7413cdaaf75besewardj /* QNaN. Make a QNaN: 11730c2cb623cca372a2b42b073121c7413cdaaf75besewardj S 1--1 (15) 1 1--1 (63) 11740c2cb623cca372a2b42b073121c7413cdaaf75besewardj */ 11750c2cb623cca372a2b42b073121c7413cdaaf75besewardj f80[9] = (sign << 7) | 0x7F; 11760c2cb623cca372a2b42b073121c7413cdaaf75besewardj f80[8] = 0xFF; 11770c2cb623cca372a2b42b073121c7413cdaaf75besewardj f80[7] = 0xFF; 11780c2cb623cca372a2b42b073121c7413cdaaf75besewardj f80[6] = f80[5] = f80[4] = f80[3] 11790c2cb623cca372a2b42b073121c7413cdaaf75besewardj = f80[2] = f80[1] = f80[0] = 0xFF; 11800c2cb623cca372a2b42b073121c7413cdaaf75besewardj } else { 11810c2cb623cca372a2b42b073121c7413cdaaf75besewardj /* SNaN. Make a SNaN: 11820c2cb623cca372a2b42b073121c7413cdaaf75besewardj S 1--1 (15) 0 1--1 (63) 11830c2cb623cca372a2b42b073121c7413cdaaf75besewardj */ 11840c2cb623cca372a2b42b073121c7413cdaaf75besewardj f80[9] = (sign << 7) | 0x7F; 11850c2cb623cca372a2b42b073121c7413cdaaf75besewardj f80[8] = 0xFF; 11860c2cb623cca372a2b42b073121c7413cdaaf75besewardj f80[7] = 0x7F; 11870c2cb623cca372a2b42b073121c7413cdaaf75besewardj f80[6] = f80[5] = f80[4] = f80[3] 11880c2cb623cca372a2b42b073121c7413cdaaf75besewardj = f80[2] = f80[1] = f80[0] = 0xFF; 11890c2cb623cca372a2b42b073121c7413cdaaf75besewardj } 11900c2cb623cca372a2b42b073121c7413cdaaf75besewardj return; 11910c2cb623cca372a2b42b073121c7413cdaaf75besewardj } 11920c2cb623cca372a2b42b073121c7413cdaaf75besewardj 11930c2cb623cca372a2b42b073121c7413cdaaf75besewardj /* It's not a zero, denormal, infinity or nan. So it must be a 11940c2cb623cca372a2b42b073121c7413cdaaf75besewardj normalised number. Rebias the exponent and build the new 11950c2cb623cca372a2b42b073121c7413cdaaf75besewardj number. */ 11960c2cb623cca372a2b42b073121c7413cdaaf75besewardj bexp += (16383 - 1023); 11970c2cb623cca372a2b42b073121c7413cdaaf75besewardj 11980c2cb623cca372a2b42b073121c7413cdaaf75besewardj f80[9] = (sign << 7) | ((bexp >> 8) & 0xFF); 11990c2cb623cca372a2b42b073121c7413cdaaf75besewardj f80[8] = bexp & 0xFF; 12000c2cb623cca372a2b42b073121c7413cdaaf75besewardj f80[7] = (1 << 7) | ((f64[6] << 3) & 0x78) | ((f64[5] >> 5) & 7); 12010c2cb623cca372a2b42b073121c7413cdaaf75besewardj f80[6] = ((f64[5] << 3) & 0xF8) | ((f64[4] >> 5) & 7); 12020c2cb623cca372a2b42b073121c7413cdaaf75besewardj f80[5] = ((f64[4] << 3) & 0xF8) | ((f64[3] >> 5) & 7); 12030c2cb623cca372a2b42b073121c7413cdaaf75besewardj f80[4] = ((f64[3] << 3) & 0xF8) | ((f64[2] >> 5) & 7); 12040c2cb623cca372a2b42b073121c7413cdaaf75besewardj f80[3] = ((f64[2] << 3) & 0xF8) | ((f64[1] >> 5) & 7); 12050c2cb623cca372a2b42b073121c7413cdaaf75besewardj f80[2] = ((f64[1] << 3) & 0xF8) | ((f64[0] >> 5) & 7); 12060c2cb623cca372a2b42b073121c7413cdaaf75besewardj f80[1] = ((f64[0] << 3) & 0xF8); 12070c2cb623cca372a2b42b073121c7413cdaaf75besewardj f80[0] = 0; 12080c2cb623cca372a2b42b073121c7413cdaaf75besewardj} 12090c2cb623cca372a2b42b073121c7413cdaaf75besewardj 12100c2cb623cca372a2b42b073121c7413cdaaf75besewardj 12110c2cb623cca372a2b42b073121c7413cdaaf75besewardj///////////////////////////////////////////////////////////////// 12120c2cb623cca372a2b42b073121c7413cdaaf75besewardj 12130c2cb623cca372a2b42b073121c7413cdaaf75besewardj/* Convert a x87 extended double (80-bit) into an IEEE 754 double 121414d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj (64-bit), mimicking the hardware fairly closely. Both numbers are 121514d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj stored little-endian. Limitations, both of which could be fixed, 12160c2cb623cca372a2b42b073121c7413cdaaf75besewardj given some level of hassle: 12170c2cb623cca372a2b42b073121c7413cdaaf75besewardj 12180c2cb623cca372a2b42b073121c7413cdaaf75besewardj * Rounding following truncation could be a bit better. 12190c2cb623cca372a2b42b073121c7413cdaaf75besewardj 12200c2cb623cca372a2b42b073121c7413cdaaf75besewardj * Identity of NaNs is not preserved. 12210c2cb623cca372a2b42b073121c7413cdaaf75besewardj 122214d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj See comments in the code for more details. 12230c2cb623cca372a2b42b073121c7413cdaaf75besewardj*/ 12240c2cb623cca372a2b42b073121c7413cdaaf75besewardjstatic void convert_f80le_to_f64le ( /*IN*/UChar* f80, /*OUT*/UChar* f64 ) 12250c2cb623cca372a2b42b073121c7413cdaaf75besewardj{ 12260c2cb623cca372a2b42b073121c7413cdaaf75besewardj Bool isInf; 122714d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj Int bexp, i, j; 12280c2cb623cca372a2b42b073121c7413cdaaf75besewardj UChar sign; 12290c2cb623cca372a2b42b073121c7413cdaaf75besewardj 12300c2cb623cca372a2b42b073121c7413cdaaf75besewardj sign = (f80[9] >> 7) & 1; 12310c2cb623cca372a2b42b073121c7413cdaaf75besewardj bexp = (((UInt)f80[9]) << 8) | (UInt)f80[8]; 12320c2cb623cca372a2b42b073121c7413cdaaf75besewardj bexp &= 0x7FFF; 12330c2cb623cca372a2b42b073121c7413cdaaf75besewardj 12340c2cb623cca372a2b42b073121c7413cdaaf75besewardj /* If the exponent is zero, either we have a zero or a denormal. 12350c2cb623cca372a2b42b073121c7413cdaaf75besewardj But an extended precision denormal becomes a double precision 12360c2cb623cca372a2b42b073121c7413cdaaf75besewardj zero, so in either case, just produce the appropriately signed 12370c2cb623cca372a2b42b073121c7413cdaaf75besewardj zero. */ 12380c2cb623cca372a2b42b073121c7413cdaaf75besewardj if (bexp == 0) { 12390c2cb623cca372a2b42b073121c7413cdaaf75besewardj f64[7] = sign << 7; 12400c2cb623cca372a2b42b073121c7413cdaaf75besewardj f64[6] = f64[5] = f64[4] = f64[3] = f64[2] = f64[1] = f64[0] = 0; 12410c2cb623cca372a2b42b073121c7413cdaaf75besewardj return; 12420c2cb623cca372a2b42b073121c7413cdaaf75besewardj } 12430c2cb623cca372a2b42b073121c7413cdaaf75besewardj 12440c2cb623cca372a2b42b073121c7413cdaaf75besewardj /* If the exponent is 7FFF, this is either an Infinity, a SNaN or 12450c2cb623cca372a2b42b073121c7413cdaaf75besewardj QNaN, as determined by examining bits 62:0, thus: 12460c2cb623cca372a2b42b073121c7413cdaaf75besewardj 0 ... 0 Inf 12470c2cb623cca372a2b42b073121c7413cdaaf75besewardj 0X ... X SNaN 12480c2cb623cca372a2b42b073121c7413cdaaf75besewardj 1X ... X QNaN 12490c2cb623cca372a2b42b073121c7413cdaaf75besewardj where at least one of the Xs is not zero. 12500c2cb623cca372a2b42b073121c7413cdaaf75besewardj */ 12510c2cb623cca372a2b42b073121c7413cdaaf75besewardj if (bexp == 0x7FFF) { 12520c2cb623cca372a2b42b073121c7413cdaaf75besewardj isInf = (f80[7] & 0x7F) == 0 12530c2cb623cca372a2b42b073121c7413cdaaf75besewardj && f80[6] == 0 && f80[5] == 0 && f80[4] == 0 12540c2cb623cca372a2b42b073121c7413cdaaf75besewardj && f80[3] == 0 && f80[2] == 0 && f80[1] == 0 && f80[0] == 0; 12550c2cb623cca372a2b42b073121c7413cdaaf75besewardj if (isInf) { 12560c2cb623cca372a2b42b073121c7413cdaaf75besewardj if (0 == (f80[7] & 0x80)) 12570c2cb623cca372a2b42b073121c7413cdaaf75besewardj goto wierd_NaN; 12580c2cb623cca372a2b42b073121c7413cdaaf75besewardj /* Produce an appropriately signed infinity: 12590c2cb623cca372a2b42b073121c7413cdaaf75besewardj S 1--1 (11) 0--0 (52) 12600c2cb623cca372a2b42b073121c7413cdaaf75besewardj */ 12610c2cb623cca372a2b42b073121c7413cdaaf75besewardj f64[7] = (sign << 7) | 0x7F; 12620c2cb623cca372a2b42b073121c7413cdaaf75besewardj f64[6] = 0xF0; 12630c2cb623cca372a2b42b073121c7413cdaaf75besewardj f64[5] = f64[4] = f64[3] = f64[2] = f64[1] = f64[0] = 0; 12640c2cb623cca372a2b42b073121c7413cdaaf75besewardj return; 12650c2cb623cca372a2b42b073121c7413cdaaf75besewardj } 12660c2cb623cca372a2b42b073121c7413cdaaf75besewardj /* So it's either a QNaN or SNaN. Distinguish by considering 12670c2cb623cca372a2b42b073121c7413cdaaf75besewardj bit 62. Note, this destroys all the trailing bits 12680c2cb623cca372a2b42b073121c7413cdaaf75besewardj (identity?) of the NaN. IEEE754 doesn't require preserving 12690c2cb623cca372a2b42b073121c7413cdaaf75besewardj these (it only requires that there be one QNaN value and one 12700c2cb623cca372a2b42b073121c7413cdaaf75besewardj SNaN value), but x87 does seem to have some ability to 12710c2cb623cca372a2b42b073121c7413cdaaf75besewardj preserve them. Anyway, here, the NaN's identity is 12720c2cb623cca372a2b42b073121c7413cdaaf75besewardj destroyed. Could be improved. */ 12730c2cb623cca372a2b42b073121c7413cdaaf75besewardj if (f80[8] & 0x40) { 12740c2cb623cca372a2b42b073121c7413cdaaf75besewardj /* QNaN. Make a QNaN: 12750c2cb623cca372a2b42b073121c7413cdaaf75besewardj S 1--1 (11) 1 1--1 (51) 12760c2cb623cca372a2b42b073121c7413cdaaf75besewardj */ 12770c2cb623cca372a2b42b073121c7413cdaaf75besewardj f64[7] = (sign << 7) | 0x7F; 12780c2cb623cca372a2b42b073121c7413cdaaf75besewardj f64[6] = 0xFF; 12790c2cb623cca372a2b42b073121c7413cdaaf75besewardj f64[5] = f64[4] = f64[3] = f64[2] = f64[1] = f64[0] = 0xFF; 12800c2cb623cca372a2b42b073121c7413cdaaf75besewardj } else { 12810c2cb623cca372a2b42b073121c7413cdaaf75besewardj /* SNaN. Make a SNaN: 12820c2cb623cca372a2b42b073121c7413cdaaf75besewardj S 1--1 (11) 0 1--1 (51) 12830c2cb623cca372a2b42b073121c7413cdaaf75besewardj */ 12840c2cb623cca372a2b42b073121c7413cdaaf75besewardj f64[7] = (sign << 7) | 0x7F; 12850c2cb623cca372a2b42b073121c7413cdaaf75besewardj f64[6] = 0xF7; 12860c2cb623cca372a2b42b073121c7413cdaaf75besewardj f64[5] = f64[4] = f64[3] = f64[2] = f64[1] = f64[0] = 0xFF; 12870c2cb623cca372a2b42b073121c7413cdaaf75besewardj } 12880c2cb623cca372a2b42b073121c7413cdaaf75besewardj return; 12890c2cb623cca372a2b42b073121c7413cdaaf75besewardj } 12900c2cb623cca372a2b42b073121c7413cdaaf75besewardj 12910c2cb623cca372a2b42b073121c7413cdaaf75besewardj /* If it's not a Zero, NaN or Inf, and the integer part (bit 62) is 12920c2cb623cca372a2b42b073121c7413cdaaf75besewardj zero, the x87 FPU appears to consider the number denormalised 12930c2cb623cca372a2b42b073121c7413cdaaf75besewardj and converts it to a QNaN. */ 12940c2cb623cca372a2b42b073121c7413cdaaf75besewardj if (0 == (f80[7] & 0x80)) { 12950c2cb623cca372a2b42b073121c7413cdaaf75besewardj wierd_NaN: 12960c2cb623cca372a2b42b073121c7413cdaaf75besewardj /* Strange hardware QNaN: 12970c2cb623cca372a2b42b073121c7413cdaaf75besewardj S 1--1 (11) 1 0--0 (51) 12980c2cb623cca372a2b42b073121c7413cdaaf75besewardj */ 12990c2cb623cca372a2b42b073121c7413cdaaf75besewardj /* On a PIII, these QNaNs always appear with sign==1. I have 13000c2cb623cca372a2b42b073121c7413cdaaf75besewardj no idea why. */ 13010c2cb623cca372a2b42b073121c7413cdaaf75besewardj f64[7] = (1 /*sign*/ << 7) | 0x7F; 13020c2cb623cca372a2b42b073121c7413cdaaf75besewardj f64[6] = 0xF8; 13030c2cb623cca372a2b42b073121c7413cdaaf75besewardj f64[5] = f64[4] = f64[3] = f64[2] = f64[1] = f64[0] = 0; 13040c2cb623cca372a2b42b073121c7413cdaaf75besewardj return; 13050c2cb623cca372a2b42b073121c7413cdaaf75besewardj } 13060c2cb623cca372a2b42b073121c7413cdaaf75besewardj 13070c2cb623cca372a2b42b073121c7413cdaaf75besewardj /* It's not a zero, denormal, infinity or nan. So it must be a 13080c2cb623cca372a2b42b073121c7413cdaaf75besewardj normalised number. Rebias the exponent and consider. */ 13090c2cb623cca372a2b42b073121c7413cdaaf75besewardj bexp -= (16383 - 1023); 13100c2cb623cca372a2b42b073121c7413cdaaf75besewardj if (bexp >= 0x7FF) { 13110c2cb623cca372a2b42b073121c7413cdaaf75besewardj /* It's too big for a double. Construct an infinity. */ 13120c2cb623cca372a2b42b073121c7413cdaaf75besewardj f64[7] = (sign << 7) | 0x7F; 13130c2cb623cca372a2b42b073121c7413cdaaf75besewardj f64[6] = 0xF0; 13140c2cb623cca372a2b42b073121c7413cdaaf75besewardj f64[5] = f64[4] = f64[3] = f64[2] = f64[1] = f64[0] = 0; 13150c2cb623cca372a2b42b073121c7413cdaaf75besewardj return; 13160c2cb623cca372a2b42b073121c7413cdaaf75besewardj } 13170c2cb623cca372a2b42b073121c7413cdaaf75besewardj 131814d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj if (bexp <= 0) { 131914d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj /* It's too small for a normalised double. First construct a 132014d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj zero and then see if it can be improved into a denormal. */ 13210c2cb623cca372a2b42b073121c7413cdaaf75besewardj f64[7] = sign << 7; 13220c2cb623cca372a2b42b073121c7413cdaaf75besewardj f64[6] = f64[5] = f64[4] = f64[3] = f64[2] = f64[1] = f64[0] = 0; 132314d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj 132414d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj if (bexp < -52) 132514d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj /* Too small even for a denormal. */ 132614d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj return; 132714d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj 132814d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj /* Ok, let's make a denormal. Note, this is SLOW. */ 132914d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj /* Copy bits 63, 62, 61, etc of the src mantissa into the dst, 133014d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj indexes 52+bexp, 51+bexp, etc, until k+bexp < 0. */ 133114d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj /* bexp is in range -52 .. 0 inclusive */ 133214d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj for (i = 63; i >= 0; i--) { 133314d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj j = i - 12 + bexp; 133414d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj if (j < 0) break; 133514d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj /* We shouldn't really call vassert from generated code. */ 133614d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj vassert(j >= 0 && j < 52); 133714d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj write_bit_array ( f64, 133814d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj j, 133914d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj read_bit_array ( f80, i ) ); 134014d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj } 134114d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj /* and now we might have to round ... */ 134214d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj if (read_bit_array(f80, 10+1 - bexp) == 1) 134314d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj goto do_rounding; 134414d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj 13450c2cb623cca372a2b42b073121c7413cdaaf75besewardj return; 13460c2cb623cca372a2b42b073121c7413cdaaf75besewardj } 13470c2cb623cca372a2b42b073121c7413cdaaf75besewardj 13480c2cb623cca372a2b42b073121c7413cdaaf75besewardj /* Ok, it's a normalised number which is representable as a double. 13490c2cb623cca372a2b42b073121c7413cdaaf75besewardj Copy the exponent and mantissa into place. */ 13500c2cb623cca372a2b42b073121c7413cdaaf75besewardj /* 13510c2cb623cca372a2b42b073121c7413cdaaf75besewardj for (i = 0; i < 52; i++) 13520c2cb623cca372a2b42b073121c7413cdaaf75besewardj write_bit_array ( f64, 13530c2cb623cca372a2b42b073121c7413cdaaf75besewardj i, 13540c2cb623cca372a2b42b073121c7413cdaaf75besewardj read_bit_array ( f80, i+11 ) ); 13550c2cb623cca372a2b42b073121c7413cdaaf75besewardj */ 13560c2cb623cca372a2b42b073121c7413cdaaf75besewardj f64[0] = (f80[1] >> 3) | (f80[2] << 5); 13570c2cb623cca372a2b42b073121c7413cdaaf75besewardj f64[1] = (f80[2] >> 3) | (f80[3] << 5); 13580c2cb623cca372a2b42b073121c7413cdaaf75besewardj f64[2] = (f80[3] >> 3) | (f80[4] << 5); 13590c2cb623cca372a2b42b073121c7413cdaaf75besewardj f64[3] = (f80[4] >> 3) | (f80[5] << 5); 13600c2cb623cca372a2b42b073121c7413cdaaf75besewardj f64[4] = (f80[5] >> 3) | (f80[6] << 5); 13610c2cb623cca372a2b42b073121c7413cdaaf75besewardj f64[5] = (f80[6] >> 3) | (f80[7] << 5); 13620c2cb623cca372a2b42b073121c7413cdaaf75besewardj 13630c2cb623cca372a2b42b073121c7413cdaaf75besewardj f64[6] = ((bexp << 4) & 0xF0) | ((f80[7] >> 3) & 0x0F); 13640c2cb623cca372a2b42b073121c7413cdaaf75besewardj 13650c2cb623cca372a2b42b073121c7413cdaaf75besewardj f64[7] = (sign << 7) | ((bexp >> 4) & 0x7F); 13660c2cb623cca372a2b42b073121c7413cdaaf75besewardj 13670c2cb623cca372a2b42b073121c7413cdaaf75besewardj /* Now consider any rounding that needs to happen as a result of 13680c2cb623cca372a2b42b073121c7413cdaaf75besewardj truncating the mantissa. */ 13690c2cb623cca372a2b42b073121c7413cdaaf75besewardj if (f80[1] & 4) /* read_bit_array(f80, 10) == 1) */ { 137014d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj 137114d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj /* If the bottom bits of f80 are "100 0000 0000", then the 137214d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj infinitely precise value is deemed to be mid-way between the 137314d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj two closest representable values. Since we're doing 137414d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj round-to-nearest (the default mode), in that case it is the 137514d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj bit immediately above which indicates whether we should round 137614d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj upwards or not -- if 0, we don't. All that is encapsulated 137714d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj in the following simple test. */ 137814d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj if ((f80[1] & 0xF) == 4/*0100b*/ && f80[0] == 0) 137914d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj return; 138014d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj 138114d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj do_rounding: 138214d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj /* Round upwards. This is a kludge. Once in every 2^24 138314d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj roundings (statistically) the bottom three bytes are all 0xFF 13840c2cb623cca372a2b42b073121c7413cdaaf75besewardj and so we don't round at all. Could be improved. */ 13850c2cb623cca372a2b42b073121c7413cdaaf75besewardj if (f64[0] != 0xFF) { 13860c2cb623cca372a2b42b073121c7413cdaaf75besewardj f64[0]++; 13870c2cb623cca372a2b42b073121c7413cdaaf75besewardj } 13880c2cb623cca372a2b42b073121c7413cdaaf75besewardj else 13890c2cb623cca372a2b42b073121c7413cdaaf75besewardj if (f64[0] == 0xFF && f64[1] != 0xFF) { 13900c2cb623cca372a2b42b073121c7413cdaaf75besewardj f64[0] = 0; 13910c2cb623cca372a2b42b073121c7413cdaaf75besewardj f64[1]++; 13920c2cb623cca372a2b42b073121c7413cdaaf75besewardj } 139314d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj else 139414d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj if (f64[0] == 0xFF && f64[1] == 0xFF && f64[2] != 0xFF) { 139514d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj f64[0] = 0; 139614d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj f64[1] = 0; 139714d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj f64[2]++; 139814d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj } 13990c2cb623cca372a2b42b073121c7413cdaaf75besewardj /* else we don't round, but we should. */ 14000c2cb623cca372a2b42b073121c7413cdaaf75besewardj } 14010c2cb623cca372a2b42b073121c7413cdaaf75besewardj} 14020c2cb623cca372a2b42b073121c7413cdaaf75besewardj 140314d3ddff72f8d257b351c92c24c9f403ed6d67a3sewardj 140417442fe8094d0f82266e5a05509f62cac8f7539esewardj/* CALLED FROM GENERATED CODE */ 140517442fe8094d0f82266e5a05509f62cac8f7539esewardj/* DIRTY HELPER (reads guest memory) */ 14062a9ad023890d3b34cf45e429df2a8ae88b419128sewardjULong x86g_loadF80le ( UInt addrU ) 140717442fe8094d0f82266e5a05509f62cac8f7539esewardj{ 140817442fe8094d0f82266e5a05509f62cac8f7539esewardj ULong f64; 140917442fe8094d0f82266e5a05509f62cac8f7539esewardj convert_f80le_to_f64le ( (UChar*)addrU, (UChar*)&f64 ); 141017442fe8094d0f82266e5a05509f62cac8f7539esewardj return f64; 141117442fe8094d0f82266e5a05509f62cac8f7539esewardj} 141217442fe8094d0f82266e5a05509f62cac8f7539esewardj 141317442fe8094d0f82266e5a05509f62cac8f7539esewardj/* CALLED FROM GENERATED CODE */ 141417442fe8094d0f82266e5a05509f62cac8f7539esewardj/* DIRTY HELPER (writes guest memory) */ 14152a9ad023890d3b34cf45e429df2a8ae88b419128sewardjvoid x86g_storeF80le ( UInt addrU, ULong f64 ) 141617442fe8094d0f82266e5a05509f62cac8f7539esewardj{ 141717442fe8094d0f82266e5a05509f62cac8f7539esewardj convert_f64le_to_f80le( (UChar*)&f64, (UChar*)addrU ); 141817442fe8094d0f82266e5a05509f62cac8f7539esewardj} 141917442fe8094d0f82266e5a05509f62cac8f7539esewardj 14200c2cb623cca372a2b42b073121c7413cdaaf75besewardj 14210c2cb623cca372a2b42b073121c7413cdaaf75besewardj/*----------------------------------------------*/ 14220c2cb623cca372a2b42b073121c7413cdaaf75besewardj/*--- The exported fns .. ---*/ 14230c2cb623cca372a2b42b073121c7413cdaaf75besewardj/*----------------------------------------------*/ 14240c2cb623cca372a2b42b073121c7413cdaaf75besewardj 14250c2cb623cca372a2b42b073121c7413cdaaf75besewardj/* Layout of the real x87 state. */ 14260c2cb623cca372a2b42b073121c7413cdaaf75besewardj 14270c2cb623cca372a2b42b073121c7413cdaaf75besewardjtypedef 14280c2cb623cca372a2b42b073121c7413cdaaf75besewardj struct { 14290c2cb623cca372a2b42b073121c7413cdaaf75besewardj UShort env[14]; 14300c2cb623cca372a2b42b073121c7413cdaaf75besewardj UChar reg[80]; 14310c2cb623cca372a2b42b073121c7413cdaaf75besewardj } 14320c2cb623cca372a2b42b073121c7413cdaaf75besewardj Fpu_State; 14330c2cb623cca372a2b42b073121c7413cdaaf75besewardj 14340c2cb623cca372a2b42b073121c7413cdaaf75besewardj/* Offsets, in 16-bit ints, into the FPU environment (env) area. */ 14350c2cb623cca372a2b42b073121c7413cdaaf75besewardj#define FP_ENV_CTRL 0 14360c2cb623cca372a2b42b073121c7413cdaaf75besewardj#define FP_ENV_STAT 2 14370c2cb623cca372a2b42b073121c7413cdaaf75besewardj#define FP_ENV_TAG 4 14380c2cb623cca372a2b42b073121c7413cdaaf75besewardj#define FP_ENV_IP 6 /* and 7 */ 14390c2cb623cca372a2b42b073121c7413cdaaf75besewardj#define FP_ENV_CS 8 14400c2cb623cca372a2b42b073121c7413cdaaf75besewardj#define FP_ENV_OPOFF 10 /* and 11 */ 14410c2cb623cca372a2b42b073121c7413cdaaf75besewardj#define FP_ENV_OPSEL 12 14420c2cb623cca372a2b42b073121c7413cdaaf75besewardj#define FP_REG(ii) (10*(7-(ii))) 14430c2cb623cca372a2b42b073121c7413cdaaf75besewardj 14440c2cb623cca372a2b42b073121c7413cdaaf75besewardj 14457df596b1e36840e2d74c90aa55589934add61ccfsewardj/* CLEAN HELPER */ 1446a0e83b06f304527e3e9aec527c344e35e7023d76sewardj/* fpucw[15:0] contains a x87 native format FPU control word. 1447d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj Extract from it the required FPROUND value and any resulting 1448d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj emulation warning, and return (warn << 32) | fpround value. 1449d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj*/ 14503bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardjULong x86g_check_fldcw ( UInt fpucw ) 1451893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj{ 1452d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj /* Decide on a rounding mode. fpucw[11:10] holds it. */ 1453d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj /* NOTE, encoded exactly as per enum IRRoundingMode. */ 1454893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj UInt rmode = (fpucw >> 10) & 3; 1455893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj 1456893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj /* Detect any required emulation warnings. */ 1457893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj VexEmWarn ew = EmWarn_NONE; 1458893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj 1459893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj if ((fpucw & 0x3F) != 0x3F) { 1460893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj /* unmasked exceptions! */ 1461893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj ew = EmWarn_X86_x87exns; 1462893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj } 1463893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj else 1464893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj if (((fpucw >> 8) & 3) != 3) { 1465893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj /* unsupported precision */ 1466893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj ew = EmWarn_X86_x87precision; 1467893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj } 1468893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj 1469d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj return (((ULong)ew) << 32) | ((ULong)rmode); 1470893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj} 1471893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj 1472893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj/* CLEAN HELPER */ 14737df596b1e36840e2d74c90aa55589934add61ccfsewardj/* Given fpround as an IRRoundingMode value, create a suitable x87 14747df596b1e36840e2d74c90aa55589934add61ccfsewardj native format FPU control word. */ 14753bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardjUInt x86g_create_fpucw ( UInt fpround ) 1476893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj{ 1477d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj fpround &= 3; 1478d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj return 0x037F | (fpround << 10); 1479893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj} 1480893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj 1481893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj 14827df596b1e36840e2d74c90aa55589934add61ccfsewardj/* CLEAN HELPER */ 1483a0e83b06f304527e3e9aec527c344e35e7023d76sewardj/* mxcsr[15:0] contains a SSE native format MXCSR value. 14847df596b1e36840e2d74c90aa55589934add61ccfsewardj Extract from it the required SSEROUND value and any resulting 14857df596b1e36840e2d74c90aa55589934add61ccfsewardj emulation warning, and return (warn << 32) | sseround value. 14867df596b1e36840e2d74c90aa55589934add61ccfsewardj*/ 14873bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardjULong x86g_check_ldmxcsr ( UInt mxcsr ) 14887df596b1e36840e2d74c90aa55589934add61ccfsewardj{ 14897df596b1e36840e2d74c90aa55589934add61ccfsewardj /* Decide on a rounding mode. mxcsr[14:13] holds it. */ 14907df596b1e36840e2d74c90aa55589934add61ccfsewardj /* NOTE, encoded exactly as per enum IRRoundingMode. */ 14917df596b1e36840e2d74c90aa55589934add61ccfsewardj UInt rmode = (mxcsr >> 13) & 3; 14927df596b1e36840e2d74c90aa55589934add61ccfsewardj 14937df596b1e36840e2d74c90aa55589934add61ccfsewardj /* Detect any required emulation warnings. */ 14947df596b1e36840e2d74c90aa55589934add61ccfsewardj VexEmWarn ew = EmWarn_NONE; 14957df596b1e36840e2d74c90aa55589934add61ccfsewardj 14967df596b1e36840e2d74c90aa55589934add61ccfsewardj if ((mxcsr & 0x1F80) != 0x1F80) { 14977df596b1e36840e2d74c90aa55589934add61ccfsewardj /* unmasked exceptions! */ 14987df596b1e36840e2d74c90aa55589934add61ccfsewardj ew = EmWarn_X86_sseExns; 14997df596b1e36840e2d74c90aa55589934add61ccfsewardj } 15007df596b1e36840e2d74c90aa55589934add61ccfsewardj else 15015edfc26d72ca8ebea2aa0443a1ed4dd218343d04sewardj if (mxcsr & (1<<15)) { 15025edfc26d72ca8ebea2aa0443a1ed4dd218343d04sewardj /* FZ is set */ 15035edfc26d72ca8ebea2aa0443a1ed4dd218343d04sewardj ew = EmWarn_X86_fz; 15045edfc26d72ca8ebea2aa0443a1ed4dd218343d04sewardj } 15055edfc26d72ca8ebea2aa0443a1ed4dd218343d04sewardj else 15065edfc26d72ca8ebea2aa0443a1ed4dd218343d04sewardj if (mxcsr & (1<<6)) { 15075edfc26d72ca8ebea2aa0443a1ed4dd218343d04sewardj /* DAZ is set */ 15085edfc26d72ca8ebea2aa0443a1ed4dd218343d04sewardj ew = EmWarn_X86_daz; 15097df596b1e36840e2d74c90aa55589934add61ccfsewardj } 15107df596b1e36840e2d74c90aa55589934add61ccfsewardj 15117df596b1e36840e2d74c90aa55589934add61ccfsewardj return (((ULong)ew) << 32) | ((ULong)rmode); 15127df596b1e36840e2d74c90aa55589934add61ccfsewardj} 15137df596b1e36840e2d74c90aa55589934add61ccfsewardj 15147df596b1e36840e2d74c90aa55589934add61ccfsewardj 15157df596b1e36840e2d74c90aa55589934add61ccfsewardj/* CLEAN HELPER */ 15167df596b1e36840e2d74c90aa55589934add61ccfsewardj/* Given sseround as an IRRoundingMode value, create a suitable SSE 15177df596b1e36840e2d74c90aa55589934add61ccfsewardj native format MXCSR value. */ 15183bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardjUInt x86g_create_mxcsr ( UInt sseround ) 15197df596b1e36840e2d74c90aa55589934add61ccfsewardj{ 15207df596b1e36840e2d74c90aa55589934add61ccfsewardj sseround &= 3; 15217df596b1e36840e2d74c90aa55589934add61ccfsewardj return 0x1F80 | (sseround << 13); 15227df596b1e36840e2d74c90aa55589934add61ccfsewardj} 15237df596b1e36840e2d74c90aa55589934add61ccfsewardj 15247df596b1e36840e2d74c90aa55589934add61ccfsewardj 1525a0e83b06f304527e3e9aec527c344e35e7023d76sewardj/* CALLED FROM GENERATED CODE */ 1526a0e83b06f304527e3e9aec527c344e35e7023d76sewardj/* DIRTY HELPER (writes guest state) */ 1527a0e83b06f304527e3e9aec527c344e35e7023d76sewardj/* Initialise the x87 FPU state as per 'finit'. */ 1528a0e83b06f304527e3e9aec527c344e35e7023d76sewardjvoid x86g_dirtyhelper_FINIT ( VexGuestX86State* gst ) 1529a0e83b06f304527e3e9aec527c344e35e7023d76sewardj{ 1530a0e83b06f304527e3e9aec527c344e35e7023d76sewardj Int i; 1531a0e83b06f304527e3e9aec527c344e35e7023d76sewardj gst->guest_FTOP = 0; 1532a0e83b06f304527e3e9aec527c344e35e7023d76sewardj for (i = 0; i < 8; i++) { 1533a0e83b06f304527e3e9aec527c344e35e7023d76sewardj gst->guest_FPTAG[i] = 0; /* empty */ 1534a0e83b06f304527e3e9aec527c344e35e7023d76sewardj gst->guest_FPREG[i] = 0; /* IEEE754 64-bit zero */ 1535a0e83b06f304527e3e9aec527c344e35e7023d76sewardj } 1536a0e83b06f304527e3e9aec527c344e35e7023d76sewardj gst->guest_FPROUND = (UInt)Irrm_NEAREST; 1537a0e83b06f304527e3e9aec527c344e35e7023d76sewardj gst->guest_FC3210 = 0; 1538a0e83b06f304527e3e9aec527c344e35e7023d76sewardj} 1539a0e83b06f304527e3e9aec527c344e35e7023d76sewardj 1540a0e83b06f304527e3e9aec527c344e35e7023d76sewardj 15417df596b1e36840e2d74c90aa55589934add61ccfsewardj/* This is used to implement both 'frstor' and 'fldenv'. The latter 15427df596b1e36840e2d74c90aa55589934add61ccfsewardj appears to differ from the former only in that the 8 FP registers 15437df596b1e36840e2d74c90aa55589934add61ccfsewardj themselves are not transferred into the guest state. */ 15447df596b1e36840e2d74c90aa55589934add61ccfsewardjstatic 154538a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjVexEmWarn do_put_x87 ( Bool moveRegs, 154638a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj /*IN*/UChar* x87_state, 154738a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj /*OUT*/VexGuestX86State* vex_state ) 15480c2cb623cca372a2b42b073121c7413cdaaf75besewardj{ 1549a0e83b06f304527e3e9aec527c344e35e7023d76sewardj Int stno, preg; 15500c2cb623cca372a2b42b073121c7413cdaaf75besewardj UInt tag; 1551f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj Double* vexRegs = (Double*)(&vex_state->guest_FPREG[0]); 1552f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj UChar* vexTags = (UChar*)(&vex_state->guest_FPTAG[0]); 15530c2cb623cca372a2b42b073121c7413cdaaf75besewardj Fpu_State* x87 = (Fpu_State*)x87_state; 15540c2cb623cca372a2b42b073121c7413cdaaf75besewardj UInt ftop = (x87->env[FP_ENV_STAT] >> 11) & 7; 15550c2cb623cca372a2b42b073121c7413cdaaf75besewardj UInt tagw = x87->env[FP_ENV_TAG]; 15566e0dbda4f7ea53dd29996d4d429d3c5c92ee3640sewardj UInt fpucw = x87->env[FP_ENV_CTRL]; 1557c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj UInt c3210 = x87->env[FP_ENV_STAT] & 0x4700; 1558893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj VexEmWarn ew; 1559d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj UInt fpround; 1560893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj ULong pair; 15610c2cb623cca372a2b42b073121c7413cdaaf75besewardj 15620c2cb623cca372a2b42b073121c7413cdaaf75besewardj /* Copy registers and tags */ 1563a0e83b06f304527e3e9aec527c344e35e7023d76sewardj for (stno = 0; stno < 8; stno++) { 1564a0e83b06f304527e3e9aec527c344e35e7023d76sewardj preg = (stno + ftop) & 7; 1565a0e83b06f304527e3e9aec527c344e35e7023d76sewardj tag = (tagw >> (2*preg)) & 3; 15660c2cb623cca372a2b42b073121c7413cdaaf75besewardj if (tag == 3) { 15670c2cb623cca372a2b42b073121c7413cdaaf75besewardj /* register is empty */ 1568a0e83b06f304527e3e9aec527c344e35e7023d76sewardj /* hmm, if it's empty, does it still get written? Probably 1569a0e83b06f304527e3e9aec527c344e35e7023d76sewardj safer to say it does. If we don't, memcheck could get out 1570a0e83b06f304527e3e9aec527c344e35e7023d76sewardj of sync, in that it thinks all FP registers are defined by 1571a0e83b06f304527e3e9aec527c344e35e7023d76sewardj this helper, but in reality some have not been updated. */ 1572a0e83b06f304527e3e9aec527c344e35e7023d76sewardj if (True || moveRegs) 1573a0e83b06f304527e3e9aec527c344e35e7023d76sewardj vexRegs[preg] = 0.0; 1574a0e83b06f304527e3e9aec527c344e35e7023d76sewardj vexTags[preg] = 0; 15750c2cb623cca372a2b42b073121c7413cdaaf75besewardj } else { 15760c2cb623cca372a2b42b073121c7413cdaaf75besewardj /* register is non-empty */ 15777df596b1e36840e2d74c90aa55589934add61ccfsewardj if (moveRegs) 1578a0e83b06f304527e3e9aec527c344e35e7023d76sewardj convert_f80le_to_f64le( &x87->reg[10*stno], 1579a0e83b06f304527e3e9aec527c344e35e7023d76sewardj (UChar*)&vexRegs[preg] ); 1580a0e83b06f304527e3e9aec527c344e35e7023d76sewardj vexTags[preg] = 1; 15810c2cb623cca372a2b42b073121c7413cdaaf75besewardj } 15820c2cb623cca372a2b42b073121c7413cdaaf75besewardj } 15830c2cb623cca372a2b42b073121c7413cdaaf75besewardj 15840c2cb623cca372a2b42b073121c7413cdaaf75besewardj /* stack pointer */ 1585f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj vex_state->guest_FTOP = ftop; 15860c2cb623cca372a2b42b073121c7413cdaaf75besewardj 15873f868e5262a8d2488f41cc49058ba60c24843c3esewardj /* status word */ 1588f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj vex_state->guest_FC3210 = c3210; 1589893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj 1590d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj /* handle the control word, setting FPROUND and detecting any 1591893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj emulation warnings. */ 15923bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj pair = x86g_check_fldcw ( (UInt)fpucw ); 1593d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj fpround = (UInt)pair; 1594d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj ew = (VexEmWarn)(pair >> 32); 1595893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj 1596d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj vex_state->guest_FPROUND = fpround & 3; 1597893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj 1598893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj /* emulation warnings --> caller */ 1599893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj return ew; 16000c2cb623cca372a2b42b073121c7413cdaaf75besewardj} 16010c2cb623cca372a2b42b073121c7413cdaaf75besewardj 16026e0dbda4f7ea53dd29996d4d429d3c5c92ee3640sewardj 1603a0e83b06f304527e3e9aec527c344e35e7023d76sewardj/* Create an x87 FPU state from the guest state, as close as 1604a0e83b06f304527e3e9aec527c344e35e7023d76sewardj we can approximate it. */ 160538a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic 160638a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjvoid do_get_x87 ( /*IN*/VexGuestX86State* vex_state, 160738a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj /*OUT*/UChar* x87_state ) 16080c2cb623cca372a2b42b073121c7413cdaaf75besewardj{ 1609a0e83b06f304527e3e9aec527c344e35e7023d76sewardj Int i, stno, preg; 16100c2cb623cca372a2b42b073121c7413cdaaf75besewardj UInt tagw; 1611f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj Double* vexRegs = (Double*)(&vex_state->guest_FPREG[0]); 1612f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj UChar* vexTags = (UChar*)(&vex_state->guest_FPTAG[0]); 16130c2cb623cca372a2b42b073121c7413cdaaf75besewardj Fpu_State* x87 = (Fpu_State*)x87_state; 1614f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj UInt ftop = vex_state->guest_FTOP; 1615f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj UInt c3210 = vex_state->guest_FC3210; 16160c2cb623cca372a2b42b073121c7413cdaaf75besewardj 16170c2cb623cca372a2b42b073121c7413cdaaf75besewardj for (i = 0; i < 14; i++) 16180c2cb623cca372a2b42b073121c7413cdaaf75besewardj x87->env[i] = 0; 16190c2cb623cca372a2b42b073121c7413cdaaf75besewardj 16200c2cb623cca372a2b42b073121c7413cdaaf75besewardj x87->env[1] = x87->env[3] = x87->env[5] = x87->env[13] = 0xFFFF; 1621c4be80c5f03eda35da5d9f2aeba90f27a2015b93sewardj x87->env[FP_ENV_STAT] = ((ftop & 7) << 11) | (c3210 & 0x4700); 1622893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj x87->env[FP_ENV_CTRL] 16233bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj = (UShort)x86g_create_fpucw( vex_state->guest_FPROUND ); 16240c2cb623cca372a2b42b073121c7413cdaaf75besewardj 1625a0e83b06f304527e3e9aec527c344e35e7023d76sewardj /* Dump the register stack in ST order. */ 16260c2cb623cca372a2b42b073121c7413cdaaf75besewardj tagw = 0; 1627a0e83b06f304527e3e9aec527c344e35e7023d76sewardj for (stno = 0; stno < 8; stno++) { 1628a0e83b06f304527e3e9aec527c344e35e7023d76sewardj preg = (stno + ftop) & 7; 1629a0e83b06f304527e3e9aec527c344e35e7023d76sewardj if (vexTags[preg] == 0) { 16300c2cb623cca372a2b42b073121c7413cdaaf75besewardj /* register is empty */ 1631a0e83b06f304527e3e9aec527c344e35e7023d76sewardj tagw |= (3 << (2*preg)); 1632a0e83b06f304527e3e9aec527c344e35e7023d76sewardj convert_f64le_to_f80le( (UChar*)&vexRegs[preg], 1633a0e83b06f304527e3e9aec527c344e35e7023d76sewardj &x87->reg[10*stno] ); 16340c2cb623cca372a2b42b073121c7413cdaaf75besewardj } else { 16350c2cb623cca372a2b42b073121c7413cdaaf75besewardj /* register is full. */ 1636a0e83b06f304527e3e9aec527c344e35e7023d76sewardj tagw |= (0 << (2*preg)); 1637a0e83b06f304527e3e9aec527c344e35e7023d76sewardj convert_f64le_to_f80le( (UChar*)&vexRegs[preg], 1638a0e83b06f304527e3e9aec527c344e35e7023d76sewardj &x87->reg[10*stno] ); 16390c2cb623cca372a2b42b073121c7413cdaaf75besewardj } 16400c2cb623cca372a2b42b073121c7413cdaaf75besewardj } 16410c2cb623cca372a2b42b073121c7413cdaaf75besewardj x87->env[FP_ENV_TAG] = tagw; 16420c2cb623cca372a2b42b073121c7413cdaaf75besewardj} 16430c2cb623cca372a2b42b073121c7413cdaaf75besewardj 16440c2cb623cca372a2b42b073121c7413cdaaf75besewardj 1645f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj/* VISIBLE TO LIBVEX CLIENT */ 164676bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardjUInt LibVEX_GuestX86_get_eflags ( /*IN*/VexGuestX86State* vex_state ) 1647f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj{ 16482a9ad023890d3b34cf45e429df2a8ae88b419128sewardj UInt eflags = x86g_calculate_eflags_all( 1649f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj vex_state->guest_CC_OP, 16502a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj vex_state->guest_CC_DEP1, 16512a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj vex_state->guest_CC_DEP2, 16522a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj vex_state->guest_CC_NDEP 1653f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj ); 1654f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj UInt dflag = vex_state->guest_DFLAG; 1655f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj vassert(dflag == 1 || dflag == 0xFFFFFFFF); 1656f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj if (dflag == 0xFFFFFFFF) 1657f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj eflags |= (1<<10); 1658006a6a2f15f48f705895a516d4883e8f8142e910sewardj if (vex_state->guest_IDFLAG == 1) 1659006a6a2f15f48f705895a516d4883e8f8142e910sewardj eflags |= (1<<21); 1660f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj 1661f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj return eflags; 1662f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj} 1663f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj 1664dda7a4c98be4c7c6f11eab4e1cad6ab275aed79csewardj/* VISIBLE TO LIBVEX CLIENT */ 166576bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardjvoid LibVEX_GuestX86_initialise ( /*OUT*/VexGuestX86State* vex_state ) 1666dda7a4c98be4c7c6f11eab4e1cad6ab275aed79csewardj{ 166776bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj vex_state->guest_EAX = 0; 166876bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj vex_state->guest_ECX = 0; 166976bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj vex_state->guest_EDX = 0; 167076bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj vex_state->guest_EBX = 0; 167176bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj vex_state->guest_ESP = 0; 167276bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj vex_state->guest_EBP = 0; 167376bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj vex_state->guest_ESI = 0; 167476bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj vex_state->guest_EDI = 0; 167576bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj 16762a9ad023890d3b34cf45e429df2a8ae88b419128sewardj vex_state->guest_CC_OP = X86G_CC_OP_COPY; 16772a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj vex_state->guest_CC_DEP1 = 0; 16782a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj vex_state->guest_CC_DEP2 = 0; 16792a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj vex_state->guest_CC_NDEP = 0; 16802a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj vex_state->guest_DFLAG = 1; /* forwards */ 16812a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj vex_state->guest_IDFLAG = 0; 168276bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj 168376bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj vex_state->guest_EIP = 0; 168476bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj 1685a0e83b06f304527e3e9aec527c344e35e7023d76sewardj /* Initialise the simulated FPU */ 1686a0e83b06f304527e3e9aec527c344e35e7023d76sewardj x86g_dirtyhelper_FINIT( vex_state ); 168776bdc805d2e3104009118cb0a2adf3ecff45e2a3sewardj 1688a0e83b06f304527e3e9aec527c344e35e7023d76sewardj /* Initialse the SSE state. */ 1689c9a43665879a03886b27a65b68af2a2c11b04f59sewardj# define SSEZERO(_xmm) _xmm[0]=_xmm[1]=_xmm[2]=_xmm[3] = 0; 1690c9a43665879a03886b27a65b68af2a2c11b04f59sewardj 1691c9a43665879a03886b27a65b68af2a2c11b04f59sewardj vex_state->guest_SSEROUND = (UInt)Irrm_NEAREST; 1692c9a43665879a03886b27a65b68af2a2c11b04f59sewardj SSEZERO(vex_state->guest_XMM0); 1693c9a43665879a03886b27a65b68af2a2c11b04f59sewardj SSEZERO(vex_state->guest_XMM1); 1694c9a43665879a03886b27a65b68af2a2c11b04f59sewardj SSEZERO(vex_state->guest_XMM2); 1695c9a43665879a03886b27a65b68af2a2c11b04f59sewardj SSEZERO(vex_state->guest_XMM3); 1696c9a43665879a03886b27a65b68af2a2c11b04f59sewardj SSEZERO(vex_state->guest_XMM4); 1697c9a43665879a03886b27a65b68af2a2c11b04f59sewardj SSEZERO(vex_state->guest_XMM5); 1698c9a43665879a03886b27a65b68af2a2c11b04f59sewardj SSEZERO(vex_state->guest_XMM6); 1699c9a43665879a03886b27a65b68af2a2c11b04f59sewardj SSEZERO(vex_state->guest_XMM7); 1700c9a43665879a03886b27a65b68af2a2c11b04f59sewardj 1701c9a43665879a03886b27a65b68af2a2c11b04f59sewardj# undef SSEZERO 1702c9a43665879a03886b27a65b68af2a2c11b04f59sewardj 17033bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj vex_state->guest_CS = 0; 17043bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj vex_state->guest_DS = 0; 17053bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj vex_state->guest_ES = 0; 17063bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj vex_state->guest_FS = 0; 17073bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj vex_state->guest_GS = 0; 17083bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj vex_state->guest_SS = 0; 17093bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj vex_state->guest_LDT = 0; 17103bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj vex_state->guest_GDT = 0; 1711893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj 1712893aadad7f29f7801ce26cb7575c16e90bd3767fsewardj vex_state->guest_EMWARN = EmWarn_NONE; 1713dda7a4c98be4c7c6f11eab4e1cad6ab275aed79csewardj} 1714f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj 1715f6dc3ce7df8154569748530c20b31c44f60ab6f8sewardj 17169aebb0c3f7a7f43313786826f31402f2b733badfsewardj/*----------------------------------------------*/ 17179fc9e782027baafd8b94163778996d6f05109f62sewardj/*--- Misc integer/fp helpers ---*/ 17189aebb0c3f7a7f43313786826f31402f2b733badfsewardj/*----------------------------------------------*/ 17199aebb0c3f7a7f43313786826f31402f2b733badfsewardj 17209aebb0c3f7a7f43313786826f31402f2b733badfsewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */ 17219aebb0c3f7a7f43313786826f31402f2b733badfsewardj/* Calculate both flags and value result for rotate right 17229aebb0c3f7a7f43313786826f31402f2b733badfsewardj through the carry bit. Result in low 32 bits, 17239aebb0c3f7a7f43313786826f31402f2b733badfsewardj new flags (OSZACP) in high 32 bits. 17249aebb0c3f7a7f43313786826f31402f2b733badfsewardj*/ 17252a9ad023890d3b34cf45e429df2a8ae88b419128sewardjULong x86g_calculate_RCR ( UInt arg, UInt rot_amt, UInt eflags_in, UInt sz ) 17269aebb0c3f7a7f43313786826f31402f2b733badfsewardj{ 17279aebb0c3f7a7f43313786826f31402f2b733badfsewardj UInt tempCOUNT = rot_amt & 0x1F, cf=0, of=0, tempcf; 17289aebb0c3f7a7f43313786826f31402f2b733badfsewardj 17299aebb0c3f7a7f43313786826f31402f2b733badfsewardj switch (sz) { 17309aebb0c3f7a7f43313786826f31402f2b733badfsewardj case 4: 17312a9ad023890d3b34cf45e429df2a8ae88b419128sewardj cf = (eflags_in >> X86G_CC_SHIFT_C) & 1; 17329aebb0c3f7a7f43313786826f31402f2b733badfsewardj of = ((arg >> 31) ^ cf) & 1; 17339aebb0c3f7a7f43313786826f31402f2b733badfsewardj while (tempCOUNT > 0) { 17349aebb0c3f7a7f43313786826f31402f2b733badfsewardj tempcf = arg & 1; 17359aebb0c3f7a7f43313786826f31402f2b733badfsewardj arg = (arg >> 1) | (cf << 31); 17369aebb0c3f7a7f43313786826f31402f2b733badfsewardj cf = tempcf; 17379aebb0c3f7a7f43313786826f31402f2b733badfsewardj tempCOUNT--; 17389aebb0c3f7a7f43313786826f31402f2b733badfsewardj } 17399aebb0c3f7a7f43313786826f31402f2b733badfsewardj break; 17409aebb0c3f7a7f43313786826f31402f2b733badfsewardj case 2: 17419aebb0c3f7a7f43313786826f31402f2b733badfsewardj while (tempCOUNT >= 17) tempCOUNT -= 17; 17422a9ad023890d3b34cf45e429df2a8ae88b419128sewardj cf = (eflags_in >> X86G_CC_SHIFT_C) & 1; 17439aebb0c3f7a7f43313786826f31402f2b733badfsewardj of = ((arg >> 15) ^ cf) & 1; 17449aebb0c3f7a7f43313786826f31402f2b733badfsewardj while (tempCOUNT > 0) { 17459aebb0c3f7a7f43313786826f31402f2b733badfsewardj tempcf = arg & 1; 17469aebb0c3f7a7f43313786826f31402f2b733badfsewardj arg = ((arg >> 1) & 0x7FFF) | (cf << 15); 17479aebb0c3f7a7f43313786826f31402f2b733badfsewardj cf = tempcf; 17489aebb0c3f7a7f43313786826f31402f2b733badfsewardj tempCOUNT--; 17499aebb0c3f7a7f43313786826f31402f2b733badfsewardj } 17509aebb0c3f7a7f43313786826f31402f2b733badfsewardj break; 17519aebb0c3f7a7f43313786826f31402f2b733badfsewardj case 1: 17529aebb0c3f7a7f43313786826f31402f2b733badfsewardj while (tempCOUNT >= 9) tempCOUNT -= 9; 17532a9ad023890d3b34cf45e429df2a8ae88b419128sewardj cf = (eflags_in >> X86G_CC_SHIFT_C) & 1; 17549aebb0c3f7a7f43313786826f31402f2b733badfsewardj of = ((arg >> 7) ^ cf) & 1; 17559aebb0c3f7a7f43313786826f31402f2b733badfsewardj while (tempCOUNT > 0) { 17569aebb0c3f7a7f43313786826f31402f2b733badfsewardj tempcf = arg & 1; 17579aebb0c3f7a7f43313786826f31402f2b733badfsewardj arg = ((arg >> 1) & 0x7F) | (cf << 7); 17589aebb0c3f7a7f43313786826f31402f2b733badfsewardj cf = tempcf; 17599aebb0c3f7a7f43313786826f31402f2b733badfsewardj tempCOUNT--; 17609aebb0c3f7a7f43313786826f31402f2b733badfsewardj } 17619aebb0c3f7a7f43313786826f31402f2b733badfsewardj break; 17629aebb0c3f7a7f43313786826f31402f2b733badfsewardj default: 17639aebb0c3f7a7f43313786826f31402f2b733badfsewardj vpanic("calculate_RCR: invalid size"); 17649aebb0c3f7a7f43313786826f31402f2b733badfsewardj } 17659aebb0c3f7a7f43313786826f31402f2b733badfsewardj 17669aebb0c3f7a7f43313786826f31402f2b733badfsewardj cf &= 1; 17679aebb0c3f7a7f43313786826f31402f2b733badfsewardj of &= 1; 17682a9ad023890d3b34cf45e429df2a8ae88b419128sewardj eflags_in &= ~(X86G_CC_MASK_C | X86G_CC_MASK_O); 17692a9ad023890d3b34cf45e429df2a8ae88b419128sewardj eflags_in |= (cf << X86G_CC_SHIFT_C) | (of << X86G_CC_SHIFT_O); 17709aebb0c3f7a7f43313786826f31402f2b733badfsewardj 17719aebb0c3f7a7f43313786826f31402f2b733badfsewardj return (((ULong)eflags_in) << 32) | ((ULong)arg); 17729aebb0c3f7a7f43313786826f31402f2b733badfsewardj} 17739aebb0c3f7a7f43313786826f31402f2b733badfsewardj 17747cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardj 17757cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardj/* CALLED FROM GENERATED CODE */ 17767cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardj/* DIRTY HELPER (modifies guest state) */ 17774ba6ed0799fcf768e3fb9627fabc52fb1d6c2a6csewardj/* Claim to be a P55C (Intel Pentium/MMX) */ 17789df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardjvoid x86g_dirtyhelper_CPUID_sse0 ( VexGuestX86State* st ) 17797cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardj{ 17809df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj switch (st->guest_EAX) { 17819df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj case 0: 17829df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj st->guest_EAX = 0x1; 17839df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj st->guest_EBX = 0x756e6547; 17849df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj st->guest_ECX = 0x6c65746e; 17859df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj st->guest_EDX = 0x49656e69; 17869df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj break; 17879df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj default: 17889df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj st->guest_EAX = 0x543; 17899df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj st->guest_EBX = 0x0; 17909df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj st->guest_ECX = 0x0; 17919df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj st->guest_EDX = 0x8001bf; 17929df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj break; 17939df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj } 17949df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj} 17959df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj 17969df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj/* CALLED FROM GENERATED CODE */ 17979df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj/* DIRTY HELPER (modifies guest state) */ 17989df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj/* Claim to be the following SSE1-capable CPU: 17999df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj vendor_id : GenuineIntel 18009df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj cpu family : 6 18019df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj model : 11 18029df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj model name : Intel(R) Pentium(R) III CPU family 1133MHz 18039df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj stepping : 1 18049df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj cpu MHz : 1131.013 18059df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj cache size : 512 KB 18069df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj*/ 18079df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardjvoid x86g_dirtyhelper_CPUID_sse1 ( VexGuestX86State* st ) 18089df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj{ 18099df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj switch (st->guest_EAX) { 18109df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj case 0: 18119df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj st->guest_EAX = 0x00000002; 18129df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj st->guest_EBX = 0x756e6547; 18139df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj st->guest_ECX = 0x6c65746e; 18149df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj st->guest_EDX = 0x49656e69; 18159df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj break; 18169df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj case 1: 18179df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj st->guest_EAX = 0x000006b1; 18189df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj st->guest_EBX = 0x00000004; 18199df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj st->guest_ECX = 0x00000000; 18209df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj st->guest_EDX = 0x0383fbff; 18219df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj break; 18229df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj default: 18239df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj st->guest_EAX = 0x03020101; 18249df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj st->guest_EBX = 0x00000000; 18259df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj st->guest_ECX = 0x00000000; 18269df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj st->guest_EDX = 0x0c040883; 18279df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj break; 18289df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj } 18299df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj} 18309df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj 18319df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj/* Claim to be the following SSE2-capable CPU: 18329df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj vendor_id : GenuineIntel 18339df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj cpu family : 15 18349df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj model : 2 18359df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj model name : Intel(R) Pentium(R) 4 CPU 2.40GHz 18369df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj stepping : 7 18379df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj cpu MHz : 2394.234 18389df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj cache size : 512 KB 18399df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj*/ 18409df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardjvoid x86g_dirtyhelper_CPUID_sse2 ( VexGuestX86State* st ) 18419df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj{ 18429df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj switch (st->guest_EAX) { 18439df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj case 0: 18449df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj st->guest_EAX = 0x00000002; 18459df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj st->guest_EBX = 0x756e6547; 18469df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj st->guest_ECX = 0x6c65746e; 18479df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj st->guest_EDX = 0x49656e69; 18489df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj break; 18499df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj case 1: 18509df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj st->guest_EAX = 0x00000f27; 18519df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj st->guest_EBX = 0x00010809; 18529df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj st->guest_ECX = 0x00004400; 18539df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj st->guest_EDX = 0xbfebfbff; 18549df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj break; 18559df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj default: 18569df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj st->guest_EAX = 0x665b5101; 18579df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj st->guest_EBX = 0x00000000; 18589df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj st->guest_ECX = 0x00000000; 18599df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj st->guest_EDX = 0x007b7040; 18609df271d97c0f79a58a8eabdcfbe6f8bf4d17876asewardj break; 18617cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardj } 18627cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardj} 18637cb49d78b0f97c1f83ac95a02f4d044a4dd3f194sewardj 1864464efa446b2db97115d3e5f04af5db3464cc0e93sewardj 18659fc9e782027baafd8b94163778996d6f05109f62sewardj/* CALLED FROM GENERATED CODE */ 18669fc9e782027baafd8b94163778996d6f05109f62sewardj/* DIRTY HELPER (reads guest state, writes guest mem) */ 1867a0e83b06f304527e3e9aec527c344e35e7023d76sewardjvoid x86g_dirtyhelper_FXSAVE ( VexGuestX86State* gst, HWord addr ) 1868a0e83b06f304527e3e9aec527c344e35e7023d76sewardj{ 1869a0e83b06f304527e3e9aec527c344e35e7023d76sewardj /* Somewhat roundabout, but at least it's simple. */ 1870a0e83b06f304527e3e9aec527c344e35e7023d76sewardj Fpu_State tmp; 1871a0e83b06f304527e3e9aec527c344e35e7023d76sewardj UShort* addrS = (UShort*)addr; 1872a0e83b06f304527e3e9aec527c344e35e7023d76sewardj UChar* addrC = (UChar*)addr; 1873a0e83b06f304527e3e9aec527c344e35e7023d76sewardj U128* xmm = (U128*)(addr + 160); 1874a0e83b06f304527e3e9aec527c344e35e7023d76sewardj UInt mxcsr; 1875a0e83b06f304527e3e9aec527c344e35e7023d76sewardj UShort fp_tags; 1876a0e83b06f304527e3e9aec527c344e35e7023d76sewardj UChar summary_tags; 1877a0e83b06f304527e3e9aec527c344e35e7023d76sewardj Int r, stno; 1878a0e83b06f304527e3e9aec527c344e35e7023d76sewardj UShort *srcS, *dstS; 1879a0e83b06f304527e3e9aec527c344e35e7023d76sewardj 188038a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj do_get_x87( gst, (UChar*)&tmp ); 1881a0e83b06f304527e3e9aec527c344e35e7023d76sewardj mxcsr = x86g_create_mxcsr( gst->guest_SSEROUND ); 1882a0e83b06f304527e3e9aec527c344e35e7023d76sewardj 1883a0e83b06f304527e3e9aec527c344e35e7023d76sewardj /* Now build the proper fxsave image from the x87 image we just 1884a0e83b06f304527e3e9aec527c344e35e7023d76sewardj made. */ 1885a0e83b06f304527e3e9aec527c344e35e7023d76sewardj 1886a0e83b06f304527e3e9aec527c344e35e7023d76sewardj addrS[0] = tmp.env[FP_ENV_CTRL]; /* FCW: fpu control word */ 1887a0e83b06f304527e3e9aec527c344e35e7023d76sewardj addrS[1] = tmp.env[FP_ENV_STAT]; /* FCW: fpu status word */ 1888a0e83b06f304527e3e9aec527c344e35e7023d76sewardj 1889a0e83b06f304527e3e9aec527c344e35e7023d76sewardj /* set addrS[2] in an endian-independent way */ 1890a0e83b06f304527e3e9aec527c344e35e7023d76sewardj summary_tags = 0; 1891a0e83b06f304527e3e9aec527c344e35e7023d76sewardj fp_tags = tmp.env[FP_ENV_TAG]; 1892a0e83b06f304527e3e9aec527c344e35e7023d76sewardj for (r = 0; r < 8; r++) { 1893a0e83b06f304527e3e9aec527c344e35e7023d76sewardj if ( ((fp_tags >> (2*r)) & 3) != 3 ) 1894a0e83b06f304527e3e9aec527c344e35e7023d76sewardj summary_tags |= (1 << r); 1895a0e83b06f304527e3e9aec527c344e35e7023d76sewardj } 1896a0e83b06f304527e3e9aec527c344e35e7023d76sewardj addrC[4] = summary_tags; /* FTW: tag summary byte */ 1897a0e83b06f304527e3e9aec527c344e35e7023d76sewardj addrC[5] = 0; /* pad */ 1898a0e83b06f304527e3e9aec527c344e35e7023d76sewardj 1899a0e83b06f304527e3e9aec527c344e35e7023d76sewardj addrS[3] = 0; /* FOP: fpu opcode (bogus) */ 1900a0e83b06f304527e3e9aec527c344e35e7023d76sewardj addrS[4] = 0; 1901a0e83b06f304527e3e9aec527c344e35e7023d76sewardj addrS[5] = 0; /* FPU IP (bogus) */ 1902a0e83b06f304527e3e9aec527c344e35e7023d76sewardj addrS[6] = 0; /* FPU IP's segment selector (bogus) (although we 1903a0e83b06f304527e3e9aec527c344e35e7023d76sewardj could conceivably dump %CS here) */ 1904a0e83b06f304527e3e9aec527c344e35e7023d76sewardj 1905a0e83b06f304527e3e9aec527c344e35e7023d76sewardj addrS[7] = 0; /* Intel reserved */ 1906a0e83b06f304527e3e9aec527c344e35e7023d76sewardj 1907a0e83b06f304527e3e9aec527c344e35e7023d76sewardj addrS[8] = 0; /* FPU DP (operand pointer) (bogus) */ 1908a0e83b06f304527e3e9aec527c344e35e7023d76sewardj addrS[9] = 0; /* FPU DP (operand pointer) (bogus) */ 1909a0e83b06f304527e3e9aec527c344e35e7023d76sewardj addrS[10] = 0; /* segment selector for above operand pointer; %DS 1910a0e83b06f304527e3e9aec527c344e35e7023d76sewardj perhaps? */ 1911a0e83b06f304527e3e9aec527c344e35e7023d76sewardj addrS[11] = 0; /* Intel reserved */ 1912a0e83b06f304527e3e9aec527c344e35e7023d76sewardj 1913a0e83b06f304527e3e9aec527c344e35e7023d76sewardj addrS[12] = (UShort)mxcsr; /* MXCSR */ 1914a0e83b06f304527e3e9aec527c344e35e7023d76sewardj addrS[13] = (UShort)(mxcsr >> 16); 1915a0e83b06f304527e3e9aec527c344e35e7023d76sewardj 1916a0e83b06f304527e3e9aec527c344e35e7023d76sewardj addrS[14] = 0xFFFF; /* MXCSR mask (lo16); who knows what for */ 1917a0e83b06f304527e3e9aec527c344e35e7023d76sewardj addrS[15] = 0xFFFF; /* MXCSR mask (hi16); who knows what for */ 1918a0e83b06f304527e3e9aec527c344e35e7023d76sewardj 1919a0e83b06f304527e3e9aec527c344e35e7023d76sewardj /* Copy in the FP registers, in ST order. */ 1920a0e83b06f304527e3e9aec527c344e35e7023d76sewardj for (stno = 0; stno < 8; stno++) { 1921a0e83b06f304527e3e9aec527c344e35e7023d76sewardj srcS = (UShort*)(&tmp.reg[10*stno]); 1922a0e83b06f304527e3e9aec527c344e35e7023d76sewardj dstS = (UShort*)(&addrS[16 + 8*stno]); 1923a0e83b06f304527e3e9aec527c344e35e7023d76sewardj dstS[0] = srcS[0]; 1924a0e83b06f304527e3e9aec527c344e35e7023d76sewardj dstS[1] = srcS[1]; 1925a0e83b06f304527e3e9aec527c344e35e7023d76sewardj dstS[2] = srcS[2]; 1926a0e83b06f304527e3e9aec527c344e35e7023d76sewardj dstS[3] = srcS[3]; 1927a0e83b06f304527e3e9aec527c344e35e7023d76sewardj dstS[4] = srcS[4]; 1928a0e83b06f304527e3e9aec527c344e35e7023d76sewardj dstS[5] = 0; 1929a0e83b06f304527e3e9aec527c344e35e7023d76sewardj dstS[6] = 0; 1930a0e83b06f304527e3e9aec527c344e35e7023d76sewardj dstS[7] = 0; 1931a0e83b06f304527e3e9aec527c344e35e7023d76sewardj } 1932a0e83b06f304527e3e9aec527c344e35e7023d76sewardj 1933a0e83b06f304527e3e9aec527c344e35e7023d76sewardj /* That's the first 160 bytes of the image done. Now only %xmm0 1934a0e83b06f304527e3e9aec527c344e35e7023d76sewardj .. %xmm7 remain to be copied. If the host is big-endian, these 1935a0e83b06f304527e3e9aec527c344e35e7023d76sewardj need to be byte-swapped. */ 1936a0e83b06f304527e3e9aec527c344e35e7023d76sewardj vassert(host_is_little_endian()); 1937a0e83b06f304527e3e9aec527c344e35e7023d76sewardj 1938a0e83b06f304527e3e9aec527c344e35e7023d76sewardj# define COPY_U128(_dst,_src) \ 1939a0e83b06f304527e3e9aec527c344e35e7023d76sewardj do { _dst[0] = _src[0]; _dst[1] = _src[1]; \ 1940a0e83b06f304527e3e9aec527c344e35e7023d76sewardj _dst[2] = _src[2]; _dst[3] = _src[3]; } \ 1941a0e83b06f304527e3e9aec527c344e35e7023d76sewardj while (0) 1942a0e83b06f304527e3e9aec527c344e35e7023d76sewardj 1943a0e83b06f304527e3e9aec527c344e35e7023d76sewardj COPY_U128( xmm[0], gst->guest_XMM0 ); 1944a0e83b06f304527e3e9aec527c344e35e7023d76sewardj COPY_U128( xmm[1], gst->guest_XMM1 ); 1945a0e83b06f304527e3e9aec527c344e35e7023d76sewardj COPY_U128( xmm[2], gst->guest_XMM2 ); 1946a0e83b06f304527e3e9aec527c344e35e7023d76sewardj COPY_U128( xmm[3], gst->guest_XMM3 ); 1947a0e83b06f304527e3e9aec527c344e35e7023d76sewardj COPY_U128( xmm[4], gst->guest_XMM4 ); 1948a0e83b06f304527e3e9aec527c344e35e7023d76sewardj COPY_U128( xmm[5], gst->guest_XMM5 ); 1949a0e83b06f304527e3e9aec527c344e35e7023d76sewardj COPY_U128( xmm[6], gst->guest_XMM6 ); 1950a0e83b06f304527e3e9aec527c344e35e7023d76sewardj COPY_U128( xmm[7], gst->guest_XMM7 ); 1951a0e83b06f304527e3e9aec527c344e35e7023d76sewardj 1952a0e83b06f304527e3e9aec527c344e35e7023d76sewardj# undef COPY_U128 1953a0e83b06f304527e3e9aec527c344e35e7023d76sewardj} 1954a0e83b06f304527e3e9aec527c344e35e7023d76sewardj 1955a0e83b06f304527e3e9aec527c344e35e7023d76sewardj 1956a0e83b06f304527e3e9aec527c344e35e7023d76sewardj/* CALLED FROM GENERATED CODE */ 1957a0e83b06f304527e3e9aec527c344e35e7023d76sewardj/* DIRTY HELPER (reads guest state, writes guest mem) */ 19589fc9e782027baafd8b94163778996d6f05109f62sewardjvoid x86g_dirtyhelper_FSAVE ( VexGuestX86State* gst, HWord addr ) 19599fc9e782027baafd8b94163778996d6f05109f62sewardj{ 196038a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj do_get_x87( gst, (UChar*)addr ); 19619fc9e782027baafd8b94163778996d6f05109f62sewardj} 19629fc9e782027baafd8b94163778996d6f05109f62sewardj 19639fc9e782027baafd8b94163778996d6f05109f62sewardj/* CALLED FROM GENERATED CODE */ 19649fc9e782027baafd8b94163778996d6f05109f62sewardj/* DIRTY HELPER (writes guest state, reads guest mem) */ 19657df596b1e36840e2d74c90aa55589934add61ccfsewardjVexEmWarn x86g_dirtyhelper_FRSTOR ( VexGuestX86State* gst, HWord addr ) 19667df596b1e36840e2d74c90aa55589934add61ccfsewardj{ 196738a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj return do_put_x87( True/*regs too*/, (UChar*)addr, gst ); 19687df596b1e36840e2d74c90aa55589934add61ccfsewardj} 19697df596b1e36840e2d74c90aa55589934add61ccfsewardj 19707df596b1e36840e2d74c90aa55589934add61ccfsewardj/* CALLED FROM GENERATED CODE */ 19717df596b1e36840e2d74c90aa55589934add61ccfsewardj/* DIRTY HELPER (reads guest state, writes guest mem) */ 19727df596b1e36840e2d74c90aa55589934add61ccfsewardjvoid x86g_dirtyhelper_FSTENV ( VexGuestX86State* gst, HWord addr ) 19737df596b1e36840e2d74c90aa55589934add61ccfsewardj{ 19747df596b1e36840e2d74c90aa55589934add61ccfsewardj /* Somewhat roundabout, but at least it's simple. */ 19757df596b1e36840e2d74c90aa55589934add61ccfsewardj Int i; 19767df596b1e36840e2d74c90aa55589934add61ccfsewardj UShort* addrP = (UShort*)addr; 19777df596b1e36840e2d74c90aa55589934add61ccfsewardj Fpu_State tmp; 197838a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj do_get_x87( gst, (UChar*)&tmp ); 19797df596b1e36840e2d74c90aa55589934add61ccfsewardj for (i = 0; i < 14; i++) 19807df596b1e36840e2d74c90aa55589934add61ccfsewardj addrP[i] = tmp.env[i]; 19817df596b1e36840e2d74c90aa55589934add61ccfsewardj} 19827df596b1e36840e2d74c90aa55589934add61ccfsewardj 19837df596b1e36840e2d74c90aa55589934add61ccfsewardj/* CALLED FROM GENERATED CODE */ 19847df596b1e36840e2d74c90aa55589934add61ccfsewardj/* DIRTY HELPER (writes guest state, reads guest mem) */ 19857df596b1e36840e2d74c90aa55589934add61ccfsewardjVexEmWarn x86g_dirtyhelper_FLDENV ( VexGuestX86State* gst, HWord addr ) 19869fc9e782027baafd8b94163778996d6f05109f62sewardj{ 198738a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj return do_put_x87( False/*don't move regs*/, (UChar*)addr, gst); 19889fc9e782027baafd8b94163778996d6f05109f62sewardj} 19899fc9e782027baafd8b94163778996d6f05109f62sewardj 1990464efa446b2db97115d3e5f04af5db3464cc0e93sewardj 1991464efa446b2db97115d3e5f04af5db3464cc0e93sewardj/*----------------------------------------------*/ 199238a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj/*--- Helpers for MMX/SSE ---*/ 1993464efa446b2db97115d3e5f04af5db3464cc0e93sewardj/*----------------------------------------------*/ 1994464efa446b2db97115d3e5f04af5db3464cc0e93sewardj 199538a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UChar abdU8 ( UChar xx, UChar yy ) { 199638a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj return xx>yy ? xx-yy : yy-xx; 199738a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj} 1998464efa446b2db97115d3e5f04af5db3464cc0e93sewardj 199938a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline ULong mk32x2 ( UInt w1, UInt w0 ) { 2000464efa446b2db97115d3e5f04af5db3464cc0e93sewardj return (((ULong)w1) << 32) | ((ULong)w0); 2001464efa446b2db97115d3e5f04af5db3464cc0e93sewardj} 2002464efa446b2db97115d3e5f04af5db3464cc0e93sewardj 200338a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UShort sel16x4_3 ( ULong w64 ) { 2004464efa446b2db97115d3e5f04af5db3464cc0e93sewardj UInt hi32 = (UInt)(w64 >> 32); 2005464efa446b2db97115d3e5f04af5db3464cc0e93sewardj return 0xFFFF & (UShort)(hi32 >> 16); 2006464efa446b2db97115d3e5f04af5db3464cc0e93sewardj} 200738a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UShort sel16x4_2 ( ULong w64 ) { 2008464efa446b2db97115d3e5f04af5db3464cc0e93sewardj UInt hi32 = (UInt)(w64 >> 32); 2009464efa446b2db97115d3e5f04af5db3464cc0e93sewardj return 0xFFFF & (UShort)hi32; 2010464efa446b2db97115d3e5f04af5db3464cc0e93sewardj} 201138a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UShort sel16x4_1 ( ULong w64 ) { 2012464efa446b2db97115d3e5f04af5db3464cc0e93sewardj UInt lo32 = (UInt)w64; 201363ba4091e2d4b049f9a81d878cb3f3c97d6e20bfsewardj return 0xFFFF & (UShort)(lo32 >> 16); 2014464efa446b2db97115d3e5f04af5db3464cc0e93sewardj} 201538a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UShort sel16x4_0 ( ULong w64 ) { 2016464efa446b2db97115d3e5f04af5db3464cc0e93sewardj UInt lo32 = (UInt)w64; 2017464efa446b2db97115d3e5f04af5db3464cc0e93sewardj return 0xFFFF & (UShort)lo32; 2018464efa446b2db97115d3e5f04af5db3464cc0e93sewardj} 2019464efa446b2db97115d3e5f04af5db3464cc0e93sewardj 202038a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UChar sel8x8_7 ( ULong w64 ) { 2021464efa446b2db97115d3e5f04af5db3464cc0e93sewardj UInt hi32 = (UInt)(w64 >> 32); 2022464efa446b2db97115d3e5f04af5db3464cc0e93sewardj return 0xFF & (UChar)(hi32 >> 24); 2023464efa446b2db97115d3e5f04af5db3464cc0e93sewardj} 202438a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UChar sel8x8_6 ( ULong w64 ) { 2025464efa446b2db97115d3e5f04af5db3464cc0e93sewardj UInt hi32 = (UInt)(w64 >> 32); 2026464efa446b2db97115d3e5f04af5db3464cc0e93sewardj return 0xFF & (UChar)(hi32 >> 16); 2027464efa446b2db97115d3e5f04af5db3464cc0e93sewardj} 202838a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UChar sel8x8_5 ( ULong w64 ) { 2029464efa446b2db97115d3e5f04af5db3464cc0e93sewardj UInt hi32 = (UInt)(w64 >> 32); 2030464efa446b2db97115d3e5f04af5db3464cc0e93sewardj return 0xFF & (UChar)(hi32 >> 8); 2031464efa446b2db97115d3e5f04af5db3464cc0e93sewardj} 203238a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UChar sel8x8_4 ( ULong w64 ) { 2033464efa446b2db97115d3e5f04af5db3464cc0e93sewardj UInt hi32 = (UInt)(w64 >> 32); 2034464efa446b2db97115d3e5f04af5db3464cc0e93sewardj return 0xFF & (UChar)(hi32 >> 0); 2035464efa446b2db97115d3e5f04af5db3464cc0e93sewardj} 203638a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UChar sel8x8_3 ( ULong w64 ) { 2037464efa446b2db97115d3e5f04af5db3464cc0e93sewardj UInt lo32 = (UInt)w64; 2038464efa446b2db97115d3e5f04af5db3464cc0e93sewardj return 0xFF & (UChar)(lo32 >> 24); 2039464efa446b2db97115d3e5f04af5db3464cc0e93sewardj} 204038a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UChar sel8x8_2 ( ULong w64 ) { 2041464efa446b2db97115d3e5f04af5db3464cc0e93sewardj UInt lo32 = (UInt)w64; 2042464efa446b2db97115d3e5f04af5db3464cc0e93sewardj return 0xFF & (UChar)(lo32 >> 16); 2043464efa446b2db97115d3e5f04af5db3464cc0e93sewardj} 204438a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UChar sel8x8_1 ( ULong w64 ) { 2045464efa446b2db97115d3e5f04af5db3464cc0e93sewardj UInt lo32 = (UInt)w64; 2046464efa446b2db97115d3e5f04af5db3464cc0e93sewardj return 0xFF & (UChar)(lo32 >> 8); 2047464efa446b2db97115d3e5f04af5db3464cc0e93sewardj} 204838a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic inline UChar sel8x8_0 ( ULong w64 ) { 2049464efa446b2db97115d3e5f04af5db3464cc0e93sewardj UInt lo32 = (UInt)w64; 2050464efa446b2db97115d3e5f04af5db3464cc0e93sewardj return 0xFF & (UChar)(lo32 >> 0); 2051464efa446b2db97115d3e5f04af5db3464cc0e93sewardj} 2052464efa446b2db97115d3e5f04af5db3464cc0e93sewardj 205338a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */ 205438a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjULong x86g_calculate_mmx_pmaddwd ( ULong xx, ULong yy ) 20554340dac5c2cede4962868e6da5b73282da2bc465sewardj{ 20564340dac5c2cede4962868e6da5b73282da2bc465sewardj return 20574340dac5c2cede4962868e6da5b73282da2bc465sewardj mk32x2( 20584340dac5c2cede4962868e6da5b73282da2bc465sewardj (((Int)(Short)sel16x4_3(xx)) * ((Int)(Short)sel16x4_3(yy))) 20594340dac5c2cede4962868e6da5b73282da2bc465sewardj + (((Int)(Short)sel16x4_2(xx)) * ((Int)(Short)sel16x4_2(yy))), 20604340dac5c2cede4962868e6da5b73282da2bc465sewardj (((Int)(Short)sel16x4_1(xx)) * ((Int)(Short)sel16x4_1(yy))) 20614340dac5c2cede4962868e6da5b73282da2bc465sewardj + (((Int)(Short)sel16x4_0(xx)) * ((Int)(Short)sel16x4_0(yy))) 20624340dac5c2cede4962868e6da5b73282da2bc465sewardj ); 20634340dac5c2cede4962868e6da5b73282da2bc465sewardj} 20644340dac5c2cede4962868e6da5b73282da2bc465sewardj 206538a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */ 206638a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjUInt x86g_calculate_mmx_pmovmskb ( ULong xx ) 2067b54520819b40c3fe907725b56bcd8db5112c0b9asewardj{ 2068b54520819b40c3fe907725b56bcd8db5112c0b9asewardj UInt r = 0; 2069b54520819b40c3fe907725b56bcd8db5112c0b9asewardj if (xx & (1ULL << (64-1))) r |= (1<<7); 2070b54520819b40c3fe907725b56bcd8db5112c0b9asewardj if (xx & (1ULL << (56-1))) r |= (1<<6); 2071b54520819b40c3fe907725b56bcd8db5112c0b9asewardj if (xx & (1ULL << (48-1))) r |= (1<<5); 2072b54520819b40c3fe907725b56bcd8db5112c0b9asewardj if (xx & (1ULL << (40-1))) r |= (1<<4); 2073b54520819b40c3fe907725b56bcd8db5112c0b9asewardj if (xx & (1ULL << (32-1))) r |= (1<<3); 2074b54520819b40c3fe907725b56bcd8db5112c0b9asewardj if (xx & (1ULL << (24-1))) r |= (1<<2); 2075b54520819b40c3fe907725b56bcd8db5112c0b9asewardj if (xx & (1ULL << (16-1))) r |= (1<<1); 2076b54520819b40c3fe907725b56bcd8db5112c0b9asewardj if (xx & (1ULL << ( 8-1))) r |= (1<<0); 2077b54520819b40c3fe907725b56bcd8db5112c0b9asewardj return r; 2078b54520819b40c3fe907725b56bcd8db5112c0b9asewardj} 2079b54520819b40c3fe907725b56bcd8db5112c0b9asewardj 208038a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */ 208138a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjULong x86g_calculate_mmx_psadbw ( ULong xx, ULong yy ) 20820bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj{ 20830bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj UInt t = 0; 20840bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj t += (UInt)abdU8( sel8x8_7(xx), sel8x8_7(yy) ); 20850bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj t += (UInt)abdU8( sel8x8_6(xx), sel8x8_6(yy) ); 20860bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj t += (UInt)abdU8( sel8x8_5(xx), sel8x8_5(yy) ); 20870bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj t += (UInt)abdU8( sel8x8_4(xx), sel8x8_4(yy) ); 20880bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj t += (UInt)abdU8( sel8x8_3(xx), sel8x8_3(yy) ); 20890bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj t += (UInt)abdU8( sel8x8_2(xx), sel8x8_2(yy) ); 20900bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj t += (UInt)abdU8( sel8x8_1(xx), sel8x8_1(yy) ); 20910bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj t += (UInt)abdU8( sel8x8_0(xx), sel8x8_0(yy) ); 20920bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj t &= 0xFFFF; 20930bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj return (ULong)t; 20940bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj} 20950bd7ce6ae95b61bd9781f6a70f0132681a7b6387sewardj 209638a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */ 2097e5854d6d470f21677ec84f71d09129434b044246sewardjUInt x86g_calculate_sse_pmovmskb ( ULong w64hi, ULong w64lo ) 2098e5854d6d470f21677ec84f71d09129434b044246sewardj{ 209938a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj UInt rHi8 = x86g_calculate_mmx_pmovmskb ( w64hi ); 210038a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj UInt rLo8 = x86g_calculate_mmx_pmovmskb ( w64lo ); 2101e5854d6d470f21677ec84f71d09129434b044246sewardj return ((rHi8 & 0xFF) << 8) | (rLo8 & 0xFF); 2102e5854d6d470f21677ec84f71d09129434b044246sewardj} 2103e5854d6d470f21677ec84f71d09129434b044246sewardj 2104464efa446b2db97115d3e5f04af5db3464cc0e93sewardj 21053bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj/*----------------------------------------------*/ 21063bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj/*--- Helpers for segment overrides ---*/ 21073bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj/*----------------------------------------------*/ 21083bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj 21093bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardjstatic inline 21103bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardjUInt get_segdescr_base ( VexGuestX86SegDescr* ent ) 21113bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj{ 21123bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj UInt lo = 0xFFFF & (UInt)ent->LdtEnt.Bits.BaseLow; 21133bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj UInt mid = 0xFF & (UInt)ent->LdtEnt.Bits.BaseMid; 21143bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj UInt hi = 0xFF & (UInt)ent->LdtEnt.Bits.BaseHi; 21153bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj return (hi << 24) | (mid << 16) | lo; 21163bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj} 21173bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj 21183bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardjstatic inline 21193bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardjUInt get_segdescr_limit ( VexGuestX86SegDescr* ent ) 21203bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj{ 21213bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj UInt lo = 0xFFFF & (UInt)ent->LdtEnt.Bits.LimitLow; 21223bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj UInt hi = 0xF & (UInt)ent->LdtEnt.Bits.LimitHi; 21233bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj UInt limit = (hi << 16) | lo; 21243bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj if (ent->LdtEnt.Bits.Granularity) 21253bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj limit = (limit << 12) | 0xFFF; 21263bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj return limit; 21273bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj} 21283bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj 212938a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */ 21303bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardjULong x86g_use_seg_selector ( HWord ldt, HWord gdt, 21313bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj UInt seg_selector, UInt virtual_addr ) 21323bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj{ 21333bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj UInt tiBit, base, limit; 21343bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj VexGuestX86SegDescr* the_descrs; 21353bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj 21363bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj Bool verboze = False; 21373bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj 21383bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj /* If this isn't true, we're in Big Trouble. */ 21393bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj vassert(8 == sizeof(VexGuestX86SegDescr)); 21403bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj 21413bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj if (verboze) 21423bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj vex_printf("x86h_use_seg_selector: " 21433bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj "seg_selector = 0x%x, vaddr = 0x%x\n", 21443bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj seg_selector, virtual_addr); 21453bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj 21463bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj /* Check for wildly invalid selector. */ 21473bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj if (seg_selector & ~0xFFFF) 21483bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj goto bad; 21493bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj 21503bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj seg_selector &= 0x0000FFFF; 21513bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj 21523bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj /* Sanity check the segment selector. Ensure that RPL=11b (least 21533bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj privilege). This forms the bottom 2 bits of the selector. */ 21543bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj if ((seg_selector & 3) != 3) 21553bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj goto bad; 21563bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj 21573bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj /* Extract the TI bit (0 means GDT, 1 means LDT) */ 21583bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj tiBit = (seg_selector >> 2) & 1; 21593bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj 21603bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj /* Convert the segment selector onto a table index */ 21613bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj seg_selector >>= 3; 21623bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj vassert(seg_selector >= 0 && seg_selector < 8192); 21633bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj 21643bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj if (tiBit == 0) { 21653bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj 21663bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj /* GDT access. */ 21673bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj /* Do we actually have a GDT to look at? */ 21683bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj if (gdt == 0) 21693bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj goto bad; 21703bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj 21713bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj /* Check for access to non-existent entry. */ 21723bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj if (seg_selector >= VEX_GUEST_X86_GDT_NENT) 21733bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj goto bad; 21743bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj 21753bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj the_descrs = (VexGuestX86SegDescr*)gdt; 21763bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj base = get_segdescr_base (&the_descrs[seg_selector]); 21773bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj limit = get_segdescr_limit(&the_descrs[seg_selector]); 21783bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj 21793bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj } else { 21803bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj 21813bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj /* All the same stuff, except for the LDT. */ 21823bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj if (ldt == 0) 21833bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj goto bad; 21843bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj 21853bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj if (seg_selector >= VEX_GUEST_X86_LDT_NENT) 21863bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj goto bad; 21873bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj 21883bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj the_descrs = (VexGuestX86SegDescr*)ldt; 21893bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj base = get_segdescr_base (&the_descrs[seg_selector]); 21903bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj limit = get_segdescr_limit(&the_descrs[seg_selector]); 21913bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj 21923bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj } 21933bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj 21943bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj /* Do the limit check. Note, this check is just slightly too 21953bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj slack. Really it should be "if (virtual_addr + size - 1 >= 21963bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj limit)," but we don't have the size info to hand. Getting it 21973bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj could be significantly complex. */ 21983bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj if (virtual_addr >= limit) 21993bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj goto bad; 22003bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj 22013bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj if (verboze) 22023bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj vex_printf("x86h_use_seg_selector: " 22033bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj "base = 0x%x, addr = 0x%x\n", 22043bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj base, base + virtual_addr); 22053bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj 22063bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj /* High 32 bits are zero, indicating success. */ 22073bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj return (ULong)( ((UInt)virtual_addr) + base ); 22083bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj 22093bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj bad: 22103bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj return 1ULL << 32; 22113bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj} 22123bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj 22133bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj 22148d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj/*-----------------------------------------------------------*/ 22158d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj/*--- Describing the x86 guest state, for the benefit ---*/ 22168d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj/*--- of iropt and instrumenters. ---*/ 22178d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj/*-----------------------------------------------------------*/ 22188d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj 22198d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj/* Figure out if any part of the guest state contained in minoff 22208d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj .. maxoff requires precise memory exceptions. If in doubt return 22218d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj True (but this is generates significantly slower code). 22228d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj 22238d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj We enforce precise exns for guest %ESP and %EIP only. 22248d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj*/ 22258d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardjBool guest_x86_state_requires_precise_mem_exns ( Int minoff, 22268d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj Int maxoff) 22278d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj{ 22288d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj Int esp_min = offsetof(VexGuestX86State, guest_ESP); 22298d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj Int esp_max = esp_min + 4 - 1; 22308d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj Int eip_min = offsetof(VexGuestX86State, guest_EIP); 22318d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj Int eip_max = eip_min + 4 - 1; 22328d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj 22338d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj if (maxoff < esp_min || minoff > esp_max) { 2234eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj /* no overlap with esp */ 22358d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj } else { 2236eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj return True; 22378d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj } 22388d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj 22398d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj if (maxoff < eip_min || minoff > eip_max) { 2240eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj /* no overlap with eip */ 22418d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj } else { 2242eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj return True; 22438d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj } 22448d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj 22458d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj return False; 22468d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj} 22478d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj 22488d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj 2249eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj#define ALWAYSDEFD(field) \ 2250eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj { offsetof(VexGuestX86State, field), \ 2251eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj (sizeof ((VexGuestX86State*)0)->field) } 2252eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj 2253eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardjVexGuestLayout 225449651f4b59b1ab7e0e70cccd34001630eafbe957sewardj x86guest_layout 2255eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj = { 2256eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj /* Total size of the guest state, in bytes. */ 2257eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj .total_sizeB = sizeof(VexGuestX86State), 2258eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj 2259eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj /* Describe the stack pointer. */ 2260eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj .offset_SP = offsetof(VexGuestX86State,guest_ESP), 2261eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj .sizeof_SP = 4, 2262eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj 2263cf7879021370aabcccb1a9347244fcc7d5680141sewardj /* Describe the instruction pointer. */ 2264cf7879021370aabcccb1a9347244fcc7d5680141sewardj .offset_IP = offsetof(VexGuestX86State,guest_EIP), 2265cf7879021370aabcccb1a9347244fcc7d5680141sewardj .sizeof_IP = 4, 2266eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj 2267eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj /* Describe any sections to be regarded by Memcheck as 2268eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj 'always-defined'. */ 22693bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj .n_alwaysDefd = 18, 22703bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj 22712a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj /* flags thunk: OP and NDEP are always defd, whereas DEP1 22722a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj and DEP2 have to be tracked. See detailed comment in 22732a2ba8b72b4e467292c33cec23dee90cbf078e5dsewardj gdefs.h on meaning of thunk fields. */ 22748fc937421c954ff9f707254f028b1fa0410c473dsewardj .alwaysDefd 22758fc937421c954ff9f707254f028b1fa0410c473dsewardj = { /* 0 */ ALWAYSDEFD(guest_CC_OP), 22768fc937421c954ff9f707254f028b1fa0410c473dsewardj /* 1 */ ALWAYSDEFD(guest_CC_NDEP), 22778fc937421c954ff9f707254f028b1fa0410c473dsewardj /* 2 */ ALWAYSDEFD(guest_DFLAG), 22788fc937421c954ff9f707254f028b1fa0410c473dsewardj /* 3 */ ALWAYSDEFD(guest_IDFLAG), 22798fc937421c954ff9f707254f028b1fa0410c473dsewardj /* 4 */ ALWAYSDEFD(guest_EIP), 22808fc937421c954ff9f707254f028b1fa0410c473dsewardj /* 5 */ ALWAYSDEFD(guest_FTOP), 22818fc937421c954ff9f707254f028b1fa0410c473dsewardj /* 6 */ ALWAYSDEFD(guest_FPTAG), 2282d01a9639811cd74b608f3d8877af4ad74d5089a7sewardj /* 7 */ ALWAYSDEFD(guest_FPROUND), 22838fc937421c954ff9f707254f028b1fa0410c473dsewardj /* 8 */ ALWAYSDEFD(guest_FC3210), 22848fc937421c954ff9f707254f028b1fa0410c473dsewardj /* 9 */ ALWAYSDEFD(guest_CS), 22858fc937421c954ff9f707254f028b1fa0410c473dsewardj /* 10 */ ALWAYSDEFD(guest_DS), 22868fc937421c954ff9f707254f028b1fa0410c473dsewardj /* 11 */ ALWAYSDEFD(guest_ES), 22878fc937421c954ff9f707254f028b1fa0410c473dsewardj /* 12 */ ALWAYSDEFD(guest_FS), 22888fc937421c954ff9f707254f028b1fa0410c473dsewardj /* 13 */ ALWAYSDEFD(guest_GS), 22893bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj /* 14 */ ALWAYSDEFD(guest_SS), 22903bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj /* 15 */ ALWAYSDEFD(guest_LDT), 22913bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj /* 16 */ ALWAYSDEFD(guest_GDT), 22923bd6f3ee3f38fe11f302dd41b2781c7bbc0f201csewardj /* 17 */ ALWAYSDEFD(guest_EMWARN) 22938fc937421c954ff9f707254f028b1fa0410c473dsewardj } 2294eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj }; 229549651f4b59b1ab7e0e70cccd34001630eafbe957sewardj 229649651f4b59b1ab7e0e70cccd34001630eafbe957sewardj 229736ca51378f8851635df814230fa23f2c409b9eddsewardj/*---------------------------------------------------------------*/ 2298c0ee2edb4563c90bc8f1a83a09984a1fda86d1d3sewardj/*--- end guest-x86/ghelpers.c ---*/ 229936ca51378f8851635df814230fa23f2c409b9eddsewardj/*---------------------------------------------------------------*/ 2300