1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/ 3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- begin guest_amd64_helpers.c ---*/ 4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/ 5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This file is part of Valgrind, a dynamic binary instrumentation 8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown framework. 9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 10b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Copyright (C) 2004-2011 OpenWorks LLP 11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info@open-works.net 12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This program is free software; you can redistribute it and/or 14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown modify it under the terms of the GNU General Public License as 15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown published by the Free Software Foundation; either version 2 of the 16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown License, or (at your option) any later version. 17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This program is distributed in the hope that it will be useful, but 19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown WITHOUT ANY WARRANTY; without even the implied warranty of 20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown General Public License for more details. 22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown You should have received a copy of the GNU General Public License 24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown along with this program; if not, write to the Free Software 25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 02110-1301, USA. 27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The GNU General Public License is contained in the file COPYING. 29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Neither the names of the U.S. Department of Energy nor the 31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown University of California nor the names of its contributors may be 32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown used to endorse or promote products derived from this software 33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown without prior written permission. 34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex_basictypes.h" 37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex_emwarn.h" 38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex_guest_amd64.h" 39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex_ir.h" 40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex.h" 41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "main_util.h" 43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "guest_generic_bb_to_IR.h" 44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "guest_amd64_defs.h" 45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "guest_generic_x87.h" 46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This file contains helper functions for amd64 guest code. 49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Calls to these functions are generated by the back end. 50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown These calls are of course in the host machine code and 51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown this file will be compiled to host machine code, so that 52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown all makes sense. 53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Only change the signatures of these helper functions very 55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown carefully. If you change the signature here, you'll have to change 56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the parameters passed to it in the IR calls constructed by 57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown guest-amd64/toIR.c. 58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The convention used is that all functions called from generated 60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown code are named amd64g_<something>, and any function whose name lacks 61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown that prefix is not called from generated code. Note that some 62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown LibVEX_* functions can however be called by VEX's client, but that 63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown is not the same as calling them from VEX-generated code. 64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Set to 1 to get detailed profiling info about use of the flag 68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown machinery. */ 69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define PROFILE_RFLAGS 0 70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/ 73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- %rflags run-time helpers. ---*/ 74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/ 75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Do 64x64 -> 128 signed/unsigned multiplies, for computing flags 77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown after imulq/mulq. */ 78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void mullS64 ( Long u, Long v, Long* rHi, Long* rLo ) 80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong u0, v0, w0; 82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Long u1, v1, w1, w2, t; 83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown u0 = u & 0xFFFFFFFFULL; 84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown u1 = u >> 32; 85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown v0 = v & 0xFFFFFFFFULL; 86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown v1 = v >> 32; 87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown w0 = u0 * v0; 88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown t = u1 * v0 + (w0 >> 32); 89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown w1 = t & 0xFFFFFFFFULL; 90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown w2 = t >> 32; 91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown w1 = u0 * v1 + w1; 92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rHi = u1 * v1 + w2 + (w1 >> 32); 93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rLo = u * v; 94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void mullU64 ( ULong u, ULong v, ULong* rHi, ULong* rLo ) 97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong u0, v0, w0; 99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong u1, v1, w1,w2,t; 100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown u0 = u & 0xFFFFFFFFULL; 101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown u1 = u >> 32; 102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown v0 = v & 0xFFFFFFFFULL; 103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown v1 = v >> 32; 104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown w0 = u0 * v0; 105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown t = u1 * v0 + (w0 >> 32); 106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown w1 = t & 0xFFFFFFFFULL; 107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown w2 = t >> 32; 108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown w1 = u0 * v1 + w1; 109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rHi = u1 * v1 + w2 + (w1 >> 32); 110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rLo = u * v; 111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic const UChar parity_table[256] = { 115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, 116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, 119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, 121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, 122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, 125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, 126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, 128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, 131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, 133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, 134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, 136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, 139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, 140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, 143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, 145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, 146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}; 148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* generalised left-shifter */ 150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline Long lshift ( Long x, Int n ) 151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n >= 0) 153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return x << n; 154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return x >> (-n); 156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* identity on ULong */ 159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline ULong idULong ( ULong x ) 160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return x; 162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define PREAMBLE(__data_bits) \ 166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* const */ ULong DATA_MASK \ 167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = __data_bits==8 \ 168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ? 0xFFULL \ 169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown : (__data_bits==16 \ 170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ? 0xFFFFULL \ 171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown : (__data_bits==32 \ 172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ? 0xFFFFFFFFULL \ 173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown : 0xFFFFFFFFFFFFFFFFULL)); \ 174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* const */ ULong SIGN_MASK = 1ULL << (__data_bits - 1); \ 175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* const */ ULong CC_DEP1 = cc_dep1_formal; \ 176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* const */ ULong CC_DEP2 = cc_dep2_formal; \ 177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* const */ ULong CC_NDEP = cc_ndep_formal; \ 178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Four bogus assignments, which hopefully gcc can */ \ 179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* optimise away, and which stop it complaining about */ \ 180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* unused variables. */ \ 181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SIGN_MASK = SIGN_MASK; \ 182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DATA_MASK = DATA_MASK; \ 183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CC_DEP2 = CC_DEP2; \ 184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CC_NDEP = CC_NDEP; 185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-------------------------------------------------------------*/ 188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ACTIONS_ADD(DATA_BITS,DATA_UTYPE) \ 190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ \ 191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PREAMBLE(DATA_BITS); \ 192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { Long cf, pf, af, zf, sf, of; \ 193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Long argL, argR, res; \ 194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argL = CC_DEP1; \ 195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argR = CC_DEP2; \ 196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = argL + argR; \ 197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cf = (DATA_UTYPE)res < (DATA_UTYPE)argL; \ 198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pf = parity_table[(UChar)res]; \ 199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown af = (res ^ argL ^ argR) & 0x10; \ 200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown zf = ((DATA_UTYPE)res == 0) << 6; \ 201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sf = lshift(res, 8 - DATA_BITS) & 0x80; \ 202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of = lshift((argL ^ argR ^ -1) & (argL ^ res), \ 203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 12 - DATA_BITS) & AMD64G_CC_MASK_O; \ 204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return cf | pf | af | zf | sf | of; \ 205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } \ 206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-------------------------------------------------------------*/ 209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ACTIONS_SUB(DATA_BITS,DATA_UTYPE) \ 211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ \ 212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PREAMBLE(DATA_BITS); \ 213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { Long cf, pf, af, zf, sf, of; \ 214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Long argL, argR, res; \ 215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argL = CC_DEP1; \ 216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argR = CC_DEP2; \ 217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = argL - argR; \ 218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cf = (DATA_UTYPE)argL < (DATA_UTYPE)argR; \ 219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pf = parity_table[(UChar)res]; \ 220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown af = (res ^ argL ^ argR) & 0x10; \ 221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown zf = ((DATA_UTYPE)res == 0) << 6; \ 222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sf = lshift(res, 8 - DATA_BITS) & 0x80; \ 223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of = lshift((argL ^ argR) & (argL ^ res), \ 224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 12 - DATA_BITS) & AMD64G_CC_MASK_O; \ 225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return cf | pf | af | zf | sf | of; \ 226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } \ 227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-------------------------------------------------------------*/ 230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ACTIONS_ADC(DATA_BITS,DATA_UTYPE) \ 232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ \ 233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PREAMBLE(DATA_BITS); \ 234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { Long cf, pf, af, zf, sf, of; \ 235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Long argL, argR, oldC, res; \ 236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown oldC = CC_NDEP & AMD64G_CC_MASK_C; \ 237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argL = CC_DEP1; \ 238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argR = CC_DEP2 ^ oldC; \ 239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = (argL + argR) + oldC; \ 240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (oldC) \ 241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cf = (DATA_UTYPE)res <= (DATA_UTYPE)argL; \ 242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else \ 243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cf = (DATA_UTYPE)res < (DATA_UTYPE)argL; \ 244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pf = parity_table[(UChar)res]; \ 245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown af = (res ^ argL ^ argR) & 0x10; \ 246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown zf = ((DATA_UTYPE)res == 0) << 6; \ 247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sf = lshift(res, 8 - DATA_BITS) & 0x80; \ 248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of = lshift((argL ^ argR ^ -1) & (argL ^ res), \ 249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 12 - DATA_BITS) & AMD64G_CC_MASK_O; \ 250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return cf | pf | af | zf | sf | of; \ 251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } \ 252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-------------------------------------------------------------*/ 255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ACTIONS_SBB(DATA_BITS,DATA_UTYPE) \ 257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ \ 258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PREAMBLE(DATA_BITS); \ 259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { Long cf, pf, af, zf, sf, of; \ 260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Long argL, argR, oldC, res; \ 261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown oldC = CC_NDEP & AMD64G_CC_MASK_C; \ 262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argL = CC_DEP1; \ 263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argR = CC_DEP2 ^ oldC; \ 264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = (argL - argR) - oldC; \ 265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (oldC) \ 266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cf = (DATA_UTYPE)argL <= (DATA_UTYPE)argR; \ 267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else \ 268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cf = (DATA_UTYPE)argL < (DATA_UTYPE)argR; \ 269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pf = parity_table[(UChar)res]; \ 270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown af = (res ^ argL ^ argR) & 0x10; \ 271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown zf = ((DATA_UTYPE)res == 0) << 6; \ 272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sf = lshift(res, 8 - DATA_BITS) & 0x80; \ 273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of = lshift((argL ^ argR) & (argL ^ res), \ 274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 12 - DATA_BITS) & AMD64G_CC_MASK_O; \ 275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return cf | pf | af | zf | sf | of; \ 276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } \ 277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-------------------------------------------------------------*/ 280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ACTIONS_LOGIC(DATA_BITS,DATA_UTYPE) \ 282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ \ 283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PREAMBLE(DATA_BITS); \ 284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { Long cf, pf, af, zf, sf, of; \ 285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cf = 0; \ 286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pf = parity_table[(UChar)CC_DEP1]; \ 287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown af = 0; \ 288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown zf = ((DATA_UTYPE)CC_DEP1 == 0) << 6; \ 289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sf = lshift(CC_DEP1, 8 - DATA_BITS) & 0x80; \ 290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of = 0; \ 291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return cf | pf | af | zf | sf | of; \ 292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } \ 293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-------------------------------------------------------------*/ 296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ACTIONS_INC(DATA_BITS,DATA_UTYPE) \ 298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ \ 299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PREAMBLE(DATA_BITS); \ 300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { Long cf, pf, af, zf, sf, of; \ 301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Long argL, argR, res; \ 302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = CC_DEP1; \ 303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argL = res - 1; \ 304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argR = 1; \ 305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cf = CC_NDEP & AMD64G_CC_MASK_C; \ 306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pf = parity_table[(UChar)res]; \ 307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown af = (res ^ argL ^ argR) & 0x10; \ 308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown zf = ((DATA_UTYPE)res == 0) << 6; \ 309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sf = lshift(res, 8 - DATA_BITS) & 0x80; \ 310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of = ((res & DATA_MASK) == SIGN_MASK) << 11; \ 311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return cf | pf | af | zf | sf | of; \ 312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } \ 313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-------------------------------------------------------------*/ 316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ACTIONS_DEC(DATA_BITS,DATA_UTYPE) \ 318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ \ 319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PREAMBLE(DATA_BITS); \ 320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { Long cf, pf, af, zf, sf, of; \ 321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Long argL, argR, res; \ 322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = CC_DEP1; \ 323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argL = res + 1; \ 324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argR = 1; \ 325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cf = CC_NDEP & AMD64G_CC_MASK_C; \ 326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pf = parity_table[(UChar)res]; \ 327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown af = (res ^ argL ^ argR) & 0x10; \ 328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown zf = ((DATA_UTYPE)res == 0) << 6; \ 329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sf = lshift(res, 8 - DATA_BITS) & 0x80; \ 330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of = ((res & DATA_MASK) \ 331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown == ((ULong)SIGN_MASK - 1)) << 11; \ 332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return cf | pf | af | zf | sf | of; \ 333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } \ 334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-------------------------------------------------------------*/ 337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ACTIONS_SHL(DATA_BITS,DATA_UTYPE) \ 339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ \ 340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PREAMBLE(DATA_BITS); \ 341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { Long cf, pf, af, zf, sf, of; \ 342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cf = (CC_DEP2 >> (DATA_BITS - 1)) & AMD64G_CC_MASK_C; \ 343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pf = parity_table[(UChar)CC_DEP1]; \ 344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown af = 0; /* undefined */ \ 345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown zf = ((DATA_UTYPE)CC_DEP1 == 0) << 6; \ 346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sf = lshift(CC_DEP1, 8 - DATA_BITS) & 0x80; \ 347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* of is defined if shift count == 1 */ \ 348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of = lshift(CC_DEP2 ^ CC_DEP1, 12 - DATA_BITS) \ 349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown & AMD64G_CC_MASK_O; \ 350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return cf | pf | af | zf | sf | of; \ 351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } \ 352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-------------------------------------------------------------*/ 355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ACTIONS_SHR(DATA_BITS,DATA_UTYPE) \ 357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ \ 358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PREAMBLE(DATA_BITS); \ 359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { Long cf, pf, af, zf, sf, of; \ 360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cf = CC_DEP2 & 1; \ 361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pf = parity_table[(UChar)CC_DEP1]; \ 362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown af = 0; /* undefined */ \ 363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown zf = ((DATA_UTYPE)CC_DEP1 == 0) << 6; \ 364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sf = lshift(CC_DEP1, 8 - DATA_BITS) & 0x80; \ 365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* of is defined if shift count == 1 */ \ 366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of = lshift(CC_DEP2 ^ CC_DEP1, 12 - DATA_BITS) \ 367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown & AMD64G_CC_MASK_O; \ 368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return cf | pf | af | zf | sf | of; \ 369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } \ 370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-------------------------------------------------------------*/ 373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ROL: cf' = lsb(result). of' = msb(result) ^ lsb(result). */ 375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DEP1 = result, NDEP = old flags */ 376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ACTIONS_ROL(DATA_BITS,DATA_UTYPE) \ 377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ \ 378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PREAMBLE(DATA_BITS); \ 379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { Long fl \ 380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = (CC_NDEP & ~(AMD64G_CC_MASK_O | AMD64G_CC_MASK_C)) \ 381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown | (AMD64G_CC_MASK_C & CC_DEP1) \ 382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown | (AMD64G_CC_MASK_O & (lshift(CC_DEP1, \ 383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 11-(DATA_BITS-1)) \ 384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ^ lshift(CC_DEP1, 11))); \ 385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return fl; \ 386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } \ 387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-------------------------------------------------------------*/ 390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ROR: cf' = msb(result). of' = msb(result) ^ msb-1(result). */ 392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DEP1 = result, NDEP = old flags */ 393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ACTIONS_ROR(DATA_BITS,DATA_UTYPE) \ 394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ \ 395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PREAMBLE(DATA_BITS); \ 396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { Long fl \ 397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = (CC_NDEP & ~(AMD64G_CC_MASK_O | AMD64G_CC_MASK_C)) \ 398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown | (AMD64G_CC_MASK_C & (CC_DEP1 >> (DATA_BITS-1))) \ 399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown | (AMD64G_CC_MASK_O & (lshift(CC_DEP1, \ 400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 11-(DATA_BITS-1)) \ 401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ^ lshift(CC_DEP1, 11-(DATA_BITS-1)+1))); \ 402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return fl; \ 403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } \ 404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-------------------------------------------------------------*/ 407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ACTIONS_UMUL(DATA_BITS, DATA_UTYPE, NARROWtoU, \ 409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DATA_U2TYPE, NARROWto2U) \ 410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ \ 411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PREAMBLE(DATA_BITS); \ 412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { Long cf, pf, af, zf, sf, of; \ 413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DATA_UTYPE hi; \ 414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DATA_UTYPE lo \ 415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = NARROWtoU( ((DATA_UTYPE)CC_DEP1) \ 416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * ((DATA_UTYPE)CC_DEP2) ); \ 417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DATA_U2TYPE rr \ 418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = NARROWto2U( \ 419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ((DATA_U2TYPE)((DATA_UTYPE)CC_DEP1)) \ 420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * ((DATA_U2TYPE)((DATA_UTYPE)CC_DEP2)) ); \ 421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hi = NARROWtoU(rr >>/*u*/ DATA_BITS); \ 422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cf = (hi != 0); \ 423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pf = parity_table[(UChar)lo]; \ 424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown af = 0; /* undefined */ \ 425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown zf = (lo == 0) << 6; \ 426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sf = lshift(lo, 8 - DATA_BITS) & 0x80; \ 427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of = cf << 11; \ 428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return cf | pf | af | zf | sf | of; \ 429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } \ 430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-------------------------------------------------------------*/ 433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ACTIONS_SMUL(DATA_BITS, DATA_STYPE, NARROWtoS, \ 435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DATA_S2TYPE, NARROWto2S) \ 436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ \ 437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PREAMBLE(DATA_BITS); \ 438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { Long cf, pf, af, zf, sf, of; \ 439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DATA_STYPE hi; \ 440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DATA_STYPE lo \ 441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = NARROWtoS( ((DATA_STYPE)CC_DEP1) \ 442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * ((DATA_STYPE)CC_DEP2) ); \ 443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DATA_S2TYPE rr \ 444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = NARROWto2S( \ 445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ((DATA_S2TYPE)((DATA_STYPE)CC_DEP1)) \ 446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * ((DATA_S2TYPE)((DATA_STYPE)CC_DEP2)) ); \ 447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hi = NARROWtoS(rr >>/*s*/ DATA_BITS); \ 448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cf = (hi != (lo >>/*s*/ (DATA_BITS-1))); \ 449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pf = parity_table[(UChar)lo]; \ 450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown af = 0; /* undefined */ \ 451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown zf = (lo == 0) << 6; \ 452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sf = lshift(lo, 8 - DATA_BITS) & 0x80; \ 453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of = cf << 11; \ 454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return cf | pf | af | zf | sf | of; \ 455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } \ 456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-------------------------------------------------------------*/ 459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ACTIONS_UMULQ \ 461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ \ 462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PREAMBLE(64); \ 463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { Long cf, pf, af, zf, sf, of; \ 464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong lo, hi; \ 465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mullU64( (ULong)CC_DEP1, (ULong)CC_DEP2, &hi, &lo ); \ 466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cf = (hi != 0); \ 467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pf = parity_table[(UChar)lo]; \ 468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown af = 0; /* undefined */ \ 469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown zf = (lo == 0) << 6; \ 470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sf = lshift(lo, 8 - 64) & 0x80; \ 471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of = cf << 11; \ 472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return cf | pf | af | zf | sf | of; \ 473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } \ 474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-------------------------------------------------------------*/ 477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ACTIONS_SMULQ \ 479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ \ 480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PREAMBLE(64); \ 481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { Long cf, pf, af, zf, sf, of; \ 482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Long lo, hi; \ 483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mullS64( (Long)CC_DEP1, (Long)CC_DEP2, &hi, &lo ); \ 484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cf = (hi != (lo >>/*s*/ (64-1))); \ 485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pf = parity_table[(UChar)lo]; \ 486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown af = 0; /* undefined */ \ 487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown zf = (lo == 0) << 6; \ 488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sf = lshift(lo, 8 - 64) & 0x80; \ 489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of = cf << 11; \ 490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return cf | pf | af | zf | sf | of; \ 491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } \ 492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if PROFILE_RFLAGS 496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool initted = False; 498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* C flag, fast route */ 500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt tabc_fast[AMD64G_CC_OP_NUMBER]; 501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* C flag, slow route */ 502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt tabc_slow[AMD64G_CC_OP_NUMBER]; 503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* table for calculate_cond */ 504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt tab_cond[AMD64G_CC_OP_NUMBER][16]; 505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* total entry counts for calc_all, calc_c, calc_cond. */ 506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt n_calc_all = 0; 507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt n_calc_c = 0; 508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt n_calc_cond = 0; 509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHOW_COUNTS_NOW (0 == (0x3FFFFF & (n_calc_all+n_calc_c+n_calc_cond))) 511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void showCounts ( void ) 514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int op, co; 516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char ch; 517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_printf("\nTotal calls: calc_all=%u calc_cond=%u calc_c=%u\n", 518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_calc_all, n_calc_cond, n_calc_c); 519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_printf(" cSLOW cFAST O NO B NB Z NZ BE NBE" 521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " S NS P NP L NL LE NLE\n"); 522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_printf(" -----------------------------------------------------" 523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "----------------------------------------\n"); 524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (op = 0; op < AMD64G_CC_OP_NUMBER; op++) { 525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ch = ' '; 527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (op > 0 && (op-1) % 4 == 0) 528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ch = 'B'; 529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (op > 0 && (op-1) % 4 == 1) 530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ch = 'W'; 531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (op > 0 && (op-1) % 4 == 2) 532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ch = 'L'; 533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (op > 0 && (op-1) % 4 == 3) 534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ch = 'Q'; 535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_printf("%2d%c: ", op, ch); 537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_printf("%6u ", tabc_slow[op]); 538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_printf("%6u ", tabc_fast[op]); 539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (co = 0; co < 16; co++) { 540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int n = tab_cond[op][co]; 541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n >= 1000) { 542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_printf(" %3dK", n / 1000); 543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else 544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n >= 0) { 545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_printf(" %3d ", n ); 546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_printf(" "); 548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_printf("\n"); 551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_printf("\n"); 553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void initCounts ( void ) 556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int op, co; 558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown initted = True; 559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (op = 0; op < AMD64G_CC_OP_NUMBER; op++) { 560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tabc_fast[op] = tabc_slow[op] = 0; 561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (co = 0; co < 16; co++) 562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tab_cond[op][co] = 0; 563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif /* PROFILE_RFLAGS */ 567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CALLED FROM GENERATED CODE: CLEAN HELPER */ 570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Calculate all the 6 flags from the supplied thunk parameters. 571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Worker function, not directly called from generated code. */ 572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong amd64g_calculate_rflags_all_WRK ( ULong cc_op, 574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong cc_dep1_formal, 575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong cc_dep2_formal, 576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong cc_ndep_formal ) 577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (cc_op) { 579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_COPY: 580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return cc_dep1_formal 581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown & (AMD64G_CC_MASK_O | AMD64G_CC_MASK_S | AMD64G_CC_MASK_Z 582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown | AMD64G_CC_MASK_A | AMD64G_CC_MASK_C | AMD64G_CC_MASK_P); 583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_ADDB: ACTIONS_ADD( 8, UChar ); 585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_ADDW: ACTIONS_ADD( 16, UShort ); 586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_ADDL: ACTIONS_ADD( 32, UInt ); 587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_ADDQ: ACTIONS_ADD( 64, ULong ); 588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_ADCB: ACTIONS_ADC( 8, UChar ); 590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_ADCW: ACTIONS_ADC( 16, UShort ); 591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_ADCL: ACTIONS_ADC( 32, UInt ); 592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_ADCQ: ACTIONS_ADC( 64, ULong ); 593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_SUBB: ACTIONS_SUB( 8, UChar ); 595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_SUBW: ACTIONS_SUB( 16, UShort ); 596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_SUBL: ACTIONS_SUB( 32, UInt ); 597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_SUBQ: ACTIONS_SUB( 64, ULong ); 598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_SBBB: ACTIONS_SBB( 8, UChar ); 600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_SBBW: ACTIONS_SBB( 16, UShort ); 601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_SBBL: ACTIONS_SBB( 32, UInt ); 602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_SBBQ: ACTIONS_SBB( 64, ULong ); 603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_LOGICB: ACTIONS_LOGIC( 8, UChar ); 605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_LOGICW: ACTIONS_LOGIC( 16, UShort ); 606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_LOGICL: ACTIONS_LOGIC( 32, UInt ); 607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_LOGICQ: ACTIONS_LOGIC( 64, ULong ); 608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_INCB: ACTIONS_INC( 8, UChar ); 610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_INCW: ACTIONS_INC( 16, UShort ); 611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_INCL: ACTIONS_INC( 32, UInt ); 612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_INCQ: ACTIONS_INC( 64, ULong ); 613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_DECB: ACTIONS_DEC( 8, UChar ); 615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_DECW: ACTIONS_DEC( 16, UShort ); 616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_DECL: ACTIONS_DEC( 32, UInt ); 617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_DECQ: ACTIONS_DEC( 64, ULong ); 618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_SHLB: ACTIONS_SHL( 8, UChar ); 620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_SHLW: ACTIONS_SHL( 16, UShort ); 621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_SHLL: ACTIONS_SHL( 32, UInt ); 622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_SHLQ: ACTIONS_SHL( 64, ULong ); 623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_SHRB: ACTIONS_SHR( 8, UChar ); 625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_SHRW: ACTIONS_SHR( 16, UShort ); 626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_SHRL: ACTIONS_SHR( 32, UInt ); 627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_SHRQ: ACTIONS_SHR( 64, ULong ); 628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_ROLB: ACTIONS_ROL( 8, UChar ); 630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_ROLW: ACTIONS_ROL( 16, UShort ); 631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_ROLL: ACTIONS_ROL( 32, UInt ); 632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_ROLQ: ACTIONS_ROL( 64, ULong ); 633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_RORB: ACTIONS_ROR( 8, UChar ); 635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_RORW: ACTIONS_ROR( 16, UShort ); 636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_RORL: ACTIONS_ROR( 32, UInt ); 637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_RORQ: ACTIONS_ROR( 64, ULong ); 638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_UMULB: ACTIONS_UMUL( 8, UChar, toUChar, 640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UShort, toUShort ); 641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_UMULW: ACTIONS_UMUL( 16, UShort, toUShort, 642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt, toUInt ); 643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_UMULL: ACTIONS_UMUL( 32, UInt, toUInt, 644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong, idULong ); 645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_UMULQ: ACTIONS_UMULQ; 647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_SMULB: ACTIONS_SMUL( 8, Char, toUChar, 649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Short, toUShort ); 650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_SMULW: ACTIONS_SMUL( 16, Short, toUShort, 651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int, toUInt ); 652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_SMULL: ACTIONS_SMUL( 32, Int, toUInt, 653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Long, idULong ); 654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_SMULQ: ACTIONS_SMULQ; 656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* shouldn't really make these calls from generated code */ 659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_printf("amd64g_calculate_rflags_all_WRK(AMD64)" 660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "( %llu, 0x%llx, 0x%llx, 0x%llx )\n", 661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cc_op, cc_dep1_formal, cc_dep2_formal, cc_ndep_formal ); 662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("amd64g_calculate_rflags_all_WRK(AMD64)"); 663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CALLED FROM GENERATED CODE: CLEAN HELPER */ 668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Calculate all the 6 flags from the supplied thunk parameters. */ 669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong amd64g_calculate_rflags_all ( ULong cc_op, 670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong cc_dep1, 671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong cc_dep2, 672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong cc_ndep ) 673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if PROFILE_RFLAGS 675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!initted) initCounts(); 676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_calc_all++; 677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (SHOW_COUNTS_NOW) showCounts(); 678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown amd64g_calculate_rflags_all_WRK ( cc_op, cc_dep1, cc_dep2, cc_ndep ); 681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CALLED FROM GENERATED CODE: CLEAN HELPER */ 685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Calculate just the carry flag from the supplied thunk parameters. */ 686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong amd64g_calculate_rflags_c ( ULong cc_op, 687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong cc_dep1, 688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong cc_dep2, 689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong cc_ndep ) 690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if PROFILE_RFLAGS 692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!initted) initCounts(); 693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_calc_c++; 694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tabc_fast[cc_op]++; 695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (SHOW_COUNTS_NOW) showCounts(); 696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Fast-case some common ones. */ 699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (cc_op) { 700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_COPY: 701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return (cc_dep1 >> AMD64G_CC_SHIFT_C) & 1; 702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_LOGICQ: 703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_LOGICL: 704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_LOGICW: 705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64G_CC_OP_LOGICB: 706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // case AMD64G_CC_OP_SUBL: 708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // return ((UInt)cc_dep1) < ((UInt)cc_dep2) 709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // ? AMD64G_CC_MASK_C : 0; 710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // case AMD64G_CC_OP_SUBW: 711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // return ((UInt)(cc_dep1 & 0xFFFF)) < ((UInt)(cc_dep2 & 0xFFFF)) 712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // ? AMD64G_CC_MASK_C : 0; 713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // case AMD64G_CC_OP_SUBB: 714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // return ((UInt)(cc_dep1 & 0xFF)) < ((UInt)(cc_dep2 & 0xFF)) 715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // ? AMD64G_CC_MASK_C : 0; 716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // case AMD64G_CC_OP_INCL: 717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // case AMD64G_CC_OP_DECL: 718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // return cc_ndep & AMD64G_CC_MASK_C; 719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if PROFILE_RFLAGS 724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tabc_fast[cc_op]--; 725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tabc_slow[cc_op]++; 726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return amd64g_calculate_rflags_all_WRK(cc_op,cc_dep1,cc_dep2,cc_ndep) 729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown & AMD64G_CC_MASK_C; 730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CALLED FROM GENERATED CODE: CLEAN HELPER */ 734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* returns 1 or 0 */ 735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong amd64g_calculate_condition ( ULong/*AMD64Condcode*/ cond, 736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong cc_op, 737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong cc_dep1, 738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong cc_dep2, 739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong cc_ndep ) 740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong rflags = amd64g_calculate_rflags_all_WRK(cc_op, cc_dep1, 742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cc_dep2, cc_ndep); 743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong of,sf,zf,cf,pf; 744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong inv = cond & 1; 745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if PROFILE_RFLAGS 747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!initted) initCounts(); 748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tab_cond[cc_op][cond]++; 749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_calc_cond++; 750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (SHOW_COUNTS_NOW) showCounts(); 751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (cond) { 754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64CondNO: 755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64CondO: /* OF == 1 */ 756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of = rflags >> AMD64G_CC_SHIFT_O; 757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 1 & (inv ^ of); 758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64CondNZ: 760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64CondZ: /* ZF == 1 */ 761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown zf = rflags >> AMD64G_CC_SHIFT_Z; 762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 1 & (inv ^ zf); 763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64CondNB: 765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64CondB: /* CF == 1 */ 766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cf = rflags >> AMD64G_CC_SHIFT_C; 767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 1 & (inv ^ cf); 768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64CondNBE: 771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64CondBE: /* (CF or ZF) == 1 */ 772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cf = rflags >> AMD64G_CC_SHIFT_C; 773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown zf = rflags >> AMD64G_CC_SHIFT_Z; 774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 1 & (inv ^ (cf | zf)); 775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64CondNS: 778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64CondS: /* SF == 1 */ 779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sf = rflags >> AMD64G_CC_SHIFT_S; 780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 1 & (inv ^ sf); 781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64CondNP: 783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64CondP: /* PF == 1 */ 784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pf = rflags >> AMD64G_CC_SHIFT_P; 785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 1 & (inv ^ pf); 786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64CondNL: 788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64CondL: /* (SF xor OF) == 1 */ 789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sf = rflags >> AMD64G_CC_SHIFT_S; 790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of = rflags >> AMD64G_CC_SHIFT_O; 791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 1 & (inv ^ (sf ^ of)); 792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64CondNLE: 795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AMD64CondLE: /* ((SF xor OF) or ZF) == 1 */ 796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sf = rflags >> AMD64G_CC_SHIFT_S; 797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of = rflags >> AMD64G_CC_SHIFT_O; 798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown zf = rflags >> AMD64G_CC_SHIFT_Z; 799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 1 & (inv ^ ((sf ^ of) | zf)); 800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* shouldn't really make these calls from generated code */ 804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_printf("amd64g_calculate_condition" 805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "( %llu, %llu, 0x%llx, 0x%llx, 0x%llx )\n", 806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cond, cc_op, cc_dep1, cc_dep2, cc_ndep ); 807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("amd64g_calculate_condition"); 808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* VISIBLE TO LIBVEX CLIENT */ 813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong LibVEX_GuestAMD64_get_rflags ( /*IN*/VexGuestAMD64State* vex_state ) 814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong rflags = amd64g_calculate_rflags_all_WRK( 816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_state->guest_CC_OP, 817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_state->guest_CC_DEP1, 818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_state->guest_CC_DEP2, 819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_state->guest_CC_NDEP 820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Long dflag = vex_state->guest_DFLAG; 822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(dflag == 1 || dflag == -1); 823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (dflag == -1) 824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown rflags |= (1<<10); 825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (vex_state->guest_IDFLAG == 1) 826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown rflags |= (1<<21); 827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (vex_state->guest_ACFLAG == 1) 828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown rflags |= (1<<18); 829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return rflags; 831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* VISIBLE TO LIBVEX CLIENT */ 834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid 835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownLibVEX_GuestAMD64_put_rflag_c ( ULong new_carry_flag, 836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*MOD*/VexGuestAMD64State* vex_state ) 837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong oszacp = amd64g_calculate_rflags_all_WRK( 839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_state->guest_CC_OP, 840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_state->guest_CC_DEP1, 841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_state->guest_CC_DEP2, 842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_state->guest_CC_NDEP 843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (new_carry_flag & 1) { 845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown oszacp |= AMD64G_CC_MASK_C; 846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown oszacp &= ~AMD64G_CC_MASK_C; 848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_state->guest_CC_OP = AMD64G_CC_OP_COPY; 850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_state->guest_CC_DEP1 = oszacp; 851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_state->guest_CC_DEP2 = 0; 852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_state->guest_CC_NDEP = 0; 853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/ 857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- %rflags translation-time function specialisers. ---*/ 858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- These help iropt specialise calls the above run-time ---*/ 859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- %rflags functions. ---*/ 860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/ 861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Used by the optimiser to try specialisations. Returns an 863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown equivalent expression, or NULL if none. */ 864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool isU64 ( IRExpr* e, ULong n ) 866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return toBool( e->tag == Iex_Const 868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && e->Iex.Const.con->tag == Ico_U64 869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && e->Iex.Const.con->Ico.U64 == n ); 870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRExpr* guest_amd64_spechelper ( HChar* function_name, 873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr** args, 874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRStmt** precedingStmts, 875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int n_precedingStmts ) 876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define unop(_op,_a1) IRExpr_Unop((_op),(_a1)) 878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define binop(_op,_a1,_a2) IRExpr_Binop((_op),(_a1),(_a2)) 879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define mkU64(_n) IRExpr_Const(IRConst_U64(_n)) 880b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# define mkU32(_n) IRExpr_Const(IRConst_U32(_n)) 881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define mkU8(_n) IRExpr_Const(IRConst_U8(_n)) 882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i, arity = 0; 884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; args[i]; i++) 885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arity++; 886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if 0 887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_printf("spec request:\n"); 888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_printf(" %s ", function_name); 889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < arity; i++) { 890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_printf(" "); 891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIRExpr(args[i]); 892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_printf("\n"); 894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- specialising "amd64g_calculate_condition" --------- */ 897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (vex_streq(function_name, "amd64g_calculate_condition")) { 899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* specialise calls to above "calculate condition" function */ 900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr *cond, *cc_op, *cc_dep1, *cc_dep2; 901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(arity == 5); 902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cond = args[0]; 903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cc_op = args[1]; 904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cc_dep1 = args[2]; 905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cc_dep2 = args[3]; 906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*---------------- ADDQ ----------------*/ 908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isU64(cc_op, AMD64G_CC_OP_ADDQ) && isU64(cond, AMD64CondZ)) { 910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* long long add, then Z --> test (dst+src == 0) */ 911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return unop(Iop_1Uto64, 912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_CmpEQ64, 913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_Add64, cc_dep1, cc_dep2), 914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkU64(0))); 915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*---------------- SUBQ ----------------*/ 918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isU64(cc_op, AMD64G_CC_OP_SUBQ) && isU64(cond, AMD64CondZ)) { 920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* long long sub/cmp, then Z --> test dst==src */ 921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return unop(Iop_1Uto64, 922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_CmpEQ64,cc_dep1,cc_dep2)); 923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isU64(cc_op, AMD64G_CC_OP_SUBQ) && isU64(cond, AMD64CondNZ)) { 925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* long long sub/cmp, then NZ --> test dst!=src */ 926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return unop(Iop_1Uto64, 927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_CmpNE64,cc_dep1,cc_dep2)); 928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isU64(cc_op, AMD64G_CC_OP_SUBQ) && isU64(cond, AMD64CondL)) { 931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* long long sub/cmp, then L (signed less than) 932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown --> test dst <s src */ 933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return unop(Iop_1Uto64, 934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_CmpLT64S, cc_dep1, cc_dep2)); 935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isU64(cc_op, AMD64G_CC_OP_SUBQ) && isU64(cond, AMD64CondB)) { 938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* long long sub/cmp, then B (unsigned less than) 939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown --> test dst <u src */ 940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return unop(Iop_1Uto64, 941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_CmpLT64U, cc_dep1, cc_dep2)); 942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isU64(cc_op, AMD64G_CC_OP_SUBQ) && isU64(cond, AMD64CondNB)) { 944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* long long sub/cmp, then NB (unsigned greater than or equal) 945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown --> test src <=u dst */ 946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Note, args are opposite way round from the usual */ 947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return unop(Iop_1Uto64, 948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_CmpLE64U, cc_dep2, cc_dep1)); 949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isU64(cc_op, AMD64G_CC_OP_SUBQ) && isU64(cond, AMD64CondBE)) { 952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* long long sub/cmp, then BE (unsigned less than or equal) 953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown --> test dst <=u src */ 954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return unop(Iop_1Uto64, 955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_CmpLE64U, cc_dep1, cc_dep2)); 956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*---------------- SUBL ----------------*/ 959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondZ)) { 961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* long sub/cmp, then Z --> test dst==src */ 962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return unop(Iop_1Uto64, 963b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov binop(Iop_CmpEQ32, 964b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov unop(Iop_64to32, cc_dep1), 965b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov unop(Iop_64to32, cc_dep2))); 966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondNZ)) { 968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* long sub/cmp, then NZ --> test dst!=src */ 969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return unop(Iop_1Uto64, 970b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov binop(Iop_CmpNE32, 971b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov unop(Iop_64to32, cc_dep1), 972b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov unop(Iop_64to32, cc_dep2))); 973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondL)) { 976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* long sub/cmp, then L (signed less than) 977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown --> test dst <s src */ 978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return unop(Iop_1Uto64, 979b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov binop(Iop_CmpLT32S, 980b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov unop(Iop_64to32, cc_dep1), 981b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov unop(Iop_64to32, cc_dep2))); 982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondLE)) { 985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* long sub/cmp, then LE (signed less than or equal) 986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown --> test dst <=s src */ 987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return unop(Iop_1Uto64, 988b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov binop(Iop_CmpLE32S, 989b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov unop(Iop_64to32, cc_dep1), 990b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov unop(Iop_64to32, cc_dep2))); 991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondNLE)) { 994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* long sub/cmp, then NLE (signed greater than) 995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown --> test !(dst <=s src) 996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown --> test (dst >s src) 997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown --> test (src <s dst) */ 998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return unop(Iop_1Uto64, 999b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov binop(Iop_CmpLT32S, 1000b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov unop(Iop_64to32, cc_dep2), 1001b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov unop(Iop_64to32, cc_dep1))); 1002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondBE)) { 1006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* long sub/cmp, then BE (unsigned less than or equal) 1007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown --> test dst <=u src */ 1008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return unop(Iop_1Uto64, 1009b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov binop(Iop_CmpLE32U, 1010b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov unop(Iop_64to32, cc_dep1), 1011b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov unop(Iop_64to32, cc_dep2))); 1012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondNBE)) { 1014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* long sub/cmp, then NBE (unsigned greater than) 1015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown --> test src <u dst */ 1016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Note, args are opposite way round from the usual */ 1017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return unop(Iop_1Uto64, 1018b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov binop(Iop_CmpLT32U, 1019b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov unop(Iop_64to32, cc_dep2), 1020b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov unop(Iop_64to32, cc_dep1))); 1021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondS)) { 1024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* long sub/cmp, then S (negative) --> test (dst-src <s 0) */ 1025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return unop(Iop_1Uto64, 1026b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov binop(Iop_CmpLT32S, 1027b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov binop(Iop_Sub32, 1028b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov unop(Iop_64to32, cc_dep1), 1029b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov unop(Iop_64to32, cc_dep2)), 1030b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mkU32(0))); 1031b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1032b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1033b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondB)) { 1034b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* long sub/cmp, then B (unsigned less than) 1035b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov --> test dst <u src */ 1036b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return unop(Iop_1Uto64, 1037b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov binop(Iop_CmpLT32U, 1038b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov unop(Iop_64to32, cc_dep1), 1039b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov unop(Iop_64to32, cc_dep2))); 1040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*---------------- SUBW ----------------*/ 1043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isU64(cc_op, AMD64G_CC_OP_SUBW) && isU64(cond, AMD64CondZ)) { 1045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* word sub/cmp, then Z --> test dst==src */ 1046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return unop(Iop_1Uto64, 1047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_CmpEQ16, 1048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_64to16,cc_dep1), 1049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_64to16,cc_dep2))); 1050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isU64(cc_op, AMD64G_CC_OP_SUBW) && isU64(cond, AMD64CondNZ)) { 1052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* word sub/cmp, then NZ --> test dst!=src */ 1053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return unop(Iop_1Uto64, 1054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_CmpNE16, 1055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_64to16,cc_dep1), 1056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_64to16,cc_dep2))); 1057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isU64(cc_op, AMD64G_CC_OP_SUBW) && isU64(cond, AMD64CondLE)) { 1060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* word sub/cmp, then LE (signed less than or equal) 1061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown --> test dst <=s src */ 1062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return unop(Iop_1Uto64, 1063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_CmpLE64S, 1064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_Shl64,cc_dep1,mkU8(48)), 1065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_Shl64,cc_dep2,mkU8(48)))); 1066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*---------------- SUBB ----------------*/ 1070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isU64(cc_op, AMD64G_CC_OP_SUBB) && isU64(cond, AMD64CondZ)) { 1072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* byte sub/cmp, then Z --> test dst==src */ 1073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return unop(Iop_1Uto64, 1074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_CmpEQ8, 1075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_64to8,cc_dep1), 1076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_64to8,cc_dep2))); 1077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isU64(cc_op, AMD64G_CC_OP_SUBB) && isU64(cond, AMD64CondNZ)) { 1079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* byte sub/cmp, then NZ --> test dst!=src */ 1080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return unop(Iop_1Uto64, 1081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_CmpNE8, 1082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_64to8,cc_dep1), 1083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_64to8,cc_dep2))); 1084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1086b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (isU64(cc_op, AMD64G_CC_OP_SUBB) && isU64(cond, AMD64CondBE)) { 1087b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* byte sub/cmp, then BE (unsigned less than or equal) 1088b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov --> test dst <=u src */ 1089b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return unop(Iop_1Uto64, 1090b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov binop(Iop_CmpLE64U, 1091b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov binop(Iop_And64, cc_dep1, mkU64(0xFF)), 1092b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov binop(Iop_And64, cc_dep2, mkU64(0xFF)))); 1093b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1094b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isU64(cc_op, AMD64G_CC_OP_SUBB) && isU64(cond, AMD64CondS) 1096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && isU64(cc_dep2, 0)) { 1097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* byte sub/cmp of zero, then S --> test (dst-0 <s 0) 1098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown --> test dst <s 0 1099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown --> (ULong)dst[7] 1100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This is yet another scheme by which gcc figures out if the 1101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown top bit of a byte is 1 or 0. See also LOGICB/CondS below. */ 1102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Note: isU64(cc_dep2, 0) is correct, even though this is 1103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for an 8-bit comparison, since the args to the helper 1104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown function are always U64s. */ 1105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return binop(Iop_And64, 1106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_Shr64,cc_dep1,mkU8(7)), 1107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkU64(1)); 1108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isU64(cc_op, AMD64G_CC_OP_SUBB) && isU64(cond, AMD64CondNS) 1110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && isU64(cc_dep2, 0)) { 1111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* byte sub/cmp of zero, then NS --> test !(dst-0 <s 0) 1112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown --> test !(dst <s 0) 1113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown --> (ULong) !dst[7] 1114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 1115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return binop(Iop_Xor64, 1116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_And64, 1117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_Shr64,cc_dep1,mkU8(7)), 1118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkU64(1)), 1119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkU64(1)); 1120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*---------------- LOGICQ ----------------*/ 1123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isU64(cc_op, AMD64G_CC_OP_LOGICQ) && isU64(cond, AMD64CondZ)) { 1125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* long long and/or/xor, then Z --> test dst==0 */ 1126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return unop(Iop_1Uto64, 1127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_CmpEQ64, cc_dep1, mkU64(0))); 1128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1129b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (isU64(cc_op, AMD64G_CC_OP_LOGICQ) && isU64(cond, AMD64CondNZ)) { 1130b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* long long and/or/xor, then NZ --> test dst!=0 */ 1131b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return unop(Iop_1Uto64, 1132b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov binop(Iop_CmpNE64, cc_dep1, mkU64(0))); 1133b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isU64(cc_op, AMD64G_CC_OP_LOGICQ) && isU64(cond, AMD64CondL)) { 1136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* long long and/or/xor, then L 1137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown LOGIC sets SF and ZF according to the 1138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown result and makes OF be zero. L computes SF ^ OF, but 1139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OF is zero, so this reduces to SF -- which will be 1 iff 1140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the result is < signed 0. Hence ... 1141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 1142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return unop(Iop_1Uto64, 1143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_CmpLT64S, 1144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cc_dep1, 1145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkU64(0))); 1146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*---------------- LOGICL ----------------*/ 1149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isU64(cc_op, AMD64G_CC_OP_LOGICL) && isU64(cond, AMD64CondZ)) { 1151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* long and/or/xor, then Z --> test dst==0 */ 1152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return unop(Iop_1Uto64, 1153b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov binop(Iop_CmpEQ32, 1154b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov unop(Iop_64to32, cc_dep1), 1155b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mkU32(0))); 1156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isU64(cc_op, AMD64G_CC_OP_LOGICL) && isU64(cond, AMD64CondNZ)) { 1158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* long and/or/xor, then NZ --> test dst!=0 */ 1159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return unop(Iop_1Uto64, 1160b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov binop(Iop_CmpNE32, 1161b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov unop(Iop_64to32, cc_dep1), 1162b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mkU32(0))); 1163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isU64(cc_op, AMD64G_CC_OP_LOGICL) && isU64(cond, AMD64CondLE)) { 1166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* long and/or/xor, then LE 1167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This is pretty subtle. LOGIC sets SF and ZF according to the 1168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown result and makes OF be zero. LE computes (SF ^ OF) | ZF, but 1169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OF is zero, so this reduces to SF | ZF -- which will be 1 iff 1170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the result is <=signed 0. Hence ... 1171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 1172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return unop(Iop_1Uto64, 1173b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov binop(Iop_CmpLE32S, 1174b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov unop(Iop_64to32, cc_dep1), 1175b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mkU32(0))); 1176b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1177b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1178b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (isU64(cc_op, AMD64G_CC_OP_LOGICL) && isU64(cond, AMD64CondS)) { 1179b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* long and/or/xor, then S --> (ULong)result[31] */ 1180b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return binop(Iop_And64, 1181b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov binop(Iop_Shr64, cc_dep1, mkU8(31)), 1182b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mkU64(1)); 1183b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1184b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (isU64(cc_op, AMD64G_CC_OP_LOGICL) && isU64(cond, AMD64CondNS)) { 1185b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* long and/or/xor, then S --> (ULong) ~ result[31] */ 1186b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return binop(Iop_Xor64, 1187b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov binop(Iop_And64, 1188b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov binop(Iop_Shr64, cc_dep1, mkU8(31)), 1189b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mkU64(1)), 1190b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mkU64(1)); 1191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*---------------- LOGICB ----------------*/ 1194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isU64(cc_op, AMD64G_CC_OP_LOGICB) && isU64(cond, AMD64CondZ)) { 1196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* byte and/or/xor, then Z --> test dst==0 */ 1197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return unop(Iop_1Uto64, 1198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_CmpEQ64, binop(Iop_And64,cc_dep1,mkU64(255)), 1199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkU64(0))); 1200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isU64(cc_op, AMD64G_CC_OP_LOGICB) && isU64(cond, AMD64CondNZ)) { 1202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* byte and/or/xor, then NZ --> test dst!=0 */ 1203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return unop(Iop_1Uto64, 1204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_CmpNE64, binop(Iop_And64,cc_dep1,mkU64(255)), 1205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkU64(0))); 1206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isU64(cc_op, AMD64G_CC_OP_LOGICB) && isU64(cond, AMD64CondS)) { 1209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* this is an idiom gcc sometimes uses to find out if the top 1210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bit of a byte register is set: eg testb %al,%al; js .. 1211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Since it just depends on the top bit of the byte, extract 1212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown that bit and explicitly get rid of all the rest. This 1213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown helps memcheck avoid false positives in the case where any 1214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of the other bits in the byte are undefined. */ 1215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* byte and/or/xor, then S --> (UInt)result[7] */ 1216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return binop(Iop_And64, 1217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_Shr64,cc_dep1,mkU8(7)), 1218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkU64(1)); 1219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1220b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (isU64(cc_op, AMD64G_CC_OP_LOGICB) && isU64(cond, AMD64CondNS)) { 1221b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* byte and/or/xor, then NS --> (UInt)!result[7] */ 1222b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return binop(Iop_Xor64, 1223b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov binop(Iop_And64, 1224b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov binop(Iop_Shr64,cc_dep1,mkU8(7)), 1225b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mkU64(1)), 1226b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mkU64(1)); 1227b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*---------------- INCB ----------------*/ 1230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isU64(cc_op, AMD64G_CC_OP_INCB) && isU64(cond, AMD64CondLE)) { 1232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 8-bit inc, then LE --> sign bit of the arg */ 1233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return binop(Iop_And64, 1234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_Shr64, 1235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_Sub64, cc_dep1, mkU64(1)), 1236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkU8(7)), 1237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkU64(1)); 1238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*---------------- INCW ----------------*/ 1241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isU64(cc_op, AMD64G_CC_OP_INCW) && isU64(cond, AMD64CondZ)) { 1243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 16-bit inc, then Z --> test dst == 0 */ 1244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return unop(Iop_1Uto64, 1245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_CmpEQ64, 1246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_Shl64,cc_dep1,mkU8(48)), 1247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkU64(0))); 1248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*---------------- DECL ----------------*/ 1251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isU64(cc_op, AMD64G_CC_OP_DECL) && isU64(cond, AMD64CondZ)) { 1253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* dec L, then Z --> test dst == 0 */ 1254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return unop(Iop_1Uto64, 1255b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov binop(Iop_CmpEQ32, 1256b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov unop(Iop_64to32, cc_dep1), 1257b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mkU32(0))); 1258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*---------------- DECW ----------------*/ 1261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isU64(cc_op, AMD64G_CC_OP_DECW) && isU64(cond, AMD64CondNZ)) { 1263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 16-bit dec, then NZ --> test dst != 0 */ 1264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return unop(Iop_1Uto64, 1265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_CmpNE64, 1266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_Shl64,cc_dep1,mkU8(48)), 1267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkU64(0))); 1268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*---------------- COPY ----------------*/ 1271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* This can happen, as a result of amd64 FP compares: "comisd ... ; 1272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown jbe" for example. */ 1273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isU64(cc_op, AMD64G_CC_OP_COPY) && 1275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (isU64(cond, AMD64CondBE) || isU64(cond, AMD64CondNBE))) { 1276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* COPY, then BE --> extract C and Z from dep1, and test (C 1277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown or Z == 1). */ 1278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* COPY, then NBE --> extract C and Z from dep1, and test (C 1279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown or Z == 0). */ 1280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong nnn = isU64(cond, AMD64CondBE) ? 1 : 0; 1281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 1282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop( 1283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Iop_1Uto64, 1284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop( 1285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Iop_CmpEQ64, 1286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop( 1287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Iop_And64, 1288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop( 1289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Iop_Or64, 1290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_Shr64, cc_dep1, mkU8(AMD64G_CC_SHIFT_C)), 1291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_Shr64, cc_dep1, mkU8(AMD64G_CC_SHIFT_Z)) 1292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ), 1293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkU64(1) 1294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ), 1295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkU64(nnn) 1296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ) 1297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 1298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isU64(cc_op, AMD64G_CC_OP_COPY) && isU64(cond, AMD64CondB)) { 1301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* COPY, then B --> extract C dep1, and test (C == 1). */ 1302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 1303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop( 1304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Iop_1Uto64, 1305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop( 1306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Iop_CmpNE64, 1307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop( 1308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Iop_And64, 1309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_Shr64, cc_dep1, mkU8(AMD64G_CC_SHIFT_C)), 1310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkU64(1) 1311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ), 1312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkU64(0) 1313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ) 1314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 1315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isU64(cc_op, AMD64G_CC_OP_COPY) 1318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && (isU64(cond, AMD64CondZ) || isU64(cond, AMD64CondNZ))) { 1319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* COPY, then Z --> extract Z from dep1, and test (Z == 1). */ 1320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* COPY, then NZ --> extract Z from dep1, and test (Z == 0). */ 1321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt nnn = isU64(cond, AMD64CondZ) ? 1 : 0; 1322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 1323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop( 1324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Iop_1Uto64, 1325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop( 1326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Iop_CmpEQ64, 1327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop( 1328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Iop_And64, 1329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_Shr64, cc_dep1, mkU8(AMD64G_CC_SHIFT_Z)), 1330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkU64(1) 1331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ), 1332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkU64(nnn) 1333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ) 1334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 1335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isU64(cc_op, AMD64G_CC_OP_COPY) && isU64(cond, AMD64CondP)) { 1338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* COPY, then P --> extract P from dep1, and test (P == 1). */ 1339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 1340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop( 1341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Iop_1Uto64, 1342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop( 1343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Iop_CmpNE64, 1344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop( 1345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Iop_And64, 1346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_Shr64, cc_dep1, mkU8(AMD64G_CC_SHIFT_P)), 1347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkU64(1) 1348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ), 1349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkU64(0) 1350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ) 1351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 1352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return NULL; 1355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- specialising "amd64g_calculate_rflags_c" --------- */ 1358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (vex_streq(function_name, "amd64g_calculate_rflags_c")) { 1360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* specialise calls to above "calculate_rflags_c" function */ 1361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr *cc_op, *cc_dep1, *cc_dep2, *cc_ndep; 1362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(arity == 4); 1363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cc_op = args[0]; 1364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cc_dep1 = args[1]; 1365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cc_dep2 = args[2]; 1366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cc_ndep = args[3]; 1367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isU64(cc_op, AMD64G_CC_OP_SUBQ)) { 1369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* C after sub denotes unsigned less than */ 1370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return unop(Iop_1Uto64, 1371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_CmpLT64U, 1372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cc_dep1, 1373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cc_dep2)); 1374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isU64(cc_op, AMD64G_CC_OP_SUBL)) { 1376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* C after sub denotes unsigned less than */ 1377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return unop(Iop_1Uto64, 1378b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov binop(Iop_CmpLT32U, 1379b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov unop(Iop_64to32, cc_dep1), 1380b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov unop(Iop_64to32, cc_dep2))); 1381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isU64(cc_op, AMD64G_CC_OP_SUBB)) { 1383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* C after sub denotes unsigned less than */ 1384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return unop(Iop_1Uto64, 1385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_CmpLT64U, 1386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_And64,cc_dep1,mkU64(0xFF)), 1387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_And64,cc_dep2,mkU64(0xFF)))); 1388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isU64(cc_op, AMD64G_CC_OP_LOGICQ) 1390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || isU64(cc_op, AMD64G_CC_OP_LOGICL) 1391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || isU64(cc_op, AMD64G_CC_OP_LOGICW) 1392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || isU64(cc_op, AMD64G_CC_OP_LOGICB)) { 1393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* cflag after logic is zero */ 1394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return mkU64(0); 1395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isU64(cc_op, AMD64G_CC_OP_DECL) || isU64(cc_op, AMD64G_CC_OP_INCL) 1397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || isU64(cc_op, AMD64G_CC_OP_DECQ) || isU64(cc_op, AMD64G_CC_OP_INCQ)) { 1398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If the thunk is dec or inc, the cflag is supplied as CC_NDEP. */ 1399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return cc_ndep; 1400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if 0 1403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (cc_op->tag == Iex_Const) { 1404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_printf("CFLAG "); ppIRExpr(cc_op); vex_printf("\n"); 1405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return NULL; 1409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# undef unop 1412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# undef binop 1413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# undef mkU64 1414b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# undef mkU32 1415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# undef mkU8 1416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return NULL; 1418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/ 1422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Supporting functions for x87 FPU activities. ---*/ 1423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/ 1424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline Bool host_is_little_endian ( void ) 1426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt x = 0x76543210; 1428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar* p = (UChar*)(&x); 1429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return toBool(*p == 0x10); 1430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Inspect a value and its tag, as per the x87 'FXAM' instruction. */ 1433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CALLED FROM GENERATED CODE: CLEAN HELPER */ 1434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong amd64g_calculate_FXAM ( ULong tag, ULong dbl ) 1435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool mantissaIsZero; 1437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int bexp; 1438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar sign; 1439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar* f64; 1440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(host_is_little_endian()); 1442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* vex_printf("calculate_FXAM ( %d, %llx ) .. ", tag, dbl ); */ 1444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown f64 = (UChar*)(&dbl); 1446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sign = toUChar( (f64[7] >> 7) & 1 ); 1447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* First off, if the tag indicates the register was empty, 1449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 1,0,sign,1 */ 1450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tag == 0) { 1451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* vex_printf("Empty\n"); */ 1452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return AMD64G_FC_MASK_C3 | 0 | (sign << AMD64G_FC_SHIFT_C1) 1453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown | AMD64G_FC_MASK_C0; 1454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bexp = (f64[7] << 4) | ((f64[6] >> 4) & 0x0F); 1457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bexp &= 0x7FF; 1458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mantissaIsZero 1460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = toBool( 1461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (f64[6] & 0x0F) == 0 1462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && (f64[5] | f64[4] | f64[3] | f64[2] | f64[1] | f64[0]) == 0 1463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 1464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If both exponent and mantissa are zero, the value is zero. 1466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Return 1,0,sign,0. */ 1467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (bexp == 0 && mantissaIsZero) { 1468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* vex_printf("Zero\n"); */ 1469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return AMD64G_FC_MASK_C3 | 0 1470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown | (sign << AMD64G_FC_SHIFT_C1) | 0; 1471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If exponent is zero but mantissa isn't, it's a denormal. 1474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Return 1,1,sign,0. */ 1475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (bexp == 0 && !mantissaIsZero) { 1476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* vex_printf("Denormal\n"); */ 1477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return AMD64G_FC_MASK_C3 | AMD64G_FC_MASK_C2 1478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown | (sign << AMD64G_FC_SHIFT_C1) | 0; 1479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If the exponent is 7FF and the mantissa is zero, this is an infinity. 1482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Return 0,1,sign,1. */ 1483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (bexp == 0x7FF && mantissaIsZero) { 1484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* vex_printf("Inf\n"); */ 1485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0 | AMD64G_FC_MASK_C2 | (sign << AMD64G_FC_SHIFT_C1) 1486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown | AMD64G_FC_MASK_C0; 1487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If the exponent is 7FF and the mantissa isn't zero, this is a NaN. 1490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Return 0,0,sign,1. */ 1491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (bexp == 0x7FF && !mantissaIsZero) { 1492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* vex_printf("NaN\n"); */ 1493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0 | 0 | (sign << AMD64G_FC_SHIFT_C1) | AMD64G_FC_MASK_C0; 1494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Uh, ok, we give up. It must be a normal finite number. 1497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Return 0,1,sign,0. 1498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 1499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* vex_printf("normal\n"); */ 1500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0 | AMD64G_FC_MASK_C2 | (sign << AMD64G_FC_SHIFT_C1) | 0; 1501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1504f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root/* This is used to implement both 'frstor' and 'fldenv'. The latter 1505f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root appears to differ from the former only in that the 8 FP registers 1506f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root themselves are not transferred into the guest state. */ 1507f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Rootstatic 1508f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny RootVexEmWarn do_put_x87 ( Bool moveRegs, 1509f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root /*IN*/UChar* x87_state, 1510f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root /*OUT*/VexGuestAMD64State* vex_state ) 1511f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root{ 1512f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root Int stno, preg; 1513f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root UInt tag; 1514f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root ULong* vexRegs = (ULong*)(&vex_state->guest_FPREG[0]); 1515f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root UChar* vexTags = (UChar*)(&vex_state->guest_FPTAG[0]); 1516f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root Fpu_State* x87 = (Fpu_State*)x87_state; 1517f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root UInt ftop = (x87->env[FP_ENV_STAT] >> 11) & 7; 1518f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root UInt tagw = x87->env[FP_ENV_TAG]; 1519f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root UInt fpucw = x87->env[FP_ENV_CTRL]; 1520f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root UInt c3210 = x87->env[FP_ENV_STAT] & 0x4700; 1521f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root VexEmWarn ew; 1522f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root UInt fpround; 1523f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root ULong pair; 1524f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root 1525f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root /* Copy registers and tags */ 1526f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root for (stno = 0; stno < 8; stno++) { 1527f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root preg = (stno + ftop) & 7; 1528f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root tag = (tagw >> (2*preg)) & 3; 1529f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root if (tag == 3) { 1530f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root /* register is empty */ 1531f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root /* hmm, if it's empty, does it still get written? Probably 1532f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root safer to say it does. If we don't, memcheck could get out 1533f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root of sync, in that it thinks all FP registers are defined by 1534f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root this helper, but in reality some have not been updated. */ 1535f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root if (moveRegs) 1536f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root vexRegs[preg] = 0; /* IEEE754 64-bit zero */ 1537f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root vexTags[preg] = 0; 1538f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root } else { 1539f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root /* register is non-empty */ 1540f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root if (moveRegs) 1541f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root convert_f80le_to_f64le( &x87->reg[10*stno], 1542f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root (UChar*)&vexRegs[preg] ); 1543f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root vexTags[preg] = 1; 1544f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root } 1545f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root } 1546f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root 1547f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root /* stack pointer */ 1548f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root vex_state->guest_FTOP = ftop; 1549f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root 1550f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root /* status word */ 1551f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root vex_state->guest_FC3210 = c3210; 1552f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root 1553f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root /* handle the control word, setting FPROUND and detecting any 1554f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root emulation warnings. */ 1555f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root pair = amd64g_check_fldcw ( (ULong)fpucw ); 1556f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root fpround = (UInt)pair; 1557f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root ew = (VexEmWarn)(pair >> 32); 1558f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root 1559f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root vex_state->guest_FPROUND = fpround & 3; 1560f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root 1561f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root /* emulation warnings --> caller */ 1562f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root return ew; 1563f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root} 1564f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root 1565f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root 1566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Create an x87 FPU state from the guest state, as close as 1567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown we can approximate it. */ 1568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 1569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid do_get_x87 ( /*IN*/VexGuestAMD64State* vex_state, 1570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*OUT*/UChar* x87_state ) 1571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i, stno, preg; 1573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt tagw; 1574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong* vexRegs = (ULong*)(&vex_state->guest_FPREG[0]); 1575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar* vexTags = (UChar*)(&vex_state->guest_FPTAG[0]); 1576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Fpu_State* x87 = (Fpu_State*)x87_state; 1577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt ftop = vex_state->guest_FTOP; 1578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt c3210 = vex_state->guest_FC3210; 1579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < 14; i++) 1581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown x87->env[i] = 0; 1582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown x87->env[1] = x87->env[3] = x87->env[5] = x87->env[13] = 0xFFFF; 1584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown x87->env[FP_ENV_STAT] 1585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = toUShort(((ftop & 7) << 11) | (c3210 & 0x4700)); 1586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown x87->env[FP_ENV_CTRL] 1587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = toUShort(amd64g_create_fpucw( vex_state->guest_FPROUND )); 1588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Dump the register stack in ST order. */ 1590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tagw = 0; 1591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (stno = 0; stno < 8; stno++) { 1592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown preg = (stno + ftop) & 7; 1593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (vexTags[preg] == 0) { 1594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* register is empty */ 1595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tagw |= (3 << (2*preg)); 1596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown convert_f64le_to_f80le( (UChar*)&vexRegs[preg], 1597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown &x87->reg[10*stno] ); 1598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* register is full. */ 1600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tagw |= (0 << (2*preg)); 1601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown convert_f64le_to_f80le( (UChar*)&vexRegs[preg], 1602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown &x87->reg[10*stno] ); 1603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown x87->env[FP_ENV_TAG] = toUShort(tagw); 1606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CALLED FROM GENERATED CODE */ 1610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DIRTY HELPER (reads guest state, writes guest mem) */ 1611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* NOTE: only handles 32-bit format (no REX.W on the insn) */ 1612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid amd64g_dirtyhelper_FXSAVE ( VexGuestAMD64State* gst, HWord addr ) 1613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Derived from values obtained from 1615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vendor_id : AuthenticAMD 1616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cpu family : 15 1617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown model : 12 1618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown model name : AMD Athlon(tm) 64 Processor 3200+ 1619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stepping : 0 1620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cpu MHz : 2200.000 1621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cache size : 512 KB 1622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 1623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Somewhat roundabout, but at least it's simple. */ 1624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Fpu_State tmp; 1625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UShort* addrS = (UShort*)addr; 1626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar* addrC = (UChar*)addr; 1627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown U128* xmm = (U128*)(addr + 160); 1628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt mxcsr; 1629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UShort fp_tags; 1630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt summary_tags; 1631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int r, stno; 1632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UShort *srcS, *dstS; 1633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do_get_x87( gst, (UChar*)&tmp ); 1635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mxcsr = amd64g_create_mxcsr( gst->guest_SSEROUND ); 1636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Now build the proper fxsave image from the x87 image we just 1638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown made. */ 1639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addrS[0] = tmp.env[FP_ENV_CTRL]; /* FCW: fpu control word */ 1641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addrS[1] = tmp.env[FP_ENV_STAT]; /* FCW: fpu status word */ 1642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* set addrS[2] in an endian-independent way */ 1644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown summary_tags = 0; 1645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fp_tags = tmp.env[FP_ENV_TAG]; 1646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (r = 0; r < 8; r++) { 1647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ( ((fp_tags >> (2*r)) & 3) != 3 ) 1648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown summary_tags |= (1 << r); 1649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addrC[4] = toUChar(summary_tags); /* FTW: tag summary byte */ 1651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addrC[5] = 0; /* pad */ 1652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* FOP: faulting fpu opcode. From experimentation, the real CPU 1654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown does not write this field. (?!) */ 1655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addrS[3] = 0; /* BOGUS */ 1656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* RIP (Last x87 instruction pointer). From experimentation, the 1658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown real CPU does not write this field. (?!) */ 1659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addrS[4] = 0; /* BOGUS */ 1660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addrS[5] = 0; /* BOGUS */ 1661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addrS[6] = 0; /* BOGUS */ 1662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addrS[7] = 0; /* BOGUS */ 1663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* RDP (Last x87 data pointer). From experimentation, the real CPU 1665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown does not write this field. (?!) */ 1666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addrS[8] = 0; /* BOGUS */ 1667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addrS[9] = 0; /* BOGUS */ 1668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addrS[10] = 0; /* BOGUS */ 1669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addrS[11] = 0; /* BOGUS */ 1670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addrS[12] = toUShort(mxcsr); /* MXCSR */ 1672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addrS[13] = toUShort(mxcsr >> 16); 1673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addrS[14] = 0xFFFF; /* MXCSR mask (lo16) */ 1675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addrS[15] = 0x0000; /* MXCSR mask (hi16) */ 1676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Copy in the FP registers, in ST order. */ 1678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (stno = 0; stno < 8; stno++) { 1679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown srcS = (UShort*)(&tmp.reg[10*stno]); 1680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dstS = (UShort*)(&addrS[16 + 8*stno]); 1681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dstS[0] = srcS[0]; 1682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dstS[1] = srcS[1]; 1683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dstS[2] = srcS[2]; 1684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dstS[3] = srcS[3]; 1685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dstS[4] = srcS[4]; 1686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dstS[5] = 0; 1687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dstS[6] = 0; 1688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dstS[7] = 0; 1689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* That's the first 160 bytes of the image done. Now only %xmm0 1692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown .. %xmm15 remain to be copied. If the host is big-endian, these 1693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown need to be byte-swapped. */ 1694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(host_is_little_endian()); 1695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define COPY_U128(_dst,_src) \ 1697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do { _dst[0] = _src[0]; _dst[1] = _src[1]; \ 1698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown _dst[2] = _src[2]; _dst[3] = _src[3]; } \ 1699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (0) 1700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown COPY_U128( xmm[0], gst->guest_XMM0 ); 1702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown COPY_U128( xmm[1], gst->guest_XMM1 ); 1703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown COPY_U128( xmm[2], gst->guest_XMM2 ); 1704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown COPY_U128( xmm[3], gst->guest_XMM3 ); 1705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown COPY_U128( xmm[4], gst->guest_XMM4 ); 1706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown COPY_U128( xmm[5], gst->guest_XMM5 ); 1707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown COPY_U128( xmm[6], gst->guest_XMM6 ); 1708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown COPY_U128( xmm[7], gst->guest_XMM7 ); 1709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown COPY_U128( xmm[8], gst->guest_XMM8 ); 1710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown COPY_U128( xmm[9], gst->guest_XMM9 ); 1711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown COPY_U128( xmm[10], gst->guest_XMM10 ); 1712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown COPY_U128( xmm[11], gst->guest_XMM11 ); 1713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown COPY_U128( xmm[12], gst->guest_XMM12 ); 1714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown COPY_U128( xmm[13], gst->guest_XMM13 ); 1715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown COPY_U128( xmm[14], gst->guest_XMM14 ); 1716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown COPY_U128( xmm[15], gst->guest_XMM15 ); 1717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# undef COPY_U128 1719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1722f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root/* CALLED FROM GENERATED CODE */ 1723f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root/* DIRTY HELPER (writes guest state, reads guest mem) */ 1724f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny RootVexEmWarn amd64g_dirtyhelper_FXRSTOR ( VexGuestAMD64State* gst, HWord addr ) 1725f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root{ 1726f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root Fpu_State tmp; 1727f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root VexEmWarn warnX87 = EmWarn_NONE; 1728f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root VexEmWarn warnXMM = EmWarn_NONE; 1729f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root UShort* addrS = (UShort*)addr; 1730f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root UChar* addrC = (UChar*)addr; 1731f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root U128* xmm = (U128*)(addr + 160); 1732f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root UShort fp_tags; 1733f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root Int r, stno, i; 1734f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root 1735f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root /* Restore %xmm0 .. %xmm15. If the host is big-endian, these need 1736f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root to be byte-swapped. */ 1737f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root vassert(host_is_little_endian()); 1738f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root 1739f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root# define COPY_U128(_dst,_src) \ 1740f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root do { _dst[0] = _src[0]; _dst[1] = _src[1]; \ 1741f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root _dst[2] = _src[2]; _dst[3] = _src[3]; } \ 1742f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root while (0) 1743f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root 1744f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root COPY_U128( gst->guest_XMM0, xmm[0] ); 1745f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root COPY_U128( gst->guest_XMM1, xmm[1] ); 1746f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root COPY_U128( gst->guest_XMM2, xmm[2] ); 1747f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root COPY_U128( gst->guest_XMM3, xmm[3] ); 1748f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root COPY_U128( gst->guest_XMM4, xmm[4] ); 1749f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root COPY_U128( gst->guest_XMM5, xmm[5] ); 1750f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root COPY_U128( gst->guest_XMM6, xmm[6] ); 1751f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root COPY_U128( gst->guest_XMM7, xmm[7] ); 1752f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root COPY_U128( gst->guest_XMM8, xmm[8] ); 1753f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root COPY_U128( gst->guest_XMM9, xmm[9] ); 1754f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root COPY_U128( gst->guest_XMM10, xmm[10] ); 1755f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root COPY_U128( gst->guest_XMM11, xmm[11] ); 1756f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root COPY_U128( gst->guest_XMM12, xmm[12] ); 1757f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root COPY_U128( gst->guest_XMM13, xmm[13] ); 1758f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root COPY_U128( gst->guest_XMM14, xmm[14] ); 1759f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root COPY_U128( gst->guest_XMM15, xmm[15] ); 1760f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root 1761f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root# undef COPY_U128 1762f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root 1763f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root /* Copy the x87 registers out of the image, into a temporary 1764f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root Fpu_State struct. */ 1765f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root for (i = 0; i < 14; i++) tmp.env[i] = 0; 1766f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root for (i = 0; i < 80; i++) tmp.reg[i] = 0; 1767f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root /* fill in tmp.reg[0..7] */ 1768f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root for (stno = 0; stno < 8; stno++) { 1769f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root UShort* dstS = (UShort*)(&tmp.reg[10*stno]); 1770f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root UShort* srcS = (UShort*)(&addrS[16 + 8*stno]); 1771f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root dstS[0] = srcS[0]; 1772f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root dstS[1] = srcS[1]; 1773f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root dstS[2] = srcS[2]; 1774f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root dstS[3] = srcS[3]; 1775f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root dstS[4] = srcS[4]; 1776f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root } 1777f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root /* fill in tmp.env[0..13] */ 1778f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root tmp.env[FP_ENV_CTRL] = addrS[0]; /* FCW: fpu control word */ 1779f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root tmp.env[FP_ENV_STAT] = addrS[1]; /* FCW: fpu status word */ 1780f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root 1781f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root fp_tags = 0; 1782f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root for (r = 0; r < 8; r++) { 1783f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root if (addrC[4] & (1<<r)) 1784f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root fp_tags |= (0 << (2*r)); /* EMPTY */ 1785f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root else 1786f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root fp_tags |= (3 << (2*r)); /* VALID -- not really precise enough. */ 1787f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root } 1788f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root tmp.env[FP_ENV_TAG] = fp_tags; 1789f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root 1790f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root /* Now write 'tmp' into the guest state. */ 1791f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root warnX87 = do_put_x87( True/*moveRegs*/, (UChar*)&tmp, gst ); 1792f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root 1793f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root { UInt w32 = (((UInt)addrS[12]) & 0xFFFF) 1794f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root | ((((UInt)addrS[13]) & 0xFFFF) << 16); 1795f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root ULong w64 = amd64g_check_ldmxcsr( (ULong)w32 ); 1796f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root 1797f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root warnXMM = (VexEmWarn)(w64 >> 32); 1798f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root 1799f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root gst->guest_SSEROUND = w64 & 0xFFFFFFFFULL; 1800f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root } 1801f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root 1802f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root /* Prefer an X87 emwarn over an XMM one, if both exist. */ 1803f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root if (warnX87 != EmWarn_NONE) 1804f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root return warnX87; 1805f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root else 1806f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root return warnXMM; 1807f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root} 1808f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root 1809f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root 1810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DIRTY HELPER (writes guest state) */ 1811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Initialise the x87 FPU state as per 'finit'. */ 1812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid amd64g_dirtyhelper_FINIT ( VexGuestAMD64State* gst ) 1813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i; 1815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_FTOP = 0; 1816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < 8; i++) { 1817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_FPTAG[i] = 0; /* empty */ 1818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_FPREG[i] = 0; /* IEEE754 64-bit zero */ 1819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_FPROUND = (ULong)Irrm_NEAREST; 1821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_FC3210 = 0; 1822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CALLED FROM GENERATED CODE */ 1826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DIRTY HELPER (reads guest memory) */ 1827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong amd64g_dirtyhelper_loadF80le ( ULong addrU ) 1828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong f64; 1830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown convert_f80le_to_f64le ( (UChar*)ULong_to_Ptr(addrU), (UChar*)&f64 ); 1831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return f64; 1832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CALLED FROM GENERATED CODE */ 1835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DIRTY HELPER (writes guest memory) */ 1836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid amd64g_dirtyhelper_storeF80le ( ULong addrU, ULong f64 ) 1837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown convert_f64le_to_f80le( (UChar*)&f64, (UChar*)ULong_to_Ptr(addrU) ); 1839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CALLED FROM GENERATED CODE */ 1843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CLEAN HELPER */ 1844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* mxcsr[15:0] contains a SSE native format MXCSR value. 1845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Extract from it the required SSEROUND value and any resulting 1846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emulation warning, and return (warn << 32) | sseround value. 1847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 1848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong amd64g_check_ldmxcsr ( ULong mxcsr ) 1849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Decide on a rounding mode. mxcsr[14:13] holds it. */ 1851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* NOTE, encoded exactly as per enum IRRoundingMode. */ 1852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong rmode = (mxcsr >> 13) & 3; 1853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Detect any required emulation warnings. */ 1855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexEmWarn ew = EmWarn_NONE; 1856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ((mxcsr & 0x1F80) != 0x1F80) { 1858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* unmasked exceptions! */ 1859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ew = EmWarn_X86_sseExns; 1860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 1862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (mxcsr & (1<<15)) { 1863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* FZ is set */ 1864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ew = EmWarn_X86_fz; 1865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 1867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (mxcsr & (1<<6)) { 1868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* DAZ is set */ 1869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ew = EmWarn_X86_daz; 1870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return (((ULong)ew) << 32) | ((ULong)rmode); 1873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CALLED FROM GENERATED CODE */ 1877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CLEAN HELPER */ 1878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Given sseround as an IRRoundingMode value, create a suitable SSE 1879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown native format MXCSR value. */ 1880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong amd64g_create_mxcsr ( ULong sseround ) 1881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sseround &= 3; 1883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0x1F80 | (sseround << 13); 1884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CLEAN HELPER */ 1888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* fpucw[15:0] contains a x87 native format FPU control word. 1889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Extract from it the required FPROUND value and any resulting 1890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emulation warning, and return (warn << 32) | fpround value. 1891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 1892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong amd64g_check_fldcw ( ULong fpucw ) 1893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Decide on a rounding mode. fpucw[11:10] holds it. */ 1895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* NOTE, encoded exactly as per enum IRRoundingMode. */ 1896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong rmode = (fpucw >> 10) & 3; 1897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Detect any required emulation warnings. */ 1899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexEmWarn ew = EmWarn_NONE; 1900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ((fpucw & 0x3F) != 0x3F) { 1902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* unmasked exceptions! */ 1903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ew = EmWarn_X86_x87exns; 1904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 1906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (((fpucw >> 8) & 3) != 3) { 1907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* unsupported precision */ 1908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ew = EmWarn_X86_x87precision; 1909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return (((ULong)ew) << 32) | ((ULong)rmode); 1912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CLEAN HELPER */ 1916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Given fpround as an IRRoundingMode value, create a suitable x87 1917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown native format FPU control word. */ 1918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong amd64g_create_fpucw ( ULong fpround ) 1919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fpround &= 3; 1921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0x037F | (fpround << 10); 1922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This is used to implement 'fldenv'. 1926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Reads 28 bytes at x87_state[0 .. 27]. */ 1927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CALLED FROM GENERATED CODE */ 1928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DIRTY HELPER */ 1929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownVexEmWarn amd64g_dirtyhelper_FLDENV ( /*OUT*/VexGuestAMD64State* vex_state, 1930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*IN*/HWord x87_state) 1931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int stno, preg; 1933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt tag; 1934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar* vexTags = (UChar*)(&vex_state->guest_FPTAG[0]); 1935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Fpu_State* x87 = (Fpu_State*)x87_state; 1936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt ftop = (x87->env[FP_ENV_STAT] >> 11) & 7; 1937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt tagw = x87->env[FP_ENV_TAG]; 1938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt fpucw = x87->env[FP_ENV_CTRL]; 1939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong c3210 = x87->env[FP_ENV_STAT] & 0x4700; 1940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexEmWarn ew; 1941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong fpround; 1942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong pair; 1943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Copy tags */ 1945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (stno = 0; stno < 8; stno++) { 1946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown preg = (stno + ftop) & 7; 1947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tag = (tagw >> (2*preg)) & 3; 1948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tag == 3) { 1949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* register is empty */ 1950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vexTags[preg] = 0; 1951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* register is non-empty */ 1953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vexTags[preg] = 1; 1954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* stack pointer */ 1958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_state->guest_FTOP = ftop; 1959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* status word */ 1961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_state->guest_FC3210 = c3210; 1962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* handle the control word, setting FPROUND and detecting any 1964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emulation warnings. */ 1965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pair = amd64g_check_fldcw ( (ULong)fpucw ); 1966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fpround = pair & 0xFFFFFFFFULL; 1967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ew = (VexEmWarn)(pair >> 32); 1968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_state->guest_FPROUND = fpround & 3; 1970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* emulation warnings --> caller */ 1972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ew; 1973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CALLED FROM GENERATED CODE */ 1977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DIRTY HELPER */ 1978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Create an x87 FPU env from the guest state, as close as we can 1979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown approximate it. Writes 28 bytes at x87_state[0..27]. */ 1980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid amd64g_dirtyhelper_FSTENV ( /*IN*/VexGuestAMD64State* vex_state, 1981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*OUT*/HWord x87_state ) 1982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i, stno, preg; 1984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt tagw; 1985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar* vexTags = (UChar*)(&vex_state->guest_FPTAG[0]); 1986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Fpu_State* x87 = (Fpu_State*)x87_state; 1987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt ftop = vex_state->guest_FTOP; 1988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong c3210 = vex_state->guest_FC3210; 1989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < 14; i++) 1991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown x87->env[i] = 0; 1992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown x87->env[1] = x87->env[3] = x87->env[5] = x87->env[13] = 0xFFFF; 1994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown x87->env[FP_ENV_STAT] 1995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = toUShort(toUInt( ((ftop & 7) << 11) | (c3210 & 0x4700) )); 1996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown x87->env[FP_ENV_CTRL] 1997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = toUShort(toUInt( amd64g_create_fpucw( vex_state->guest_FPROUND ) )); 1998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Compute the x87 tag word. */ 2000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tagw = 0; 2001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (stno = 0; stno < 8; stno++) { 2002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown preg = (stno + ftop) & 7; 2003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (vexTags[preg] == 0) { 2004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* register is empty */ 2005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tagw |= (3 << (2*preg)); 2006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 2007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* register is full. */ 2008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tagw |= (0 << (2*preg)); 2009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown x87->env[FP_ENV_TAG] = toUShort(tagw); 2012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* We don't dump the x87 registers, tho. */ 2014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/ 2018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Misc integer helpers, including rotates and CPUID. ---*/ 2019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/ 2020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Claim to be the following CPU, which is probably representative of 2022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the lowliest (earliest) amd64 offerings. It can do neither sse3 2023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nor cx16. 2024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vendor_id : AuthenticAMD 2026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cpu family : 15 2027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown model : 5 2028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown model name : AMD Opteron (tm) Processor 848 2029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stepping : 10 2030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cpu MHz : 1797.682 2031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cache size : 1024 KB 2032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fpu : yes 2033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fpu_exception : yes 2034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cpuid level : 1 2035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown wp : yes 2036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown flags : fpu vme de pse tsc msr pae mce cx8 apic sep 2037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mtrr pge mca cmov pat pse36 clflush mmx fxsr 2038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sse sse2 syscall nx mmxext lm 3dnowext 3dnow 2039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bogomips : 3600.62 2040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TLB size : 1088 4K pages 2041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown clflush size : 64 2042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cache_alignment : 64 2043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown address sizes : 40 bits physical, 48 bits virtual 2044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown power management: ts fid vid ttp 2045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 2046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid amd64g_dirtyhelper_CPUID_baseline ( VexGuestAMD64State* st ) 2047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define SET_ABCD(_a,_b,_c,_d) \ 2049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do { st->guest_RAX = (ULong)(_a); \ 2050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown st->guest_RBX = (ULong)(_b); \ 2051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown st->guest_RCX = (ULong)(_c); \ 2052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown st->guest_RDX = (ULong)(_d); \ 2053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } while (0) 2054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (0xFFFFFFFF & st->guest_RAX) { 2056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x00000000: 2057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x00000001, 0x68747541, 0x444d4163, 0x69746e65); 2058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x00000001: 2060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x00000f5a, 0x01000800, 0x00000000, 0x078bfbff); 2061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x80000000: 2063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x80000018, 0x68747541, 0x444d4163, 0x69746e65); 2064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x80000001: 2066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x00000f5a, 0x00000505, 0x00000000, 0xe1d3fbff); 2067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x80000002: 2069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x20444d41, 0x6574704f, 0x206e6f72, 0x296d7428); 2070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x80000003: 2072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x6f725020, 0x73736563, 0x3820726f, 0x00003834); 2073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x80000004: 2075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000); 2076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x80000005: 2078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0xff08ff08, 0xff20ff20, 0x40020140, 0x40020140); 2079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x80000006: 2081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x00000000, 0x42004200, 0x04008140, 0x00000000); 2082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x80000007: 2084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x0000000f); 2085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x80000008: 2087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x00003028, 0x00000000, 0x00000000, 0x00000000); 2088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 2090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000); 2091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# undef SET_ABCD 2094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Claim to be the following CPU (2 x ...), which is sse3 and cx16 2098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown capable. 2099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vendor_id : GenuineIntel 2101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cpu family : 6 2102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown model : 15 2103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown model name : Intel(R) Core(TM)2 CPU 6600 @ 2.40GHz 2104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stepping : 6 2105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cpu MHz : 2394.000 2106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cache size : 4096 KB 2107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown physical id : 0 2108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown siblings : 2 2109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown core id : 0 2110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cpu cores : 2 2111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fpu : yes 2112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fpu_exception : yes 2113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cpuid level : 10 2114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown wp : yes 2115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown flags : fpu vme de pse tsc msr pae mce cx8 apic sep 2116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mtrr pge mca cmov pat pse36 clflush dts acpi 2117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mmx fxsr sse sse2 ss ht tm syscall nx lm 2118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown constant_tsc pni monitor ds_cpl vmx est tm2 2119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cx16 xtpr lahf_lm 2120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bogomips : 4798.78 2121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown clflush size : 64 2122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cache_alignment : 64 2123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown address sizes : 36 bits physical, 48 bits virtual 2124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown power management: 2125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 2126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid amd64g_dirtyhelper_CPUID_sse3_and_cx16 ( VexGuestAMD64State* st ) 2127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define SET_ABCD(_a,_b,_c,_d) \ 2129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do { st->guest_RAX = (ULong)(_a); \ 2130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown st->guest_RBX = (ULong)(_b); \ 2131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown st->guest_RCX = (ULong)(_c); \ 2132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown st->guest_RDX = (ULong)(_d); \ 2133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } while (0) 2134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (0xFFFFFFFF & st->guest_RAX) { 2136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x00000000: 2137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x0000000a, 0x756e6547, 0x6c65746e, 0x49656e69); 2138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x00000001: 2140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x000006f6, 0x00020800, 0x0000e3bd, 0xbfebfbff); 2141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x00000002: 2143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x05b0b101, 0x005657f0, 0x00000000, 0x2cb43049); 2144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x00000003: 2146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000); 2147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x00000004: { 2149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (0xFFFFFFFF & st->guest_RCX) { 2150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x00000000: SET_ABCD(0x04000121, 0x01c0003f, 2151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0x0000003f, 0x00000001); break; 2152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x00000001: SET_ABCD(0x04000122, 0x01c0003f, 2153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0x0000003f, 0x00000001); break; 2154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x00000002: SET_ABCD(0x04004143, 0x03c0003f, 2155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0x00000fff, 0x00000001); break; 2156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: SET_ABCD(0x00000000, 0x00000000, 2157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0x00000000, 0x00000000); break; 2158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x00000005: 2162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x00000040, 0x00000040, 0x00000003, 0x00000020); 2163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x00000006: 2165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x00000001, 0x00000002, 0x00000001, 0x00000000); 2166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x00000007: 2168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000); 2169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x00000008: 2171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x00000400, 0x00000000, 0x00000000, 0x00000000); 2172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x00000009: 2174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000); 2175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x0000000a: 2177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unhandled_eax_value: 2178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x07280202, 0x00000000, 0x00000000, 0x00000000); 2179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x80000000: 2181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x80000008, 0x00000000, 0x00000000, 0x00000000); 2182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x80000001: 2184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x00000000, 0x00000000, 0x00000001, 0x20100800); 2185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x80000002: 2187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x65746e49, 0x2952286c, 0x726f4320, 0x4d542865); 2188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x80000003: 2190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x43203229, 0x20205550, 0x20202020, 0x20202020); 2191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x80000004: 2193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x30303636, 0x20402020, 0x30342e32, 0x007a4847); 2194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x80000005: 2196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000); 2197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x80000006: 2199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x00000000, 0x00000000, 0x10008040, 0x00000000); 2200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x80000007: 2202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000); 2203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x80000008: 2205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x00003024, 0x00000000, 0x00000000, 0x00000000); 2206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 2208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto unhandled_eax_value; 2209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# undef SET_ABCD 2211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Claim to be the following CPU (4 x ...), which is sse4.2 and cx16 2215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown capable. 2216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vendor_id : GenuineIntel 2218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cpu family : 6 2219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown model : 37 2220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown model name : Intel(R) Core(TM) i5 CPU 670 @ 3.47GHz 2221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stepping : 2 2222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cpu MHz : 3334.000 2223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cache size : 4096 KB 2224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown physical id : 0 2225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown siblings : 4 2226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown core id : 0 2227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cpu cores : 2 2228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown apicid : 0 2229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown initial apicid : 0 2230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fpu : yes 2231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fpu_exception : yes 2232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cpuid level : 11 2233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown wp : yes 2234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown flags : fpu vme de pse tsc msr pae mce cx8 apic sep 2235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mtrr pge mca cmov pat pse36 clflush dts acpi 2236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp 2237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown lm constant_tsc arch_perfmon pebs bts rep_good 2238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xtopology nonstop_tsc aperfmperf pni pclmulqdq 2239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 2240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xtpr pdcm sse4_1 sse4_2 popcnt aes lahf_lm ida 2241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arat tpr_shadow vnmi flexpriority ept vpid 2242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MINUS aes (see below) 2243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bogomips : 6957.57 2244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown clflush size : 64 2245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cache_alignment : 64 2246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown address sizes : 36 bits physical, 48 bits virtual 2247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown power management: 2248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 2249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid amd64g_dirtyhelper_CPUID_sse42_and_cx16 ( VexGuestAMD64State* st ) 2250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define SET_ABCD(_a,_b,_c,_d) \ 2252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do { st->guest_RAX = (ULong)(_a); \ 2253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown st->guest_RBX = (ULong)(_b); \ 2254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown st->guest_RCX = (ULong)(_c); \ 2255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown st->guest_RDX = (ULong)(_d); \ 2256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } while (0) 2257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt old_eax = (UInt)st->guest_RAX; 2259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt old_ecx = (UInt)st->guest_RCX; 2260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (old_eax) { 2262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x00000000: 2263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x0000000b, 0x756e6547, 0x6c65746e, 0x49656e69); 2264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x00000001: 2266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // & ~(1<<25): don't claim to support AES insns. See 2267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // bug 249991. 2268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x00020652, 0x00100800, 0x0298e3ff & ~(1<<25), 2269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0xbfebfbff); 2270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x00000002: 2272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x55035a01, 0x00f0b2e3, 0x00000000, 0x09ca212c); 2273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x00000003: 2275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000); 2276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x00000004: 2278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (old_ecx) { 2279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x00000000: SET_ABCD(0x1c004121, 0x01c0003f, 2280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0x0000003f, 0x00000000); break; 2281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x00000001: SET_ABCD(0x1c004122, 0x00c0003f, 2282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0x0000007f, 0x00000000); break; 2283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x00000002: SET_ABCD(0x1c004143, 0x01c0003f, 2284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0x000001ff, 0x00000000); break; 2285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x00000003: SET_ABCD(0x1c03c163, 0x03c0003f, 2286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0x00000fff, 0x00000002); break; 2287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: SET_ABCD(0x00000000, 0x00000000, 2288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0x00000000, 0x00000000); break; 2289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x00000005: 2292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x00000040, 0x00000040, 0x00000003, 0x00001120); 2293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x00000006: 2295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x00000007, 0x00000002, 0x00000001, 0x00000000); 2296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x00000007: 2298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000); 2299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x00000008: 2301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000); 2302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x00000009: 2304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000); 2305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x0000000a: 2307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x07300403, 0x00000004, 0x00000000, 0x00000603); 2308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x0000000b: 2310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (old_ecx) { 2311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x00000000: 2312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x00000001, 0x00000002, 2313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0x00000100, 0x00000000); break; 2314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x00000001: 2315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x00000004, 0x00000004, 2316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0x00000201, 0x00000000); break; 2317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 2318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x00000000, 0x00000000, 2319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown old_ecx, 0x00000000); break; 2320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x0000000c: 2323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x00000001, 0x00000002, 0x00000100, 0x00000000); 2324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x0000000d: 2326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (old_ecx) { 2327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x00000000: SET_ABCD(0x00000001, 0x00000002, 2328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0x00000100, 0x00000000); break; 2329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x00000001: SET_ABCD(0x00000004, 0x00000004, 2330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0x00000201, 0x00000000); break; 2331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: SET_ABCD(0x00000000, 0x00000000, 2332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown old_ecx, 0x00000000); break; 2333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x80000000: 2336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x80000008, 0x00000000, 0x00000000, 0x00000000); 2337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x80000001: 2339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x00000000, 0x00000000, 0x00000001, 0x28100800); 2340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x80000002: 2342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x65746e49, 0x2952286c, 0x726f4320, 0x4d542865); 2343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x80000003: 2345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x35692029, 0x55504320, 0x20202020, 0x20202020); 2346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x80000004: 2348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x30373620, 0x20402020, 0x37342e33, 0x007a4847); 2349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x80000005: 2351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000); 2352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x80000006: 2354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x00000000, 0x00000000, 0x01006040, 0x00000000); 2355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x80000007: 2357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000100); 2358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x80000008: 2360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x00003024, 0x00000000, 0x00000000, 0x00000000); 2361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 2363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_ABCD(0x00000001, 0x00000002, 0x00000100, 0x00000000); 2364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# undef SET_ABCD 2367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong amd64g_calculate_RCR ( ULong arg, 2371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong rot_amt, 2372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong rflags_in, 2373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Long szIN ) 2374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool wantRflags = toBool(szIN < 0); 2376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong sz = wantRflags ? (-szIN) : szIN; 2377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong tempCOUNT = rot_amt & (sz == 8 ? 0x3F : 0x1F); 2378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong cf=0, of=0, tempcf; 2379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (sz) { 2381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 8: 2382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cf = (rflags_in >> AMD64G_CC_SHIFT_C) & 1; 2383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of = ((arg >> 63) ^ cf) & 1; 2384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (tempCOUNT > 0) { 2385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tempcf = arg & 1; 2386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg = (arg >> 1) | (cf << 63); 2387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cf = tempcf; 2388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tempCOUNT--; 2389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 4: 2392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (tempCOUNT >= 33) tempCOUNT -= 33; 2393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cf = (rflags_in >> AMD64G_CC_SHIFT_C) & 1; 2394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of = ((arg >> 31) ^ cf) & 1; 2395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (tempCOUNT > 0) { 2396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tempcf = arg & 1; 2397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg = ((arg >> 1) & 0x7FFFFFFFULL) | (cf << 31); 2398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cf = tempcf; 2399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tempCOUNT--; 2400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 2: 2403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (tempCOUNT >= 17) tempCOUNT -= 17; 2404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cf = (rflags_in >> AMD64G_CC_SHIFT_C) & 1; 2405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of = ((arg >> 15) ^ cf) & 1; 2406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (tempCOUNT > 0) { 2407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tempcf = arg & 1; 2408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg = ((arg >> 1) & 0x7FFFULL) | (cf << 15); 2409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cf = tempcf; 2410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tempCOUNT--; 2411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 1: 2414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (tempCOUNT >= 9) tempCOUNT -= 9; 2415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cf = (rflags_in >> AMD64G_CC_SHIFT_C) & 1; 2416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of = ((arg >> 7) ^ cf) & 1; 2417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (tempCOUNT > 0) { 2418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tempcf = arg & 1; 2419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg = ((arg >> 1) & 0x7FULL) | (cf << 7); 2420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cf = tempcf; 2421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tempCOUNT--; 2422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 2425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("calculate_RCR(amd64g): invalid size"); 2426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cf &= 1; 2429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of &= 1; 2430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown rflags_in &= ~(AMD64G_CC_MASK_C | AMD64G_CC_MASK_O); 2431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown rflags_in |= (cf << AMD64G_CC_SHIFT_C) | (of << AMD64G_CC_SHIFT_O); 2432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* caller can ask to have back either the resulting flags or 2434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown resulting value, but not both */ 2435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return wantRflags ? rflags_in : arg; 2436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong amd64g_calculate_RCL ( ULong arg, 2439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong rot_amt, 2440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong rflags_in, 2441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Long szIN ) 2442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool wantRflags = toBool(szIN < 0); 2444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong sz = wantRflags ? (-szIN) : szIN; 2445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong tempCOUNT = rot_amt & (sz == 8 ? 0x3F : 0x1F); 2446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong cf=0, of=0, tempcf; 2447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (sz) { 2449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 8: 2450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cf = (rflags_in >> AMD64G_CC_SHIFT_C) & 1; 2451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (tempCOUNT > 0) { 2452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tempcf = (arg >> 63) & 1; 2453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg = (arg << 1) | (cf & 1); 2454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cf = tempcf; 2455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tempCOUNT--; 2456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of = ((arg >> 63) ^ cf) & 1; 2458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 4: 2460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (tempCOUNT >= 33) tempCOUNT -= 33; 2461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cf = (rflags_in >> AMD64G_CC_SHIFT_C) & 1; 2462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (tempCOUNT > 0) { 2463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tempcf = (arg >> 31) & 1; 2464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg = 0xFFFFFFFFULL & ((arg << 1) | (cf & 1)); 2465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cf = tempcf; 2466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tempCOUNT--; 2467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of = ((arg >> 31) ^ cf) & 1; 2469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 2: 2471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (tempCOUNT >= 17) tempCOUNT -= 17; 2472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cf = (rflags_in >> AMD64G_CC_SHIFT_C) & 1; 2473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (tempCOUNT > 0) { 2474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tempcf = (arg >> 15) & 1; 2475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg = 0xFFFFULL & ((arg << 1) | (cf & 1)); 2476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cf = tempcf; 2477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tempCOUNT--; 2478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of = ((arg >> 15) ^ cf) & 1; 2480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 1: 2482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (tempCOUNT >= 9) tempCOUNT -= 9; 2483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cf = (rflags_in >> AMD64G_CC_SHIFT_C) & 1; 2484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (tempCOUNT > 0) { 2485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tempcf = (arg >> 7) & 1; 2486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg = 0xFFULL & ((arg << 1) | (cf & 1)); 2487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cf = tempcf; 2488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tempCOUNT--; 2489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of = ((arg >> 7) ^ cf) & 1; 2491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 2493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("calculate_RCL(amd64g): invalid size"); 2494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cf &= 1; 2497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of &= 1; 2498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown rflags_in &= ~(AMD64G_CC_MASK_C | AMD64G_CC_MASK_O); 2499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown rflags_in |= (cf << AMD64G_CC_SHIFT_C) | (of << AMD64G_CC_SHIFT_O); 2500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return wantRflags ? rflags_in : arg; 2502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Taken from gf2x-0.9.5, released under GPLv2+ (later versions LGPLv2+) 2505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * svn://scm.gforge.inria.fr/svn/gf2x/trunk/hardware/opteron/gf2x_mul1.h@25 2506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 2507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong amd64g_calculate_pclmul(ULong a, ULong b, ULong which) 2508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong hi, lo, tmp, A[16]; 2510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown A[0] = 0; A[1] = a; 2512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown A[2] = A[1] << 1; A[3] = A[2] ^ a; 2513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown A[4] = A[2] << 1; A[5] = A[4] ^ a; 2514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown A[6] = A[3] << 1; A[7] = A[6] ^ a; 2515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown A[8] = A[4] << 1; A[9] = A[8] ^ a; 2516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown A[10] = A[5] << 1; A[11] = A[10] ^ a; 2517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown A[12] = A[6] << 1; A[13] = A[12] ^ a; 2518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown A[14] = A[7] << 1; A[15] = A[14] ^ a; 2519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown lo = (A[b >> 60] << 4) ^ A[(b >> 56) & 15]; 2521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hi = lo >> 56; 2522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown lo = (lo << 8) ^ (A[(b >> 52) & 15] << 4) ^ A[(b >> 48) & 15]; 2523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hi = (hi << 8) | (lo >> 56); 2524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown lo = (lo << 8) ^ (A[(b >> 44) & 15] << 4) ^ A[(b >> 40) & 15]; 2525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hi = (hi << 8) | (lo >> 56); 2526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown lo = (lo << 8) ^ (A[(b >> 36) & 15] << 4) ^ A[(b >> 32) & 15]; 2527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hi = (hi << 8) | (lo >> 56); 2528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown lo = (lo << 8) ^ (A[(b >> 28) & 15] << 4) ^ A[(b >> 24) & 15]; 2529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hi = (hi << 8) | (lo >> 56); 2530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown lo = (lo << 8) ^ (A[(b >> 20) & 15] << 4) ^ A[(b >> 16) & 15]; 2531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hi = (hi << 8) | (lo >> 56); 2532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown lo = (lo << 8) ^ (A[(b >> 12) & 15] << 4) ^ A[(b >> 8) & 15]; 2533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hi = (hi << 8) | (lo >> 56); 2534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown lo = (lo << 8) ^ (A[(b >> 4) & 15] << 4) ^ A[b & 15]; 2535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong m0 = -1; 2537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown m0 /= 255; 2538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmp = -((a >> 63) & 1); tmp &= ((b & (m0 * 0xfe)) >> 1); hi = hi ^ tmp; 2539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmp = -((a >> 62) & 1); tmp &= ((b & (m0 * 0xfc)) >> 2); hi = hi ^ tmp; 2540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmp = -((a >> 61) & 1); tmp &= ((b & (m0 * 0xf8)) >> 3); hi = hi ^ tmp; 2541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmp = -((a >> 60) & 1); tmp &= ((b & (m0 * 0xf0)) >> 4); hi = hi ^ tmp; 2542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmp = -((a >> 59) & 1); tmp &= ((b & (m0 * 0xe0)) >> 5); hi = hi ^ tmp; 2543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmp = -((a >> 58) & 1); tmp &= ((b & (m0 * 0xc0)) >> 6); hi = hi ^ tmp; 2544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmp = -((a >> 57) & 1); tmp &= ((b & (m0 * 0x80)) >> 7); hi = hi ^ tmp; 2545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return which ? hi : lo; 2547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CALLED FROM GENERATED CODE */ 2551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DIRTY HELPER (non-referentially-transparent) */ 2552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Horrible hack. On non-amd64 platforms, return 1. */ 2553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong amd64g_dirtyhelper_RDTSC ( void ) 2554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(__x86_64__) 2556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt eax, edx; 2557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown __asm__ __volatile__("rdtsc" : "=a" (eax), "=d" (edx)); 2558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return (((ULong)edx) << 32) | ((ULong)eax); 2559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 2560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 1ULL; 2561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 2562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CALLED FROM GENERATED CODE */ 2566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DIRTY HELPER (non-referentially-transparent) */ 2567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Horrible hack. On non-amd64 platforms, return 0. */ 2568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong amd64g_dirtyhelper_IN ( ULong portno, ULong sz/*1,2 or 4*/ ) 2569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(__x86_64__) 2571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong r = 0; 2572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown portno &= 0xFFFF; 2573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (sz) { 2574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 4: 2575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown __asm__ __volatile__("movq $0,%%rax; inl %w1,%%eax; movq %%rax,%0" 2576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown : "=a" (r) : "Nd" (portno)); 2577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 2: 2579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown __asm__ __volatile__("movq $0,%%rax; inw %w1,%w0" 2580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown : "=a" (r) : "Nd" (portno)); 2581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 1: 2583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown __asm__ __volatile__("movq $0,%%rax; inb %w1,%b0" 2584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown : "=a" (r) : "Nd" (portno)); 2585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 2587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; /* note: no 64-bit version of insn exists */ 2588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return r; 2590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 2591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 2592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 2593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CALLED FROM GENERATED CODE */ 2597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DIRTY HELPER (non-referentially-transparent) */ 2598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Horrible hack. On non-amd64 platforms, do nothing. */ 2599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid amd64g_dirtyhelper_OUT ( ULong portno, ULong data, ULong sz/*1,2 or 4*/ ) 2600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(__x86_64__) 2602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown portno &= 0xFFFF; 2603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (sz) { 2604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 4: 2605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown __asm__ __volatile__("movq %0,%%rax; outl %%eax, %w1" 2606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown : : "a" (data), "Nd" (portno)); 2607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 2: 2609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown __asm__ __volatile__("outw %w0, %w1" 2610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown : : "a" (data), "Nd" (portno)); 2611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 1: 2613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown __asm__ __volatile__("outb %b0, %w1" 2614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown : : "a" (data), "Nd" (portno)); 2615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 2617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; /* note: no 64-bit version of insn exists */ 2618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 2620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* do nothing */ 2621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 2622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CALLED FROM GENERATED CODE */ 2625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DIRTY HELPER (non-referentially-transparent) */ 2626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Horrible hack. On non-amd64 platforms, do nothing. */ 2627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* op = 0: call the native SGDT instruction. 2628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown op = 1: call the native SIDT instruction. 2629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 2630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid amd64g_dirtyhelper_SxDT ( void *address, ULong op ) { 2631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(__x86_64__) 2632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (op) { 2633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0: 2634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown __asm__ __volatile__("sgdt (%0)" : : "r" (address) : "memory"); 2635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 1: 2637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown __asm__ __volatile__("sidt (%0)" : : "r" (address) : "memory"); 2638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 2640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("amd64g_dirtyhelper_SxDT"); 2641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 2643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* do nothing */ 2644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar* p = (UChar*)address; 2645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p[0] = p[1] = p[2] = p[3] = p[4] = p[5] = 0; 2646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p[6] = p[7] = p[8] = p[9] = 0; 2647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 2648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/ 2651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Helpers for MMX/SSE/SSE2. ---*/ 2652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/ 2653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline UChar abdU8 ( UChar xx, UChar yy ) { 2655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return toUChar(xx>yy ? xx-yy : yy-xx); 2656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline ULong mk32x2 ( UInt w1, UInt w0 ) { 2659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return (((ULong)w1) << 32) | ((ULong)w0); 2660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline UShort sel16x4_3 ( ULong w64 ) { 2663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt hi32 = toUInt(w64 >> 32); 2664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return toUShort(hi32 >> 16); 2665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline UShort sel16x4_2 ( ULong w64 ) { 2667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt hi32 = toUInt(w64 >> 32); 2668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return toUShort(hi32); 2669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline UShort sel16x4_1 ( ULong w64 ) { 2671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt lo32 = toUInt(w64); 2672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return toUShort(lo32 >> 16); 2673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline UShort sel16x4_0 ( ULong w64 ) { 2675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt lo32 = toUInt(w64); 2676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return toUShort(lo32); 2677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline UChar sel8x8_7 ( ULong w64 ) { 2680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt hi32 = toUInt(w64 >> 32); 2681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return toUChar(hi32 >> 24); 2682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline UChar sel8x8_6 ( ULong w64 ) { 2684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt hi32 = toUInt(w64 >> 32); 2685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return toUChar(hi32 >> 16); 2686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline UChar sel8x8_5 ( ULong w64 ) { 2688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt hi32 = toUInt(w64 >> 32); 2689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return toUChar(hi32 >> 8); 2690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline UChar sel8x8_4 ( ULong w64 ) { 2692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt hi32 = toUInt(w64 >> 32); 2693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return toUChar(hi32 >> 0); 2694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline UChar sel8x8_3 ( ULong w64 ) { 2696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt lo32 = toUInt(w64); 2697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return toUChar(lo32 >> 24); 2698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline UChar sel8x8_2 ( ULong w64 ) { 2700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt lo32 = toUInt(w64); 2701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return toUChar(lo32 >> 16); 2702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline UChar sel8x8_1 ( ULong w64 ) { 2704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt lo32 = toUInt(w64); 2705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return toUChar(lo32 >> 8); 2706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline UChar sel8x8_0 ( ULong w64 ) { 2708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt lo32 = toUInt(w64); 2709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return toUChar(lo32 >> 0); 2710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CALLED FROM GENERATED CODE: CLEAN HELPER */ 2713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong amd64g_calculate_mmx_pmaddwd ( ULong xx, ULong yy ) 2714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 2716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mk32x2( 2717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (((Int)(Short)sel16x4_3(xx)) * ((Int)(Short)sel16x4_3(yy))) 2718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown + (((Int)(Short)sel16x4_2(xx)) * ((Int)(Short)sel16x4_2(yy))), 2719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (((Int)(Short)sel16x4_1(xx)) * ((Int)(Short)sel16x4_1(yy))) 2720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown + (((Int)(Short)sel16x4_0(xx)) * ((Int)(Short)sel16x4_0(yy))) 2721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 2722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CALLED FROM GENERATED CODE: CLEAN HELPER */ 2725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong amd64g_calculate_mmx_pmovmskb ( ULong xx ) 2726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong r = 0; 2728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (xx & (1ULL << (64-1))) r |= (1<<7); 2729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (xx & (1ULL << (56-1))) r |= (1<<6); 2730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (xx & (1ULL << (48-1))) r |= (1<<5); 2731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (xx & (1ULL << (40-1))) r |= (1<<4); 2732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (xx & (1ULL << (32-1))) r |= (1<<3); 2733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (xx & (1ULL << (24-1))) r |= (1<<2); 2734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (xx & (1ULL << (16-1))) r |= (1<<1); 2735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (xx & (1ULL << ( 8-1))) r |= (1<<0); 2736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return r; 2737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CALLED FROM GENERATED CODE: CLEAN HELPER */ 2740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong amd64g_calculate_mmx_psadbw ( ULong xx, ULong yy ) 2741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt t = 0; 2743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown t += (UInt)abdU8( sel8x8_7(xx), sel8x8_7(yy) ); 2744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown t += (UInt)abdU8( sel8x8_6(xx), sel8x8_6(yy) ); 2745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown t += (UInt)abdU8( sel8x8_5(xx), sel8x8_5(yy) ); 2746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown t += (UInt)abdU8( sel8x8_4(xx), sel8x8_4(yy) ); 2747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown t += (UInt)abdU8( sel8x8_3(xx), sel8x8_3(yy) ); 2748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown t += (UInt)abdU8( sel8x8_2(xx), sel8x8_2(yy) ); 2749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown t += (UInt)abdU8( sel8x8_1(xx), sel8x8_1(yy) ); 2750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown t += (UInt)abdU8( sel8x8_0(xx), sel8x8_0(yy) ); 2751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown t &= 0xFFFF; 2752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return (ULong)t; 2753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CALLED FROM GENERATED CODE: CLEAN HELPER */ 2756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong amd64g_calculate_sse_pmovmskb ( ULong w64hi, ULong w64lo ) 2757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong rHi8 = amd64g_calculate_mmx_pmovmskb ( w64hi ); 2759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong rLo8 = amd64g_calculate_mmx_pmovmskb ( w64lo ); 2760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ((rHi8 & 0xFF) << 8) | (rLo8 & 0xFF); 2761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2763f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root/* CALLED FROM GENERATED CODE: CLEAN HELPER */ 2764f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny RootULong amd64g_calc_crc32b ( ULong crcIn, ULong b ) 2765f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root{ 2766f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root UInt i; 2767f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root ULong crc = (b & 0xFFULL) ^ crcIn; 2768f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root for (i = 0; i < 8; i++) 2769f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root crc = (crc >> 1) ^ ((crc & 1) ? 0x82f63b78ULL : 0); 2770f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root return crc; 2771f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root} 2772f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root 2773f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root/* CALLED FROM GENERATED CODE: CLEAN HELPER */ 2774f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny RootULong amd64g_calc_crc32w ( ULong crcIn, ULong w ) 2775f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root{ 2776f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root UInt i; 2777f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root ULong crc = (w & 0xFFFFULL) ^ crcIn; 2778f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root for (i = 0; i < 16; i++) 2779f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root crc = (crc >> 1) ^ ((crc & 1) ? 0x82f63b78ULL : 0); 2780f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root return crc; 2781f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root} 2782f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root 2783f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root/* CALLED FROM GENERATED CODE: CLEAN HELPER */ 2784f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny RootULong amd64g_calc_crc32l ( ULong crcIn, ULong l ) 2785f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root{ 2786f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root UInt i; 2787f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root ULong crc = (l & 0xFFFFFFFFULL) ^ crcIn; 2788f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root for (i = 0; i < 32; i++) 2789f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root crc = (crc >> 1) ^ ((crc & 1) ? 0x82f63b78ULL : 0); 2790f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root return crc; 2791f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root} 2792f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root 2793f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root/* CALLED FROM GENERATED CODE: CLEAN HELPER */ 2794f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny RootULong amd64g_calc_crc32q ( ULong crcIn, ULong q ) 2795f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root{ 2796f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root ULong crc = amd64g_calc_crc32l(crcIn, q); 2797f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root return amd64g_calc_crc32l(crc, q >> 32); 2798f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root} 2799f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root 2800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/ 2802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Helpers for SSE4.2 PCMP{E,I}STR{I,M} ---*/ 2803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/ 2804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt zmask_from_V128 ( V128* arg ) 2806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt i, res = 0; 2808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < 16; i++) { 2809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res |= ((arg->w8[i] == 0) ? 1 : 0) << i; 2810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Helps with PCMP{I,E}STR{I,M}. 2815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALLED FROM GENERATED CODE: DIRTY HELPER(s). (But not really, 2817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown actually it could be a clean helper, but for the fact that we can't 2818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pass by value 2 x V128 to a clean helper, nor have one returned.) 2819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Reads guest state, writes to guest state for the xSTRM cases, no 2820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown accesses of memory, is a pure function. 2821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown opc_and_imm contains (4th byte of opcode << 8) | the-imm8-byte so 2823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the callee knows which I/E and I/M variant it is dealing with and 2824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown what the specific operation is. 4th byte of opcode is in the range 2825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0x60 to 0x63: 2826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown istri 66 0F 3A 63 2827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown istrm 66 0F 3A 62 2828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown estri 66 0F 3A 61 2829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown estrm 66 0F 3A 60 2830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gstOffL and gstOffR are the guest state offsets for the two XMM 2832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown register inputs. We never have to deal with the memory case since 2833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown that is handled by pre-loading the relevant value into the fake 2834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XMM16 register. 2835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown For ESTRx variants, edxIN and eaxIN hold the values of those two 2837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown registers. 2838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown In all cases, the bottom 16 bits of the result contain the new 2840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OSZACP %rflags values. For xSTRI variants, bits[31:16] of the 2841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown result hold the new %ecx value. For xSTRM variants, the helper 2842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown writes the result directly to the guest XMM0. 2843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Declarable side effects: in all cases, reads guest state at 2845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown [gstOffL, +16) and [gstOffR, +16). For xSTRM variants, also writes 2846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown guest_XMM0. 2847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Is expected to be called with opc_and_imm combinations which have 2849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown actually been validated, and will assert if otherwise. The front 2850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown end should ensure we're only called with verified values. 2851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 2852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong amd64g_dirtyhelper_PCMPxSTRx ( 2853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexGuestAMD64State* gst, 2854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HWord opc4_and_imm, 2855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HWord gstOffL, HWord gstOffR, 2856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HWord edxIN, HWord eaxIN 2857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ) 2858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HWord opc4 = (opc4_and_imm >> 8) & 0xFF; 2860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HWord imm8 = opc4_and_imm & 0xFF; 2861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HWord isISTRx = opc4 & 2; 2862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HWord isxSTRM = (opc4 & 1) ^ 1; 2863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert((opc4 & 0xFC) == 0x60); /* 0x60 .. 0x63 */ 2864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert((imm8 & 1) == 0); /* we support byte-size cases only */ 2865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // where the args are 2867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown V128* argL = (V128*)( ((UChar*)gst) + gstOffL ); 2868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown V128* argR = (V128*)( ((UChar*)gst) + gstOffR ); 2869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Create the arg validity masks, either from the vectors 2871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown themselves or from the supplied edx/eax values. */ 2872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // FIXME: this is only right for the 8-bit data cases. 2873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // At least that is asserted above. 2874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt zmaskL, zmaskR; 2875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isISTRx) { 2876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown zmaskL = zmask_from_V128(argL); 2877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown zmaskR = zmask_from_V128(argR); 2878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 2879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int tmp; 2880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmp = edxIN & 0xFFFFFFFF; 2881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tmp < -16) tmp = -16; 2882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tmp > 16) tmp = 16; 2883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tmp < 0) tmp = -tmp; 2884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(tmp >= 0 && tmp <= 16); 2885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown zmaskL = (1 << tmp) & 0xFFFF; 2886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmp = eaxIN & 0xFFFFFFFF; 2887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tmp < -16) tmp = -16; 2888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tmp > 16) tmp = 16; 2889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tmp < 0) tmp = -tmp; 2890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(tmp >= 0 && tmp <= 16); 2891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown zmaskR = (1 << tmp) & 0xFFFF; 2892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // temp spot for the resulting flags and vector. 2895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown V128 resV; 2896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt resOSZACP; 2897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // do the meyaath 2899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool ok = compute_PCMPxSTRx ( 2900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown &resV, &resOSZACP, argL, argR, 2901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown zmaskL, zmaskR, imm8, (Bool)isxSTRM 2902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 2903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // front end shouldn't pass us any imm8 variants we can't 2905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // handle. Hence: 2906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(ok); 2907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // So, finally we need to get the results back to the caller. 2909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // In all cases, the new OSZACP value is the lowest 16 of 2910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // the return value. 2911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isxSTRM) { 2912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* gst->guest_XMM0 = resV; */ // gcc don't like that 2913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_XMM0[0] = resV.w32[0]; 2914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_XMM0[1] = resV.w32[1]; 2915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_XMM0[2] = resV.w32[2]; 2916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gst->guest_XMM0[3] = resV.w32[3]; 2917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return resOSZACP & 0x8D5; 2918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 2919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt newECX = resV.w32[0] & 0xFFFF; 2920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return (newECX << 16) | (resOSZACP & 0x8D5); 2921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/ 2926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Helpers for dealing with, and describing, ---*/ 2927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- guest state as a whole. ---*/ 2928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/ 2929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Initialise the entire amd64 guest state. */ 2931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* VISIBLE TO LIBVEX CLIENT */ 2932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid LibVEX_GuestAMD64_initialise ( /*OUT*/VexGuestAMD64State* vex_state ) 2933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_state->guest_RAX = 0; 2935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_state->guest_RCX = 0; 2936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_state->guest_RDX = 0; 2937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_state->guest_RBX = 0; 2938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_state->guest_RSP = 0; 2939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_state->guest_RBP = 0; 2940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_state->guest_RSI = 0; 2941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_state->guest_RDI = 0; 2942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_state->guest_R8 = 0; 2943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_state->guest_R9 = 0; 2944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_state->guest_R10 = 0; 2945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_state->guest_R11 = 0; 2946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_state->guest_R12 = 0; 2947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_state->guest_R13 = 0; 2948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_state->guest_R14 = 0; 2949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_state->guest_R15 = 0; 2950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_state->guest_CC_OP = AMD64G_CC_OP_COPY; 2952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_state->guest_CC_DEP1 = 0; 2953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_state->guest_CC_DEP2 = 0; 2954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_state->guest_CC_NDEP = 0; 2955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_state->guest_DFLAG = 1; /* forwards */ 2957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_state->guest_IDFLAG = 0; 2958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* HACK: represent the offset associated with %fs==0. This 2960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown assumes that %fs is only ever zero. */ 2961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_state->guest_FS_ZERO = 0; 2962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_state->guest_RIP = 0; 2964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Initialise the simulated FPU */ 2966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown amd64g_dirtyhelper_FINIT( vex_state ); 2967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Initialise the SSE state. */ 2969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define SSEZERO(_xmm) _xmm[0]=_xmm[1]=_xmm[2]=_xmm[3] = 0; 2970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_state->guest_SSEROUND = (ULong)Irrm_NEAREST; 2972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SSEZERO(vex_state->guest_XMM0); 2973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SSEZERO(vex_state->guest_XMM1); 2974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SSEZERO(vex_state->guest_XMM2); 2975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SSEZERO(vex_state->guest_XMM3); 2976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SSEZERO(vex_state->guest_XMM4); 2977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SSEZERO(vex_state->guest_XMM5); 2978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SSEZERO(vex_state->guest_XMM6); 2979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SSEZERO(vex_state->guest_XMM7); 2980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SSEZERO(vex_state->guest_XMM8); 2981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SSEZERO(vex_state->guest_XMM9); 2982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SSEZERO(vex_state->guest_XMM10); 2983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SSEZERO(vex_state->guest_XMM11); 2984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SSEZERO(vex_state->guest_XMM12); 2985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SSEZERO(vex_state->guest_XMM13); 2986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SSEZERO(vex_state->guest_XMM14); 2987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SSEZERO(vex_state->guest_XMM15); 2988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SSEZERO(vex_state->guest_XMM16); 2989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# undef SSEZERO 2991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_state->guest_EMWARN = EmWarn_NONE; 2993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* These should not ever be either read or written, but we 2995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown initialise them anyway. */ 2996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_state->guest_TISTART = 0; 2997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_state->guest_TILEN = 0; 2998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_state->guest_NRADDR = 0; 3000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_state->guest_SC_CLASS = 0; 3001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_state->guest_GS_0x60 = 0; 3002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_state->guest_IP_AT_SYSCALL = 0; 3004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* vex_state->padding = 0; */ 3005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Figure out if any part of the guest state contained in minoff 3009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown .. maxoff requires precise memory exceptions. If in doubt return 3010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown True (but this is generates significantly slower code). 3011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown By default we enforce precise exns for guest %RSP, %RBP and %RIP 3013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown only. These are the minimum needed to extract correct stack 3014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown backtraces from amd64 code. 3015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 3016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool guest_amd64_state_requires_precise_mem_exns ( Int minoff, 3017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int maxoff) 3018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int rbp_min = offsetof(VexGuestAMD64State, guest_RBP); 3020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int rbp_max = rbp_min + 8 - 1; 3021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int rsp_min = offsetof(VexGuestAMD64State, guest_RSP); 3022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int rsp_max = rsp_min + 8 - 1; 3023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int rip_min = offsetof(VexGuestAMD64State, guest_RIP); 3024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int rip_max = rip_min + 8 - 1; 3025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (maxoff < rbp_min || minoff > rbp_max) { 3027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* no overlap with rbp */ 3028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 3029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 3030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (maxoff < rsp_min || minoff > rsp_max) { 3033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* no overlap with rsp */ 3034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 3035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 3036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (maxoff < rip_min || minoff > rip_max) { 3039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* no overlap with eip */ 3040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 3041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 3042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 3045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ALWAYSDEFD(field) \ 3049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { offsetof(VexGuestAMD64State, field), \ 3050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (sizeof ((VexGuestAMD64State*)0)->field) } 3051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownVexGuestLayout 3053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown amd64guest_layout 3054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = { 3055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Total size of the guest state, in bytes. */ 3056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown .total_sizeB = sizeof(VexGuestAMD64State), 3057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Describe the stack pointer. */ 3059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown .offset_SP = offsetof(VexGuestAMD64State,guest_RSP), 3060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown .sizeof_SP = 8, 3061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Describe the frame pointer. */ 3063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown .offset_FP = offsetof(VexGuestAMD64State,guest_RBP), 3064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown .sizeof_FP = 8, 3065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Describe the instruction pointer. */ 3067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown .offset_IP = offsetof(VexGuestAMD64State,guest_RIP), 3068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown .sizeof_IP = 8, 3069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Describe any sections to be regarded by Memcheck as 3071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 'always-defined'. */ 3072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown .n_alwaysDefd = 16, 3073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* flags thunk: OP and NDEP are always defd, whereas DEP1 3075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and DEP2 have to be tracked. See detailed comment in 3076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gdefs.h on meaning of thunk fields. */ 3077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown .alwaysDefd 3078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = { /* 0 */ ALWAYSDEFD(guest_CC_OP), 3079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 1 */ ALWAYSDEFD(guest_CC_NDEP), 3080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 2 */ ALWAYSDEFD(guest_DFLAG), 3081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 3 */ ALWAYSDEFD(guest_IDFLAG), 3082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 4 */ ALWAYSDEFD(guest_RIP), 3083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 5 */ ALWAYSDEFD(guest_FS_ZERO), 3084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 6 */ ALWAYSDEFD(guest_FTOP), 3085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 7 */ ALWAYSDEFD(guest_FPTAG), 3086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 8 */ ALWAYSDEFD(guest_FPROUND), 3087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 9 */ ALWAYSDEFD(guest_FC3210), 3088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // /* */ ALWAYSDEFD(guest_CS), 3089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // /* */ ALWAYSDEFD(guest_DS), 3090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // /* */ ALWAYSDEFD(guest_ES), 3091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // /* */ ALWAYSDEFD(guest_FS), 3092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // /* */ ALWAYSDEFD(guest_GS), 3093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // /* */ ALWAYSDEFD(guest_SS), 3094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // /* */ ALWAYSDEFD(guest_LDT), 3095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // /* */ ALWAYSDEFD(guest_GDT), 3096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 10 */ ALWAYSDEFD(guest_EMWARN), 3097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 11 */ ALWAYSDEFD(guest_SSEROUND), 3098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 12 */ ALWAYSDEFD(guest_TISTART), 3099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 13 */ ALWAYSDEFD(guest_TILEN), 3100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 14 */ ALWAYSDEFD(guest_SC_CLASS), 3101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 15 */ ALWAYSDEFD(guest_IP_AT_SYSCALL) 3102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown }; 3104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/ 3107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end guest_amd64_helpers.c ---*/ 3108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/ 3109