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
10436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Copyright (C) 2004-2013 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"
37436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "libvex_emnote.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"
43436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "main_globals.h"
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "guest_generic_bb_to_IR.h"
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "guest_amd64_defs.h"
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "guest_generic_x87.h"
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This file contains helper functions for amd64 guest code.
50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Calls to these functions are generated by the back end.
51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   These calls are of course in the host machine code and
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   this file will be compiled to host machine code, so that
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   all makes sense.
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Only change the signatures of these helper functions very
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   carefully.  If you change the signature here, you'll have to change
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the parameters passed to it in the IR calls constructed by
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   guest-amd64/toIR.c.
59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The convention used is that all functions called from generated
61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   code are named amd64g_<something>, and any function whose name lacks
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   that prefix is not called from generated code.  Note that some
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LibVEX_* functions can however be called by VEX's client, but that
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   is not the same as calling them from VEX-generated code.
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Set to 1 to get detailed profiling info about use of the flag
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   machinery. */
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define PROFILE_RFLAGS 0
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- %rflags run-time helpers.                               ---*/
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Do 64x64 -> 128 signed/unsigned multiplies, for computing flags
78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   after imulq/mulq. */
79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void mullS64 ( Long u, Long v, Long* rHi, Long* rLo )
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong u0, v0, w0;
83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Long u1, v1, w1, w2, t;
84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   u0   = u & 0xFFFFFFFFULL;
85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   u1   = u >> 32;
86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   v0   = v & 0xFFFFFFFFULL;
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   v1   = v >> 32;
88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w0   = u0 * v0;
89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   t    = u1 * v0 + (w0 >> 32);
90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w1   = t & 0xFFFFFFFFULL;
91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w2   = t >> 32;
92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w1   = u0 * v1 + w1;
93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *rHi = u1 * v1 + w2 + (w1 >> 32);
94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *rLo = u * v;
95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void mullU64 ( ULong u, ULong v, ULong* rHi, ULong* rLo )
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong u0, v0, w0;
100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong u1, v1, w1,w2,t;
101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   u0   = u & 0xFFFFFFFFULL;
102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   u1   = u >> 32;
103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   v0   = v & 0xFFFFFFFFULL;
104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   v1   = v >> 32;
105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w0   = u0 * v0;
106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   t    = u1 * v0 + (w0 >> 32);
107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w1   = t & 0xFFFFFFFFULL;
108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w2   = t >> 32;
109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w1   = u0 * v1 + w1;
110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *rHi = u1 * v1 + w2 + (w1 >> 32);
111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *rLo = u * v;
112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic const UChar parity_table[256] = {
116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* generalised left-shifter */
151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline Long lshift ( Long x, Int n )
152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (n >= 0)
154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return x << n;
155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return x >> (-n);
157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* identity on ULong */
160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline ULong idULong ( ULong x )
161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return x;
163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define PREAMBLE(__data_bits)					\
167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* const */ ULong DATA_MASK 					\
168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = __data_bits==8                                          \
169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           ? 0xFFULL 					        \
170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           : (__data_bits==16                                   \
171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ? 0xFFFFULL 		                        \
172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : (__data_bits==32                              \
173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     ? 0xFFFFFFFFULL                            \
174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     : 0xFFFFFFFFFFFFFFFFULL));                 \
175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* const */ ULong SIGN_MASK = 1ULL << (__data_bits - 1);     \
176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* const */ ULong CC_DEP1 = cc_dep1_formal;			\
177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* const */ ULong CC_DEP2 = cc_dep2_formal;			\
178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* const */ ULong CC_NDEP = cc_ndep_formal;			\
179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Four bogus assignments, which hopefully gcc can     */	\
180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* optimise away, and which stop it complaining about  */	\
181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* unused variables.                                   */	\
182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SIGN_MASK = SIGN_MASK;					\
183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DATA_MASK = DATA_MASK;					\
184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CC_DEP2 = CC_DEP2;						\
185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CC_NDEP = CC_NDEP;
186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-------------------------------------------------------------*/
189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ACTIONS_ADD(DATA_BITS,DATA_UTYPE)			\
191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{								\
192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PREAMBLE(DATA_BITS);						\
193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { Long cf, pf, af, zf, sf, of;				\
194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Long argL, argR, res;					\
195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     argL = CC_DEP1;						\
196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     argR = CC_DEP2;						\
197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     res  = argL + argR;					\
198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     cf = (DATA_UTYPE)res < (DATA_UTYPE)argL;			\
199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     pf = parity_table[(UChar)res];				\
200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     af = (res ^ argL ^ argR) & 0x10;				\
201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     zf = ((DATA_UTYPE)res == 0) << 6;				\
202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     sf = lshift(res, 8 - DATA_BITS) & 0x80;			\
203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     of = lshift((argL ^ argR ^ -1) & (argL ^ res), 		\
204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 12 - DATA_BITS) & AMD64G_CC_MASK_O;		\
205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     return cf | pf | af | zf | sf | of;			\
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }								\
207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-------------------------------------------------------------*/
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ACTIONS_SUB(DATA_BITS,DATA_UTYPE)			\
212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{								\
213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PREAMBLE(DATA_BITS);						\
214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { Long cf, pf, af, zf, sf, of;				\
215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Long argL, argR, res;					\
216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     argL = CC_DEP1;						\
217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     argR = CC_DEP2;						\
218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     res  = argL - argR;					\
219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     cf = (DATA_UTYPE)argL < (DATA_UTYPE)argR;			\
220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     pf = parity_table[(UChar)res];				\
221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     af = (res ^ argL ^ argR) & 0x10;				\
222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     zf = ((DATA_UTYPE)res == 0) << 6;				\
223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     sf = lshift(res, 8 - DATA_BITS) & 0x80;			\
224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     of = lshift((argL ^ argR) & (argL ^ res),	 		\
225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 12 - DATA_BITS) & AMD64G_CC_MASK_O; 		\
226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     return cf | pf | af | zf | sf | of;			\
227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }								\
228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-------------------------------------------------------------*/
231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ACTIONS_ADC(DATA_BITS,DATA_UTYPE)			\
233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{								\
234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PREAMBLE(DATA_BITS);						\
235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { Long cf, pf, af, zf, sf, of;				\
236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Long argL, argR, oldC, res;		 		\
237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     oldC = CC_NDEP & AMD64G_CC_MASK_C;				\
238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     argL = CC_DEP1;						\
239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     argR = CC_DEP2 ^ oldC;	       				\
240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     res  = (argL + argR) + oldC;				\
241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (oldC)							\
242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cf = (DATA_UTYPE)res <= (DATA_UTYPE)argL;		\
243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     else							\
244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cf = (DATA_UTYPE)res < (DATA_UTYPE)argL;		\
245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     pf = parity_table[(UChar)res];				\
246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     af = (res ^ argL ^ argR) & 0x10;				\
247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     zf = ((DATA_UTYPE)res == 0) << 6;				\
248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     sf = lshift(res, 8 - DATA_BITS) & 0x80;			\
249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     of = lshift((argL ^ argR ^ -1) & (argL ^ res), 		\
250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  12 - DATA_BITS) & AMD64G_CC_MASK_O;		\
251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     return cf | pf | af | zf | sf | of;			\
252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }								\
253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-------------------------------------------------------------*/
256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ACTIONS_SBB(DATA_BITS,DATA_UTYPE)			\
258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{								\
259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PREAMBLE(DATA_BITS);						\
260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { Long cf, pf, af, zf, sf, of;				\
261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Long argL, argR, oldC, res;	       			\
262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     oldC = CC_NDEP & AMD64G_CC_MASK_C;				\
263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     argL = CC_DEP1;						\
264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     argR = CC_DEP2 ^ oldC;	       				\
265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     res  = (argL - argR) - oldC;				\
266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (oldC)							\
267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cf = (DATA_UTYPE)argL <= (DATA_UTYPE)argR;		\
268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     else							\
269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cf = (DATA_UTYPE)argL < (DATA_UTYPE)argR;		\
270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     pf = parity_table[(UChar)res];				\
271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     af = (res ^ argL ^ argR) & 0x10;				\
272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     zf = ((DATA_UTYPE)res == 0) << 6;				\
273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     sf = lshift(res, 8 - DATA_BITS) & 0x80;			\
274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     of = lshift((argL ^ argR) & (argL ^ res), 			\
275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 12 - DATA_BITS) & AMD64G_CC_MASK_O;		\
276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     return cf | pf | af | zf | sf | of;			\
277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }								\
278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-------------------------------------------------------------*/
281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ACTIONS_LOGIC(DATA_BITS,DATA_UTYPE)			\
283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{								\
284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PREAMBLE(DATA_BITS);						\
285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { Long cf, pf, af, zf, sf, of;				\
286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     cf = 0;							\
287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     pf = parity_table[(UChar)CC_DEP1];				\
288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     af = 0;							\
289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     zf = ((DATA_UTYPE)CC_DEP1 == 0) << 6;			\
290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     sf = lshift(CC_DEP1, 8 - DATA_BITS) & 0x80;		\
291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     of = 0;							\
292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     return cf | pf | af | zf | sf | of;			\
293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }								\
294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-------------------------------------------------------------*/
297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ACTIONS_INC(DATA_BITS,DATA_UTYPE)			\
299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{								\
300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PREAMBLE(DATA_BITS);						\
301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { Long cf, pf, af, zf, sf, of;				\
302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Long argL, argR, res;					\
303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     res  = CC_DEP1;						\
304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     argL = res - 1;						\
305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     argR = 1;							\
306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     cf = CC_NDEP & AMD64G_CC_MASK_C;				\
307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     pf = parity_table[(UChar)res];				\
308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     af = (res ^ argL ^ argR) & 0x10;				\
309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     zf = ((DATA_UTYPE)res == 0) << 6;				\
310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     sf = lshift(res, 8 - DATA_BITS) & 0x80;			\
311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     of = ((res & DATA_MASK) == SIGN_MASK) << 11;		\
312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     return cf | pf | af | zf | sf | of;			\
313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }								\
314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-------------------------------------------------------------*/
317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ACTIONS_DEC(DATA_BITS,DATA_UTYPE)			\
319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{								\
320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PREAMBLE(DATA_BITS);						\
321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { Long cf, pf, af, zf, sf, of;				\
322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Long argL, argR, res;					\
323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     res  = CC_DEP1;						\
324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     argL = res + 1;						\
325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     argR = 1;							\
326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     cf = CC_NDEP & AMD64G_CC_MASK_C;				\
327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     pf = parity_table[(UChar)res];				\
328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     af = (res ^ argL ^ argR) & 0x10;				\
329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     zf = ((DATA_UTYPE)res == 0) << 6;				\
330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     sf = lshift(res, 8 - DATA_BITS) & 0x80;			\
331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     of = ((res & DATA_MASK) 					\
332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          == ((ULong)SIGN_MASK - 1)) << 11;			\
333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     return cf | pf | af | zf | sf | of;			\
334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }								\
335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-------------------------------------------------------------*/
338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ACTIONS_SHL(DATA_BITS,DATA_UTYPE)			\
340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{								\
341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PREAMBLE(DATA_BITS);						\
342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { Long cf, pf, af, zf, sf, of;				\
343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     cf = (CC_DEP2 >> (DATA_BITS - 1)) & AMD64G_CC_MASK_C;	\
344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     pf = parity_table[(UChar)CC_DEP1];				\
345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     af = 0; /* undefined */					\
346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     zf = ((DATA_UTYPE)CC_DEP1 == 0) << 6;			\
347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     sf = lshift(CC_DEP1, 8 - DATA_BITS) & 0x80;		\
348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* of is defined if shift count == 1 */			\
349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     of = lshift(CC_DEP2 ^ CC_DEP1, 12 - DATA_BITS) 		\
350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          & AMD64G_CC_MASK_O;					\
351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     return cf | pf | af | zf | sf | of;			\
352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }								\
353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-------------------------------------------------------------*/
356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ACTIONS_SHR(DATA_BITS,DATA_UTYPE)			\
358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{								\
359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PREAMBLE(DATA_BITS);  					\
360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { Long cf, pf, af, zf, sf, of;				\
361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     cf = CC_DEP2 & 1;						\
362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     pf = parity_table[(UChar)CC_DEP1];				\
363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     af = 0; /* undefined */					\
364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     zf = ((DATA_UTYPE)CC_DEP1 == 0) << 6;			\
365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     sf = lshift(CC_DEP1, 8 - DATA_BITS) & 0x80;		\
366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* of is defined if shift count == 1 */			\
367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     of = lshift(CC_DEP2 ^ CC_DEP1, 12 - DATA_BITS)		\
368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          & AMD64G_CC_MASK_O;					\
369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     return cf | pf | af | zf | sf | of;			\
370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }								\
371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-------------------------------------------------------------*/
374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ROL: cf' = lsb(result).  of' = msb(result) ^ lsb(result). */
376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DEP1 = result, NDEP = old flags */
377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ACTIONS_ROL(DATA_BITS,DATA_UTYPE)			\
378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{								\
379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PREAMBLE(DATA_BITS);						\
380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { Long fl 							\
381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        = (CC_NDEP & ~(AMD64G_CC_MASK_O | AMD64G_CC_MASK_C))	\
382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          | (AMD64G_CC_MASK_C & CC_DEP1)			\
383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          | (AMD64G_CC_MASK_O & (lshift(CC_DEP1,  		\
384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      11-(DATA_BITS-1)) 	\
385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     ^ lshift(CC_DEP1, 11)));			\
386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     return fl;							\
387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }								\
388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-------------------------------------------------------------*/
391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ROR: cf' = msb(result).  of' = msb(result) ^ msb-1(result). */
393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DEP1 = result, NDEP = old flags */
394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ACTIONS_ROR(DATA_BITS,DATA_UTYPE)			\
395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{								\
396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PREAMBLE(DATA_BITS);						\
397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { Long fl 							\
398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        = (CC_NDEP & ~(AMD64G_CC_MASK_O | AMD64G_CC_MASK_C))	\
399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          | (AMD64G_CC_MASK_C & (CC_DEP1 >> (DATA_BITS-1)))	\
400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          | (AMD64G_CC_MASK_O & (lshift(CC_DEP1, 		\
401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      11-(DATA_BITS-1)) 	\
402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     ^ lshift(CC_DEP1, 11-(DATA_BITS-1)+1)));	\
403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     return fl;							\
404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }								\
405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-------------------------------------------------------------*/
408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ACTIONS_UMUL(DATA_BITS, DATA_UTYPE,  NARROWtoU,         \
410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                DATA_U2TYPE, NARROWto2U)        \
411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{                                                               \
412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PREAMBLE(DATA_BITS);                                         \
413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { Long cf, pf, af, zf, sf, of;                               \
414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DATA_UTYPE  hi;                                            \
415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DATA_UTYPE  lo                                             \
416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        = NARROWtoU( ((DATA_UTYPE)CC_DEP1)                      \
417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     * ((DATA_UTYPE)CC_DEP2) );                 \
418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DATA_U2TYPE rr                                             \
419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        = NARROWto2U(                                           \
420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             ((DATA_U2TYPE)((DATA_UTYPE)CC_DEP1))               \
421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             * ((DATA_U2TYPE)((DATA_UTYPE)CC_DEP2)) );          \
422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     hi = NARROWtoU(rr >>/*u*/ DATA_BITS);                      \
423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     cf = (hi != 0);                                            \
424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     pf = parity_table[(UChar)lo];                              \
425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     af = 0; /* undefined */                                    \
426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     zf = (lo == 0) << 6;                                       \
427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     sf = lshift(lo, 8 - DATA_BITS) & 0x80;                     \
428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     of = cf << 11;                                             \
429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     return cf | pf | af | zf | sf | of;                        \
430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }								\
431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-------------------------------------------------------------*/
434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ACTIONS_SMUL(DATA_BITS, DATA_STYPE,  NARROWtoS,         \
436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                DATA_S2TYPE, NARROWto2S)        \
437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{                                                               \
438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PREAMBLE(DATA_BITS);                                         \
439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { Long cf, pf, af, zf, sf, of;                               \
440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DATA_STYPE  hi;                                            \
441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DATA_STYPE  lo                                             \
442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        = NARROWtoS( ((DATA_STYPE)CC_DEP1)                      \
443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     * ((DATA_STYPE)CC_DEP2) );                 \
444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DATA_S2TYPE rr                                             \
445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        = NARROWto2S(                                           \
446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             ((DATA_S2TYPE)((DATA_STYPE)CC_DEP1))               \
447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             * ((DATA_S2TYPE)((DATA_STYPE)CC_DEP2)) );          \
448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     hi = NARROWtoS(rr >>/*s*/ DATA_BITS);                      \
449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     cf = (hi != (lo >>/*s*/ (DATA_BITS-1)));                   \
450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     pf = parity_table[(UChar)lo];                              \
451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     af = 0; /* undefined */                                    \
452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     zf = (lo == 0) << 6;                                       \
453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     sf = lshift(lo, 8 - DATA_BITS) & 0x80;                     \
454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     of = cf << 11;                                             \
455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     return cf | pf | af | zf | sf | of;                        \
456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }								\
457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-------------------------------------------------------------*/
460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ACTIONS_UMULQ                                           \
462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{                                                               \
463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PREAMBLE(64);                                                \
464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { Long cf, pf, af, zf, sf, of;                               \
465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     ULong lo, hi;                                              \
466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     mullU64( (ULong)CC_DEP1, (ULong)CC_DEP2, &hi, &lo );       \
467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     cf = (hi != 0);                                            \
468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     pf = parity_table[(UChar)lo];                              \
469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     af = 0; /* undefined */                                    \
470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     zf = (lo == 0) << 6;                                       \
471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     sf = lshift(lo, 8 - 64) & 0x80;                            \
472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     of = cf << 11;                                             \
473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     return cf | pf | af | zf | sf | of;                        \
474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }								\
475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-------------------------------------------------------------*/
478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ACTIONS_SMULQ                                           \
480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{                                                               \
481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PREAMBLE(64);                                                \
482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { Long cf, pf, af, zf, sf, of;                               \
483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Long lo, hi;                                               \
484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     mullS64( (Long)CC_DEP1, (Long)CC_DEP2, &hi, &lo );         \
485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     cf = (hi != (lo >>/*s*/ (64-1)));                          \
486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     pf = parity_table[(UChar)lo];                              \
487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     af = 0; /* undefined */                                    \
488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     zf = (lo == 0) << 6;                                       \
489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     sf = lshift(lo, 8 - 64) & 0x80;                            \
490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     of = cf << 11;                                             \
491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     return cf | pf | af | zf | sf | of;                        \
492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }								\
493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
495436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*-------------------------------------------------------------*/
496436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
497436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#define ACTIONS_ANDN(DATA_BITS,DATA_UTYPE)			\
498436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{								\
499436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   PREAMBLE(DATA_BITS);						\
500436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   { Long cf, pf, af, zf, sf, of;				\
501436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     cf = 0;							\
502436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     pf = 0;							\
503436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     af = 0;							\
504436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     zf = ((DATA_UTYPE)CC_DEP1 == 0) << 6;			\
505436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     sf = lshift(CC_DEP1, 8 - DATA_BITS) & 0x80;		\
506436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     of = 0;							\
507436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     return cf | pf | af | zf | sf | of;			\
508436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }								\
509436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
510436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
511436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*-------------------------------------------------------------*/
512436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
513436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#define ACTIONS_BLSI(DATA_BITS,DATA_UTYPE)			\
514436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{								\
515436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   PREAMBLE(DATA_BITS);						\
516436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   { Long cf, pf, af, zf, sf, of;				\
517436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     cf = ((DATA_UTYPE)CC_DEP2 != 0);				\
518436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     pf = 0;							\
519436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     af = 0;							\
520436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     zf = ((DATA_UTYPE)CC_DEP1 == 0) << 6;			\
521436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     sf = lshift(CC_DEP1, 8 - DATA_BITS) & 0x80;		\
522436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     of = 0;							\
523436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     return cf | pf | af | zf | sf | of;			\
524436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }								\
525436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
526436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
527436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*-------------------------------------------------------------*/
528436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
529436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#define ACTIONS_BLSMSK(DATA_BITS,DATA_UTYPE)			\
530436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{								\
531436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   PREAMBLE(DATA_BITS);						\
532436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   { Long cf, pf, af, zf, sf, of;				\
533436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     cf = ((DATA_UTYPE)CC_DEP2 == 0);				\
534436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     pf = 0;							\
535436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     af = 0;							\
536436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     zf = 0;							\
537436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     sf = lshift(CC_DEP1, 8 - DATA_BITS) & 0x80;		\
538436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     of = 0;							\
539436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     return cf | pf | af | zf | sf | of;			\
540436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }								\
541436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
542436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
543436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*-------------------------------------------------------------*/
544436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
545436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#define ACTIONS_BLSR(DATA_BITS,DATA_UTYPE)			\
546436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{								\
547436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   PREAMBLE(DATA_BITS);						\
548436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   { Long cf, pf, af, zf, sf, of;				\
549436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     cf = ((DATA_UTYPE)CC_DEP2 == 0);				\
550436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     pf = 0;							\
551436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     af = 0;							\
552436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     zf = ((DATA_UTYPE)CC_DEP1 == 0) << 6;			\
553436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     sf = lshift(CC_DEP1, 8 - DATA_BITS) & 0x80;		\
554436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     of = 0;							\
555436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     return cf | pf | af | zf | sf | of;			\
556436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }								\
557436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
558436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
559436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*-------------------------------------------------------------*/
560436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if PROFILE_RFLAGS
563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool initted     = False;
565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* C flag, fast route */
567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt tabc_fast[AMD64G_CC_OP_NUMBER];
568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* C flag, slow route */
569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt tabc_slow[AMD64G_CC_OP_NUMBER];
570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* table for calculate_cond */
571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt tab_cond[AMD64G_CC_OP_NUMBER][16];
572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* total entry counts for calc_all, calc_c, calc_cond. */
573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt n_calc_all  = 0;
574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt n_calc_c    = 0;
575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt n_calc_cond = 0;
576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHOW_COUNTS_NOW (0 == (0x3FFFFF & (n_calc_all+n_calc_c+n_calc_cond)))
578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void showCounts ( void )
581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int op, co;
583436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   HChar ch;
584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("\nTotal calls: calc_all=%u   calc_cond=%u   calc_c=%u\n",
585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              n_calc_all, n_calc_cond, n_calc_c);
586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("      cSLOW  cFAST    O   NO    B   NB    Z   NZ   BE  NBE"
588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              "    S   NS    P   NP    L   NL   LE  NLE\n");
589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("     -----------------------------------------------------"
590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              "----------------------------------------\n");
591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (op = 0; op < AMD64G_CC_OP_NUMBER; op++) {
592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ch = ' ';
594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (op > 0 && (op-1) % 4 == 0)
595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ch = 'B';
596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (op > 0 && (op-1) % 4 == 1)
597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ch = 'W';
598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (op > 0 && (op-1) % 4 == 2)
599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ch = 'L';
600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (op > 0 && (op-1) % 4 == 3)
601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ch = 'Q';
602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("%2d%c: ", op, ch);
604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("%6u ", tabc_slow[op]);
605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("%6u ", tabc_fast[op]);
606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (co = 0; co < 16; co++) {
607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Int n = tab_cond[op][co];
608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (n >= 1000) {
609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf(" %3dK", n / 1000);
610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else
611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (n >= 0) {
612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf(" %3d ", n );
613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("     ");
615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\n");
618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("\n");
620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void initCounts ( void )
623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int op, co;
625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   initted = True;
626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (op = 0; op < AMD64G_CC_OP_NUMBER; op++) {
627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tabc_fast[op] = tabc_slow[op] = 0;
628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (co = 0; co < 16; co++)
629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tab_cond[op][co] = 0;
630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif /* PROFILE_RFLAGS */
634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CALLED FROM GENERATED CODE: CLEAN HELPER */
637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Calculate all the 6 flags from the supplied thunk parameters.
638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Worker function, not directly called from generated code. */
639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong amd64g_calculate_rflags_all_WRK ( ULong cc_op,
641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        ULong cc_dep1_formal,
642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        ULong cc_dep2_formal,
643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        ULong cc_ndep_formal )
644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (cc_op) {
646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_COPY:
647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return cc_dep1_formal
648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                & (AMD64G_CC_MASK_O | AMD64G_CC_MASK_S | AMD64G_CC_MASK_Z
649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   | AMD64G_CC_MASK_A | AMD64G_CC_MASK_C | AMD64G_CC_MASK_P);
650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_ADDB:   ACTIONS_ADD( 8,  UChar  );
652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_ADDW:   ACTIONS_ADD( 16, UShort );
653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_ADDL:   ACTIONS_ADD( 32, UInt   );
654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_ADDQ:   ACTIONS_ADD( 64, ULong  );
655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_ADCB:   ACTIONS_ADC( 8,  UChar  );
657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_ADCW:   ACTIONS_ADC( 16, UShort );
658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_ADCL:   ACTIONS_ADC( 32, UInt   );
659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_ADCQ:   ACTIONS_ADC( 64, ULong  );
660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_SUBB:   ACTIONS_SUB(  8, UChar  );
662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_SUBW:   ACTIONS_SUB( 16, UShort );
663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_SUBL:   ACTIONS_SUB( 32, UInt   );
664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_SUBQ:   ACTIONS_SUB( 64, ULong  );
665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_SBBB:   ACTIONS_SBB(  8, UChar  );
667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_SBBW:   ACTIONS_SBB( 16, UShort );
668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_SBBL:   ACTIONS_SBB( 32, UInt   );
669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_SBBQ:   ACTIONS_SBB( 64, ULong  );
670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_LOGICB: ACTIONS_LOGIC(  8, UChar  );
672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_LOGICW: ACTIONS_LOGIC( 16, UShort );
673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_LOGICL: ACTIONS_LOGIC( 32, UInt   );
674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_LOGICQ: ACTIONS_LOGIC( 64, ULong  );
675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_INCB:   ACTIONS_INC(  8, UChar  );
677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_INCW:   ACTIONS_INC( 16, UShort );
678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_INCL:   ACTIONS_INC( 32, UInt   );
679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_INCQ:   ACTIONS_INC( 64, ULong  );
680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_DECB:   ACTIONS_DEC(  8, UChar  );
682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_DECW:   ACTIONS_DEC( 16, UShort );
683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_DECL:   ACTIONS_DEC( 32, UInt   );
684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_DECQ:   ACTIONS_DEC( 64, ULong  );
685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_SHLB:   ACTIONS_SHL(  8, UChar  );
687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_SHLW:   ACTIONS_SHL( 16, UShort );
688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_SHLL:   ACTIONS_SHL( 32, UInt   );
689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_SHLQ:   ACTIONS_SHL( 64, ULong  );
690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_SHRB:   ACTIONS_SHR(  8, UChar  );
692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_SHRW:   ACTIONS_SHR( 16, UShort );
693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_SHRL:   ACTIONS_SHR( 32, UInt   );
694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_SHRQ:   ACTIONS_SHR( 64, ULong  );
695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_ROLB:   ACTIONS_ROL(  8, UChar  );
697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_ROLW:   ACTIONS_ROL( 16, UShort );
698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_ROLL:   ACTIONS_ROL( 32, UInt   );
699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_ROLQ:   ACTIONS_ROL( 64, ULong  );
700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_RORB:   ACTIONS_ROR(  8, UChar  );
702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_RORW:   ACTIONS_ROR( 16, UShort );
703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_RORL:   ACTIONS_ROR( 32, UInt   );
704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_RORQ:   ACTIONS_ROR( 64, ULong  );
705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_UMULB:  ACTIONS_UMUL(  8, UChar,  toUChar,
707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                  UShort, toUShort );
708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_UMULW:  ACTIONS_UMUL( 16, UShort, toUShort,
709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                  UInt,   toUInt );
710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_UMULL:  ACTIONS_UMUL( 32, UInt,   toUInt,
711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                  ULong,  idULong );
712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_UMULQ:  ACTIONS_UMULQ;
714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_SMULB:  ACTIONS_SMUL(  8, Char,   toUChar,
716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                  Short,  toUShort );
717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_SMULW:  ACTIONS_SMUL( 16, Short,  toUShort,
718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                  Int,    toUInt   );
719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_SMULL:  ACTIONS_SMUL( 32, Int,    toUInt,
720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                  Long,   idULong );
721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_SMULQ:  ACTIONS_SMULQ;
723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
724436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case AMD64G_CC_OP_ANDN32: ACTIONS_ANDN( 32, UInt   );
725436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case AMD64G_CC_OP_ANDN64: ACTIONS_ANDN( 64, ULong  );
726436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
727436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case AMD64G_CC_OP_BLSI32: ACTIONS_BLSI( 32, UInt   );
728436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case AMD64G_CC_OP_BLSI64: ACTIONS_BLSI( 64, ULong  );
729436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
730436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case AMD64G_CC_OP_BLSMSK32: ACTIONS_BLSMSK( 32, UInt   );
731436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case AMD64G_CC_OP_BLSMSK64: ACTIONS_BLSMSK( 64, ULong  );
732436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
733436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case AMD64G_CC_OP_BLSR32: ACTIONS_BLSR( 32, UInt   );
734436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case AMD64G_CC_OP_BLSR64: ACTIONS_BLSR( 64, ULong  );
735436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* shouldn't really make these calls from generated code */
738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("amd64g_calculate_rflags_all_WRK(AMD64)"
739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    "( %llu, 0x%llx, 0x%llx, 0x%llx )\n",
740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    cc_op, cc_dep1_formal, cc_dep2_formal, cc_ndep_formal );
741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("amd64g_calculate_rflags_all_WRK(AMD64)");
742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CALLED FROM GENERATED CODE: CLEAN HELPER */
747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Calculate all the 6 flags from the supplied thunk parameters. */
748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong amd64g_calculate_rflags_all ( ULong cc_op,
749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    ULong cc_dep1,
750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    ULong cc_dep2,
751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    ULong cc_ndep )
752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if PROFILE_RFLAGS
754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!initted) initCounts();
755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n_calc_all++;
756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (SHOW_COUNTS_NOW) showCounts();
757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return
759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      amd64g_calculate_rflags_all_WRK ( cc_op, cc_dep1, cc_dep2, cc_ndep );
760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CALLED FROM GENERATED CODE: CLEAN HELPER */
764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Calculate just the carry flag from the supplied thunk parameters. */
765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong amd64g_calculate_rflags_c ( ULong cc_op,
766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  ULong cc_dep1,
767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  ULong cc_dep2,
768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  ULong cc_ndep )
769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if PROFILE_RFLAGS
771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!initted) initCounts();
772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n_calc_c++;
773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tabc_fast[cc_op]++;
774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (SHOW_COUNTS_NOW) showCounts();
775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Fast-case some common ones. */
778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (cc_op) {
779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_COPY:
780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return (cc_dep1 >> AMD64G_CC_SHIFT_C) & 1;
781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_LOGICQ:
782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_LOGICL:
783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_LOGICW:
784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_LOGICB:
785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return 0;
786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 //      case AMD64G_CC_OP_SUBL:
787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 //         return ((UInt)cc_dep1) < ((UInt)cc_dep2)
788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 //                   ? AMD64G_CC_MASK_C : 0;
789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 //      case AMD64G_CC_OP_SUBW:
790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 //         return ((UInt)(cc_dep1 & 0xFFFF)) < ((UInt)(cc_dep2 & 0xFFFF))
791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 //                   ? AMD64G_CC_MASK_C : 0;
792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 //      case AMD64G_CC_OP_SUBB:
793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 //         return ((UInt)(cc_dep1 & 0xFF)) < ((UInt)(cc_dep2 & 0xFF))
794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 //                   ? AMD64G_CC_MASK_C : 0;
795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 //      case AMD64G_CC_OP_INCL:
796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 //      case AMD64G_CC_OP_DECL:
797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 //         return cc_ndep & AMD64G_CC_MASK_C;
798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if PROFILE_RFLAGS
803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tabc_fast[cc_op]--;
804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tabc_slow[cc_op]++;
805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return amd64g_calculate_rflags_all_WRK(cc_op,cc_dep1,cc_dep2,cc_ndep)
808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          & AMD64G_CC_MASK_C;
809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CALLED FROM GENERATED CODE: CLEAN HELPER */
813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* returns 1 or 0 */
814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong amd64g_calculate_condition ( ULong/*AMD64Condcode*/ cond,
815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   ULong cc_op,
816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   ULong cc_dep1,
817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   ULong cc_dep2,
818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   ULong cc_ndep )
819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong rflags = amd64g_calculate_rflags_all_WRK(cc_op, cc_dep1,
821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                  cc_dep2, cc_ndep);
822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong of,sf,zf,cf,pf;
823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong inv = cond & 1;
824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if PROFILE_RFLAGS
826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!initted) initCounts();
827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tab_cond[cc_op][cond]++;
828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n_calc_cond++;
829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (SHOW_COUNTS_NOW) showCounts();
830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (cond) {
833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64CondNO:
834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64CondO: /* OF == 1 */
835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         of = rflags >> AMD64G_CC_SHIFT_O;
836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return 1 & (inv ^ of);
837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64CondNZ:
839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64CondZ: /* ZF == 1 */
840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         zf = rflags >> AMD64G_CC_SHIFT_Z;
841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return 1 & (inv ^ zf);
842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64CondNB:
844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64CondB: /* CF == 1 */
845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cf = rflags >> AMD64G_CC_SHIFT_C;
846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return 1 & (inv ^ cf);
847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64CondNBE:
850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64CondBE: /* (CF or ZF) == 1 */
851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cf = rflags >> AMD64G_CC_SHIFT_C;
852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         zf = rflags >> AMD64G_CC_SHIFT_Z;
853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return 1 & (inv ^ (cf | zf));
854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64CondNS:
857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64CondS: /* SF == 1 */
858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         sf = rflags >> AMD64G_CC_SHIFT_S;
859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return 1 & (inv ^ sf);
860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64CondNP:
862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64CondP: /* PF == 1 */
863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         pf = rflags >> AMD64G_CC_SHIFT_P;
864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return 1 & (inv ^ pf);
865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64CondNL:
867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64CondL: /* (SF xor OF) == 1 */
868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         sf = rflags >> AMD64G_CC_SHIFT_S;
869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         of = rflags >> AMD64G_CC_SHIFT_O;
870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return 1 & (inv ^ (sf ^ of));
871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64CondNLE:
874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64CondLE: /* ((SF xor OF) or ZF)  == 1 */
875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         sf = rflags >> AMD64G_CC_SHIFT_S;
876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         of = rflags >> AMD64G_CC_SHIFT_O;
877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         zf = rflags >> AMD64G_CC_SHIFT_Z;
878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return 1 & (inv ^ ((sf ^ of) | zf));
879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* shouldn't really make these calls from generated code */
883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("amd64g_calculate_condition"
884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    "( %llu, %llu, 0x%llx, 0x%llx, 0x%llx )\n",
885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    cond, cc_op, cc_dep1, cc_dep2, cc_ndep );
886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("amd64g_calculate_condition");
887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* VISIBLE TO LIBVEX CLIENT */
892436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovULong LibVEX_GuestAMD64_get_rflags ( /*IN*/const VexGuestAMD64State* vex_state )
893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong rflags = amd64g_calculate_rflags_all_WRK(
895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vex_state->guest_CC_OP,
896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vex_state->guest_CC_DEP1,
897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vex_state->guest_CC_DEP2,
898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vex_state->guest_CC_NDEP
899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  );
900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Long dflag = vex_state->guest_DFLAG;
901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(dflag == 1 || dflag == -1);
902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (dflag == -1)
903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      rflags |= (1<<10);
904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vex_state->guest_IDFLAG == 1)
905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      rflags |= (1<<21);
906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vex_state->guest_ACFLAG == 1)
907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      rflags |= (1<<18);
908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return rflags;
910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* VISIBLE TO LIBVEX CLIENT */
913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid
914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownLibVEX_GuestAMD64_put_rflag_c ( ULong new_carry_flag,
915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               /*MOD*/VexGuestAMD64State* vex_state )
916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong oszacp = amd64g_calculate_rflags_all_WRK(
918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vex_state->guest_CC_OP,
919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vex_state->guest_CC_DEP1,
920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vex_state->guest_CC_DEP2,
921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vex_state->guest_CC_NDEP
922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  );
923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (new_carry_flag & 1) {
924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      oszacp |= AMD64G_CC_MASK_C;
925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      oszacp &= ~AMD64G_CC_MASK_C;
927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_state->guest_CC_OP   = AMD64G_CC_OP_COPY;
929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_state->guest_CC_DEP1 = oszacp;
930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_state->guest_CC_DEP2 = 0;
931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_state->guest_CC_NDEP = 0;
932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- %rflags translation-time function specialisers.         ---*/
937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- These help iropt specialise calls the above run-time    ---*/
938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- %rflags functions.                                      ---*/
939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Used by the optimiser to try specialisations.  Returns an
942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   equivalent expression, or NULL if none. */
943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool isU64 ( IRExpr* e, ULong n )
945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toBool( e->tag == Iex_Const
947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  && e->Iex.Const.con->tag == Ico_U64
948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  && e->Iex.Const.con->Ico.U64 == n );
949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
951436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovIRExpr* guest_amd64_spechelper ( const HChar* function_name,
952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 IRExpr** args,
953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 IRStmt** precedingStmts,
954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 Int      n_precedingStmts )
955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define unop(_op,_a1) IRExpr_Unop((_op),(_a1))
957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define binop(_op,_a1,_a2) IRExpr_Binop((_op),(_a1),(_a2))
958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define mkU64(_n) IRExpr_Const(IRConst_U64(_n))
959b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#  define mkU32(_n) IRExpr_Const(IRConst_U32(_n))
960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define mkU8(_n)  IRExpr_Const(IRConst_U8(_n))
961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i, arity = 0;
963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; args[i]; i++)
964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      arity++;
965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if 0
966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("spec request:\n");
967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("   %s  ", function_name);
968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < arity; i++) {
969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("  ");
970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRExpr(args[i]);
971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("\n");
973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- specialising "amd64g_calculate_condition" --------- */
976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vex_streq(function_name, "amd64g_calculate_condition")) {
978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* specialise calls to above "calculate condition" function */
979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRExpr *cond, *cc_op, *cc_dep1, *cc_dep2;
980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(arity == 5);
981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cond    = args[0];
982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cc_op   = args[1];
983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cc_dep1 = args[2];
984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cc_dep2 = args[3];
985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*---------------- ADDQ ----------------*/
987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_ADDQ) && isU64(cond, AMD64CondZ)) {
989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* long long add, then Z --> test (dst+src == 0) */
990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_CmpEQ64,
992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           binop(Iop_Add64, cc_dep1, cc_dep2),
993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           mkU64(0)));
994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*---------------- SUBQ ----------------*/
997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_SUBQ) && isU64(cond, AMD64CondZ)) {
999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* long long sub/cmp, then Z --> test dst==src */
1000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_CmpEQ64,cc_dep1,cc_dep2));
1002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_SUBQ) && isU64(cond, AMD64CondNZ)) {
1004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* long long sub/cmp, then NZ --> test dst!=src */
1005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_CmpNE64,cc_dep1,cc_dep2));
1007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_SUBQ) && isU64(cond, AMD64CondL)) {
1010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* long long sub/cmp, then L (signed less than)
1011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            --> test dst <s src */
1012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_CmpLT64S, cc_dep1, cc_dep2));
1014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_SUBQ) && isU64(cond, AMD64CondB)) {
1017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* long long sub/cmp, then B (unsigned less than)
1018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            --> test dst <u src */
1019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_CmpLT64U, cc_dep1, cc_dep2));
1021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_SUBQ) && isU64(cond, AMD64CondNB)) {
1023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* long long sub/cmp, then NB (unsigned greater than or equal)
1024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            --> test src <=u dst */
1025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Note, args are opposite way round from the usual */
1026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_CmpLE64U, cc_dep2, cc_dep1));
1028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1030436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (isU64(cc_op, AMD64G_CC_OP_SUBQ) && isU64(cond, AMD64CondNLE)) {
1031436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* long sub/cmp, then NLE (signed greater than)
1032436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            --> test !(dst <=s src)
1033436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            --> test (dst >s src)
1034436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            --> test (src <s dst) */
1035436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return unop(Iop_1Uto64,
1036436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                     binop(Iop_CmpLT64S, cc_dep2, cc_dep1));
1037436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1038436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
1039436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_SUBQ) && isU64(cond, AMD64CondBE)) {
1041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* long long sub/cmp, then BE (unsigned less than or equal)
1042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            --> test dst <=u src */
1043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_CmpLE64U, cc_dep1, cc_dep2));
1045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1046663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (isU64(cc_op, AMD64G_CC_OP_SUBQ) && isU64(cond, AMD64CondNBE)) {
1047663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* long long sub/cmp, then NBE (unsigned greater than)
1048663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            --> test !(dst <=u src) */
1049663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return binop(Iop_Xor64,
1050663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      unop(Iop_1Uto64,
1051663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           binop(Iop_CmpLE64U, cc_dep1, cc_dep2)),
1052663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      mkU64(1));
1053663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
1054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*---------------- SUBL ----------------*/
1056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondZ)) {
1058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* long sub/cmp, then Z --> test dst==src */
1059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1060b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     binop(Iop_CmpEQ32,
1061b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop(Iop_64to32, cc_dep1),
1062b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop(Iop_64to32, cc_dep2)));
1063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondNZ)) {
1065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* long sub/cmp, then NZ --> test dst!=src */
1066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1067b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     binop(Iop_CmpNE32,
1068b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop(Iop_64to32, cc_dep1),
1069b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop(Iop_64to32, cc_dep2)));
1070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondL)) {
1073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* long sub/cmp, then L (signed less than)
1074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            --> test dst <s src */
1075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1076b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     binop(Iop_CmpLT32S,
1077b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop(Iop_64to32, cc_dep1),
1078b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop(Iop_64to32, cc_dep2)));
1079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondLE)) {
1082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* long sub/cmp, then LE (signed less than or equal)
1083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            --> test dst <=s src */
1084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1085b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     binop(Iop_CmpLE32S,
1086b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop(Iop_64to32, cc_dep1),
1087b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop(Iop_64to32, cc_dep2)));
1088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondNLE)) {
1091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* long sub/cmp, then NLE (signed greater than)
1092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            --> test !(dst <=s src)
1093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            --> test (dst >s src)
1094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            --> test (src <s dst) */
1095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1096b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     binop(Iop_CmpLT32S,
1097b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop(Iop_64to32, cc_dep2),
1098b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop(Iop_64to32, cc_dep1)));
1099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondBE)) {
1103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* long sub/cmp, then BE (unsigned less than or equal)
1104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            --> test dst <=u src */
1105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1106b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     binop(Iop_CmpLE32U,
1107b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop(Iop_64to32, cc_dep1),
1108b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop(Iop_64to32, cc_dep2)));
1109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondNBE)) {
1111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* long sub/cmp, then NBE (unsigned greater than)
1112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            --> test src <u dst */
1113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Note, args are opposite way round from the usual */
1114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1115b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     binop(Iop_CmpLT32U,
1116b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop(Iop_64to32, cc_dep2),
1117b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop(Iop_64to32, cc_dep1)));
1118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondS)) {
1121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* long sub/cmp, then S (negative) --> test (dst-src <s 0) */
1122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1123b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     binop(Iop_CmpLT32S,
1124b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           binop(Iop_Sub32,
1125b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 unop(Iop_64to32, cc_dep1),
1126b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 unop(Iop_64to32, cc_dep2)),
1127b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           mkU32(0)));
1128b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
1129b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1130b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondB)) {
1131b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* long sub/cmp, then B (unsigned less than)
1132b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            --> test dst <u src */
1133b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return unop(Iop_1Uto64,
1134b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     binop(Iop_CmpLT32U,
1135b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop(Iop_64to32, cc_dep1),
1136b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop(Iop_64to32, cc_dep2)));
1137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*---------------- SUBW ----------------*/
1140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_SUBW) && isU64(cond, AMD64CondZ)) {
1142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* word sub/cmp, then Z --> test dst==src */
1143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_CmpEQ16,
1145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           unop(Iop_64to16,cc_dep1),
1146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           unop(Iop_64to16,cc_dep2)));
1147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_SUBW) && isU64(cond, AMD64CondNZ)) {
1149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* word sub/cmp, then NZ --> test dst!=src */
1150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_CmpNE16,
1152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           unop(Iop_64to16,cc_dep1),
1153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           unop(Iop_64to16,cc_dep2)));
1154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_SUBW) && isU64(cond, AMD64CondLE)) {
1157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* word sub/cmp, then LE (signed less than or equal)
1158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            --> test dst <=s src */
1159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_CmpLE64S,
1161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           binop(Iop_Shl64,cc_dep1,mkU8(48)),
1162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           binop(Iop_Shl64,cc_dep2,mkU8(48))));
1163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*---------------- SUBB ----------------*/
1167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_SUBB) && isU64(cond, AMD64CondZ)) {
1169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* byte sub/cmp, then Z --> test dst==src */
1170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_CmpEQ8,
1172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           unop(Iop_64to8,cc_dep1),
1173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           unop(Iop_64to8,cc_dep2)));
1174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_SUBB) && isU64(cond, AMD64CondNZ)) {
1176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* byte sub/cmp, then NZ --> test dst!=src */
1177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_CmpNE8,
1179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           unop(Iop_64to8,cc_dep1),
1180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           unop(Iop_64to8,cc_dep2)));
1181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1183b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (isU64(cc_op, AMD64G_CC_OP_SUBB) && isU64(cond, AMD64CondBE)) {
1184b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* byte sub/cmp, then BE (unsigned less than or equal)
1185b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            --> test dst <=u src */
1186b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return unop(Iop_1Uto64,
1187b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     binop(Iop_CmpLE64U,
1188b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           binop(Iop_And64, cc_dep1, mkU64(0xFF)),
1189b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           binop(Iop_And64, cc_dep2, mkU64(0xFF))));
1190b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
1191b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_SUBB) && isU64(cond, AMD64CondS)
1193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          && isU64(cc_dep2, 0)) {
1194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* byte sub/cmp of zero, then S --> test (dst-0 <s 0)
1195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         --> test dst <s 0
1196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         --> (ULong)dst[7]
1197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            This is yet another scheme by which gcc figures out if the
1198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            top bit of a byte is 1 or 0.  See also LOGICB/CondS below. */
1199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Note: isU64(cc_dep2, 0) is correct, even though this is
1200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for an 8-bit comparison, since the args to the helper
1201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            function are always U64s. */
1202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return binop(Iop_And64,
1203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_Shr64,cc_dep1,mkU8(7)),
1204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      mkU64(1));
1205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_SUBB) && isU64(cond, AMD64CondNS)
1207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          && isU64(cc_dep2, 0)) {
1208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* byte sub/cmp of zero, then NS --> test !(dst-0 <s 0)
1209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          --> test !(dst <s 0)
1210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          --> (ULong) !dst[7]
1211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         */
1212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return binop(Iop_Xor64,
1213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_And64,
1214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(Iop_Shr64,cc_dep1,mkU8(7)),
1215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkU64(1)),
1216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      mkU64(1));
1217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*---------------- LOGICQ ----------------*/
1220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_LOGICQ) && isU64(cond, AMD64CondZ)) {
1222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* long long and/or/xor, then Z --> test dst==0 */
1223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_CmpEQ64, cc_dep1, mkU64(0)));
1225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1226b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (isU64(cc_op, AMD64G_CC_OP_LOGICQ) && isU64(cond, AMD64CondNZ)) {
1227b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* long long and/or/xor, then NZ --> test dst!=0 */
1228b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return unop(Iop_1Uto64,
1229b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     binop(Iop_CmpNE64, cc_dep1, mkU64(0)));
1230b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
1231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_LOGICQ) && isU64(cond, AMD64CondL)) {
1233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* long long and/or/xor, then L
1234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            LOGIC sets SF and ZF according to the
1235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            result and makes OF be zero.  L computes SF ^ OF, but
1236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            OF is zero, so this reduces to SF -- which will be 1 iff
1237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            the result is < signed 0.  Hence ...
1238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         */
1239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_CmpLT64S,
1241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           cc_dep1,
1242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           mkU64(0)));
1243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*---------------- LOGICL ----------------*/
1246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_LOGICL) && isU64(cond, AMD64CondZ)) {
1248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* long and/or/xor, then Z --> test dst==0 */
1249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1250b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     binop(Iop_CmpEQ32,
1251b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop(Iop_64to32, cc_dep1),
1252b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           mkU32(0)));
1253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_LOGICL) && isU64(cond, AMD64CondNZ)) {
1255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* long and/or/xor, then NZ --> test dst!=0 */
1256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1257b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     binop(Iop_CmpNE32,
1258b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop(Iop_64to32, cc_dep1),
1259b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           mkU32(0)));
1260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_LOGICL) && isU64(cond, AMD64CondLE)) {
1263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* long and/or/xor, then LE
1264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            This is pretty subtle.  LOGIC sets SF and ZF according to the
1265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            result and makes OF be zero.  LE computes (SF ^ OF) | ZF, but
1266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            OF is zero, so this reduces to SF | ZF -- which will be 1 iff
1267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            the result is <=signed 0.  Hence ...
1268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         */
1269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1270b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     binop(Iop_CmpLE32S,
1271b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop(Iop_64to32, cc_dep1),
1272b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           mkU32(0)));
1273b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
1274b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1275b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (isU64(cc_op, AMD64G_CC_OP_LOGICL) && isU64(cond, AMD64CondS)) {
1276b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* long and/or/xor, then S --> (ULong)result[31] */
1277b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return binop(Iop_And64,
1278b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                      binop(Iop_Shr64, cc_dep1, mkU8(31)),
1279b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                      mkU64(1));
1280b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
1281b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (isU64(cc_op, AMD64G_CC_OP_LOGICL) && isU64(cond, AMD64CondNS)) {
1282b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* long and/or/xor, then S --> (ULong) ~ result[31] */
1283b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return binop(Iop_Xor64,
1284b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                binop(Iop_And64,
1285b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                      binop(Iop_Shr64, cc_dep1, mkU8(31)),
1286b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                      mkU64(1)),
1287b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                mkU64(1));
1288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1290663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /*---------------- LOGICW ----------------*/
1291663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1292663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (isU64(cc_op, AMD64G_CC_OP_LOGICW) && isU64(cond, AMD64CondZ)) {
1293663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* word and/or/xor, then Z --> test dst==0 */
1294663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return unop(Iop_1Uto64,
1295663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     binop(Iop_CmpEQ64,
1296663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           binop(Iop_And64, cc_dep1, mkU64(0xFFFF)),
1297663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           mkU64(0)));
1298663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
1299663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (isU64(cc_op, AMD64G_CC_OP_LOGICW) && isU64(cond, AMD64CondNZ)) {
1300663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* word and/or/xor, then NZ --> test dst!=0 */
1301663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return unop(Iop_1Uto64,
1302663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     binop(Iop_CmpNE64,
1303663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           binop(Iop_And64, cc_dep1, mkU64(0xFFFF)),
1304663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           mkU64(0)));
1305663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
1306663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*---------------- LOGICB ----------------*/
1308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_LOGICB) && isU64(cond, AMD64CondZ)) {
1310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* byte and/or/xor, then Z --> test dst==0 */
1311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_CmpEQ64, binop(Iop_And64,cc_dep1,mkU64(255)),
1313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        mkU64(0)));
1314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_LOGICB) && isU64(cond, AMD64CondNZ)) {
1316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* byte and/or/xor, then NZ --> test dst!=0 */
1317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_CmpNE64, binop(Iop_And64,cc_dep1,mkU64(255)),
1319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        mkU64(0)));
1320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_LOGICB) && isU64(cond, AMD64CondS)) {
1323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* this is an idiom gcc sometimes uses to find out if the top
1324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bit of a byte register is set: eg testb %al,%al; js ..
1325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Since it just depends on the top bit of the byte, extract
1326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            that bit and explicitly get rid of all the rest.  This
1327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            helps memcheck avoid false positives in the case where any
1328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            of the other bits in the byte are undefined. */
1329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* byte and/or/xor, then S --> (UInt)result[7] */
1330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return binop(Iop_And64,
1331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_Shr64,cc_dep1,mkU8(7)),
1332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      mkU64(1));
1333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1334b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (isU64(cc_op, AMD64G_CC_OP_LOGICB) && isU64(cond, AMD64CondNS)) {
1335b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* byte and/or/xor, then NS --> (UInt)!result[7] */
1336b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return binop(Iop_Xor64,
1337b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                      binop(Iop_And64,
1338b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                            binop(Iop_Shr64,cc_dep1,mkU8(7)),
1339b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                            mkU64(1)),
1340b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                      mkU64(1));
1341b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
1342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*---------------- INCB ----------------*/
1344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_INCB) && isU64(cond, AMD64CondLE)) {
1346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* 8-bit inc, then LE --> sign bit of the arg */
1347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return binop(Iop_And64,
1348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_Shr64,
1349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(Iop_Sub64, cc_dep1, mkU64(1)),
1350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkU8(7)),
1351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      mkU64(1));
1352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*---------------- INCW ----------------*/
1355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_INCW) && isU64(cond, AMD64CondZ)) {
1357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* 16-bit inc, then Z --> test dst == 0 */
1358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_CmpEQ64,
1360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           binop(Iop_Shl64,cc_dep1,mkU8(48)),
1361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           mkU64(0)));
1362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*---------------- DECL ----------------*/
1365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_DECL) && isU64(cond, AMD64CondZ)) {
1367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* dec L, then Z --> test dst == 0 */
1368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1369b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     binop(Iop_CmpEQ32,
1370b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop(Iop_64to32, cc_dep1),
1371b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           mkU32(0)));
1372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*---------------- DECW ----------------*/
1375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_DECW) && isU64(cond, AMD64CondNZ)) {
1377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* 16-bit dec, then NZ --> test dst != 0 */
1378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_CmpNE64,
1380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           binop(Iop_Shl64,cc_dep1,mkU8(48)),
1381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           mkU64(0)));
1382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*---------------- COPY ----------------*/
1385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* This can happen, as a result of amd64 FP compares: "comisd ... ;
1386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         jbe" for example. */
1387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_COPY) &&
1389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          (isU64(cond, AMD64CondBE) || isU64(cond, AMD64CondNBE))) {
1390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* COPY, then BE --> extract C and Z from dep1, and test (C
1391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            or Z == 1). */
1392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* COPY, then NBE --> extract C and Z from dep1, and test (C
1393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            or Z == 0). */
1394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ULong nnn = isU64(cond, AMD64CondBE) ? 1 : 0;
1395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return
1396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            unop(
1397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Iop_1Uto64,
1398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(
1399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  Iop_CmpEQ64,
1400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(
1401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     Iop_And64,
1402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(
1403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        Iop_Or64,
1404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_Shr64, cc_dep1, mkU8(AMD64G_CC_SHIFT_C)),
1405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_Shr64, cc_dep1, mkU8(AMD64G_CC_SHIFT_Z))
1406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     ),
1407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkU64(1)
1408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  ),
1409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  mkU64(nnn)
1410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               )
1411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            );
1412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_COPY) && isU64(cond, AMD64CondB)) {
1415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* COPY, then B --> extract C dep1, and test (C == 1). */
1416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return
1417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            unop(
1418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Iop_1Uto64,
1419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(
1420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  Iop_CmpNE64,
1421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(
1422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     Iop_And64,
1423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_Shr64, cc_dep1, mkU8(AMD64G_CC_SHIFT_C)),
1424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkU64(1)
1425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  ),
1426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  mkU64(0)
1427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               )
1428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            );
1429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_COPY)
1432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && (isU64(cond, AMD64CondZ) || isU64(cond, AMD64CondNZ))) {
1433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* COPY, then Z --> extract Z from dep1, and test (Z == 1). */
1434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* COPY, then NZ --> extract Z from dep1, and test (Z == 0). */
1435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt nnn = isU64(cond, AMD64CondZ) ? 1 : 0;
1436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return
1437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            unop(
1438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Iop_1Uto64,
1439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(
1440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  Iop_CmpEQ64,
1441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(
1442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     Iop_And64,
1443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_Shr64, cc_dep1, mkU8(AMD64G_CC_SHIFT_Z)),
1444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkU64(1)
1445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  ),
1446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  mkU64(nnn)
1447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               )
1448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            );
1449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_COPY) && isU64(cond, AMD64CondP)) {
1452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* COPY, then P --> extract P from dep1, and test (P == 1). */
1453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return
1454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            unop(
1455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Iop_1Uto64,
1456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(
1457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  Iop_CmpNE64,
1458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(
1459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     Iop_And64,
1460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_Shr64, cc_dep1, mkU8(AMD64G_CC_SHIFT_P)),
1461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkU64(1)
1462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  ),
1463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  mkU64(0)
1464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               )
1465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            );
1466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return NULL;
1469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- specialising "amd64g_calculate_rflags_c" --------- */
1472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vex_streq(function_name, "amd64g_calculate_rflags_c")) {
1474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* specialise calls to above "calculate_rflags_c" function */
1475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRExpr *cc_op, *cc_dep1, *cc_dep2, *cc_ndep;
1476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(arity == 4);
1477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cc_op   = args[0];
1478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cc_dep1 = args[1];
1479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cc_dep2 = args[2];
1480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cc_ndep = args[3];
1481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_SUBQ)) {
1483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* C after sub denotes unsigned less than */
1484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_CmpLT64U,
1486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           cc_dep1,
1487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           cc_dep2));
1488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_SUBL)) {
1490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* C after sub denotes unsigned less than */
1491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1492b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     binop(Iop_CmpLT32U,
1493b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop(Iop_64to32, cc_dep1),
1494b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop(Iop_64to32, cc_dep2)));
1495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_SUBB)) {
1497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* C after sub denotes unsigned less than */
1498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_CmpLT64U,
1500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           binop(Iop_And64,cc_dep1,mkU64(0xFF)),
1501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           binop(Iop_And64,cc_dep2,mkU64(0xFF))));
1502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_LOGICQ)
1504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          || isU64(cc_op, AMD64G_CC_OP_LOGICL)
1505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          || isU64(cc_op, AMD64G_CC_OP_LOGICW)
1506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          || isU64(cc_op, AMD64G_CC_OP_LOGICB)) {
1507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* cflag after logic is zero */
1508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkU64(0);
1509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_DECL) || isU64(cc_op, AMD64G_CC_OP_INCL)
1511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          || isU64(cc_op, AMD64G_CC_OP_DECQ) || isU64(cc_op, AMD64G_CC_OP_INCQ)) {
1512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* If the thunk is dec or inc, the cflag is supplied as CC_NDEP. */
1513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return cc_ndep;
1514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#     if 0
1517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (cc_op->tag == Iex_Const) {
1518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("CFLAG "); ppIRExpr(cc_op); vex_printf("\n");
1519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#     endif
1521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return NULL;
1523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef unop
1526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef binop
1527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef mkU64
1528b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#  undef mkU32
1529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef mkU8
1530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return NULL;
1532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
1536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Supporting functions for x87 FPU activities.            ---*/
1537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
1538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline Bool host_is_little_endian ( void )
1540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt x = 0x76543210;
1542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar* p = (UChar*)(&x);
1543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toBool(*p == 0x10);
1544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Inspect a value and its tag, as per the x87 'FXAM' instruction. */
1547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CALLED FROM GENERATED CODE: CLEAN HELPER */
1548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong amd64g_calculate_FXAM ( ULong tag, ULong dbl )
1549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool   mantissaIsZero;
1551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int    bexp;
1552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar  sign;
1553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar* f64;
1554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(host_is_little_endian());
1556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* vex_printf("calculate_FXAM ( %d, %llx ) .. ", tag, dbl ); */
1558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   f64  = (UChar*)(&dbl);
1560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sign = toUChar( (f64[7] >> 7) & 1 );
1561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* First off, if the tag indicates the register was empty,
1563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return 1,0,sign,1 */
1564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (tag == 0) {
1565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* vex_printf("Empty\n"); */
1566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return AMD64G_FC_MASK_C3 | 0 | (sign << AMD64G_FC_SHIFT_C1)
1567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   | AMD64G_FC_MASK_C0;
1568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bexp = (f64[7] << 4) | ((f64[6] >> 4) & 0x0F);
1571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bexp &= 0x7FF;
1572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mantissaIsZero
1574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = toBool(
1575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           (f64[6] & 0x0F) == 0
1576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           && (f64[5] | f64[4] | f64[3] | f64[2] | f64[1] | f64[0]) == 0
1577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        );
1578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* If both exponent and mantissa are zero, the value is zero.
1580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Return 1,0,sign,0. */
1581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (bexp == 0 && mantissaIsZero) {
1582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* vex_printf("Zero\n"); */
1583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return AMD64G_FC_MASK_C3 | 0
1584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               | (sign << AMD64G_FC_SHIFT_C1) | 0;
1585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* If exponent is zero but mantissa isn't, it's a denormal.
1588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Return 1,1,sign,0. */
1589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (bexp == 0 && !mantissaIsZero) {
1590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* vex_printf("Denormal\n"); */
1591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return AMD64G_FC_MASK_C3 | AMD64G_FC_MASK_C2
1592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               | (sign << AMD64G_FC_SHIFT_C1) | 0;
1593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* If the exponent is 7FF and the mantissa is zero, this is an infinity.
1596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Return 0,1,sign,1. */
1597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (bexp == 0x7FF && mantissaIsZero) {
1598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* vex_printf("Inf\n"); */
1599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return 0 | AMD64G_FC_MASK_C2 | (sign << AMD64G_FC_SHIFT_C1)
1600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   | AMD64G_FC_MASK_C0;
1601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* If the exponent is 7FF and the mantissa isn't zero, this is a NaN.
1604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Return 0,0,sign,1. */
1605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (bexp == 0x7FF && !mantissaIsZero) {
1606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* vex_printf("NaN\n"); */
1607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return 0 | 0 | (sign << AMD64G_FC_SHIFT_C1) | AMD64G_FC_MASK_C0;
1608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Uh, ok, we give up.  It must be a normal finite number.
1611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Return 0,1,sign,0.
1612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
1613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* vex_printf("normal\n"); */
1614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return 0 | AMD64G_FC_MASK_C2 | (sign << AMD64G_FC_SHIFT_C1) | 0;
1615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1618f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root/* This is used to implement both 'frstor' and 'fldenv'.  The latter
1619f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   appears to differ from the former only in that the 8 FP registers
1620f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   themselves are not transferred into the guest state. */
1621f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Rootstatic
1622436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovVexEmNote do_put_x87 ( Bool moveRegs,
1623f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root                       /*IN*/UChar* x87_state,
1624f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root                       /*OUT*/VexGuestAMD64State* vex_state )
1625f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root{
1626f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   Int        stno, preg;
1627f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   UInt       tag;
1628f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   ULong*     vexRegs = (ULong*)(&vex_state->guest_FPREG[0]);
1629f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   UChar*     vexTags = (UChar*)(&vex_state->guest_FPTAG[0]);
1630f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   Fpu_State* x87     = (Fpu_State*)x87_state;
1631f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   UInt       ftop    = (x87->env[FP_ENV_STAT] >> 11) & 7;
1632f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   UInt       tagw    = x87->env[FP_ENV_TAG];
1633f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   UInt       fpucw   = x87->env[FP_ENV_CTRL];
1634f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   UInt       c3210   = x87->env[FP_ENV_STAT] & 0x4700;
1635436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   VexEmNote  ew;
1636f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   UInt       fpround;
1637f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   ULong      pair;
1638f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
1639f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   /* Copy registers and tags */
1640f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   for (stno = 0; stno < 8; stno++) {
1641f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      preg = (stno + ftop) & 7;
1642f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      tag = (tagw >> (2*preg)) & 3;
1643f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      if (tag == 3) {
1644f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         /* register is empty */
1645f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         /* hmm, if it's empty, does it still get written?  Probably
1646f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root            safer to say it does.  If we don't, memcheck could get out
1647f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root            of sync, in that it thinks all FP registers are defined by
1648f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root            this helper, but in reality some have not been updated. */
1649f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         if (moveRegs)
1650f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root            vexRegs[preg] = 0; /* IEEE754 64-bit zero */
1651f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         vexTags[preg] = 0;
1652f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      } else {
1653f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         /* register is non-empty */
1654f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         if (moveRegs)
1655f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root            convert_f80le_to_f64le( &x87->reg[10*stno],
1656f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root                                    (UChar*)&vexRegs[preg] );
1657f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         vexTags[preg] = 1;
1658f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      }
1659f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   }
1660f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
1661f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   /* stack pointer */
1662f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   vex_state->guest_FTOP = ftop;
1663f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
1664f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   /* status word */
1665f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   vex_state->guest_FC3210 = c3210;
1666f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
1667f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   /* handle the control word, setting FPROUND and detecting any
1668f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      emulation warnings. */
1669f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   pair    = amd64g_check_fldcw ( (ULong)fpucw );
1670663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   fpround = (UInt)pair & 0xFFFFFFFFULL;
1671436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   ew      = (VexEmNote)(pair >> 32);
1672f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
1673f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   vex_state->guest_FPROUND = fpround & 3;
1674f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
1675f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   /* emulation warnings --> caller */
1676f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   return ew;
1677f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root}
1678f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
1679f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
1680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Create an x87 FPU state from the guest state, as close as
1681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   we can approximate it. */
1682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid do_get_x87 ( /*IN*/VexGuestAMD64State* vex_state,
1684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  /*OUT*/UChar* x87_state )
1685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int        i, stno, preg;
1687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt       tagw;
1688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong*     vexRegs = (ULong*)(&vex_state->guest_FPREG[0]);
1689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar*     vexTags = (UChar*)(&vex_state->guest_FPTAG[0]);
1690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Fpu_State* x87     = (Fpu_State*)x87_state;
1691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt       ftop    = vex_state->guest_FTOP;
1692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt       c3210   = vex_state->guest_FC3210;
1693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < 14; i++)
1695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      x87->env[i] = 0;
1696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   x87->env[1] = x87->env[3] = x87->env[5] = x87->env[13] = 0xFFFF;
1698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   x87->env[FP_ENV_STAT]
1699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = toUShort(((ftop & 7) << 11) | (c3210 & 0x4700));
1700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   x87->env[FP_ENV_CTRL]
1701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = toUShort(amd64g_create_fpucw( vex_state->guest_FPROUND ));
1702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Dump the register stack in ST order. */
1704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tagw = 0;
1705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (stno = 0; stno < 8; stno++) {
1706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      preg = (stno + ftop) & 7;
1707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (vexTags[preg] == 0) {
1708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* register is empty */
1709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tagw |= (3 << (2*preg));
1710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         convert_f64le_to_f80le( (UChar*)&vexRegs[preg],
1711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 &x87->reg[10*stno] );
1712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
1713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* register is full. */
1714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tagw |= (0 << (2*preg));
1715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         convert_f64le_to_f80le( (UChar*)&vexRegs[preg],
1716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 &x87->reg[10*stno] );
1717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   x87->env[FP_ENV_TAG] = toUShort(tagw);
1720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CALLED FROM GENERATED CODE */
1724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DIRTY HELPER (reads guest state, writes guest mem) */
1725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* NOTE: only handles 32-bit format (no REX.W on the insn) */
1726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid amd64g_dirtyhelper_FXSAVE ( VexGuestAMD64State* gst, HWord addr )
1727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Derived from values obtained from
1729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vendor_id       : AuthenticAMD
1730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cpu family      : 15
1731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      model           : 12
1732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      model name      : AMD Athlon(tm) 64 Processor 3200+
1733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stepping        : 0
1734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cpu MHz         : 2200.000
1735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cache size      : 512 KB
1736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
1737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Somewhat roundabout, but at least it's simple. */
1738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Fpu_State tmp;
1739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UShort*   addrS = (UShort*)addr;
1740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar*    addrC = (UChar*)addr;
1741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   U128*     xmm   = (U128*)(addr + 160);
1742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt      mxcsr;
1743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UShort    fp_tags;
1744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt      summary_tags;
1745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int       r, stno;
1746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UShort    *srcS, *dstS;
1747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   do_get_x87( gst, (UChar*)&tmp );
1749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mxcsr = amd64g_create_mxcsr( gst->guest_SSEROUND );
1750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Now build the proper fxsave image from the x87 image we just
1752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      made. */
1753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addrS[0]  = tmp.env[FP_ENV_CTRL]; /* FCW: fpu control word */
1755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addrS[1]  = tmp.env[FP_ENV_STAT]; /* FCW: fpu status word */
1756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* set addrS[2] in an endian-independent way */
1758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   summary_tags = 0;
1759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   fp_tags = tmp.env[FP_ENV_TAG];
1760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (r = 0; r < 8; r++) {
1761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ( ((fp_tags >> (2*r)) & 3) != 3 )
1762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         summary_tags |= (1 << r);
1763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addrC[4]  = toUChar(summary_tags); /* FTW: tag summary byte */
1765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addrC[5]  = 0; /* pad */
1766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* FOP: faulting fpu opcode.  From experimentation, the real CPU
1768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      does not write this field. (?!) */
1769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addrS[3]  = 0; /* BOGUS */
1770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* RIP (Last x87 instruction pointer).  From experimentation, the
1772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      real CPU does not write this field. (?!) */
1773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addrS[4]  = 0; /* BOGUS */
1774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addrS[5]  = 0; /* BOGUS */
1775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addrS[6]  = 0; /* BOGUS */
1776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addrS[7]  = 0; /* BOGUS */
1777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* RDP (Last x87 data pointer).  From experimentation, the real CPU
1779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      does not write this field. (?!) */
1780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addrS[8]  = 0; /* BOGUS */
1781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addrS[9]  = 0; /* BOGUS */
1782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addrS[10] = 0; /* BOGUS */
1783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addrS[11] = 0; /* BOGUS */
1784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addrS[12] = toUShort(mxcsr);  /* MXCSR */
1786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addrS[13] = toUShort(mxcsr >> 16);
1787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addrS[14] = 0xFFFF; /* MXCSR mask (lo16) */
1789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addrS[15] = 0x0000; /* MXCSR mask (hi16) */
1790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Copy in the FP registers, in ST order. */
1792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (stno = 0; stno < 8; stno++) {
1793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      srcS = (UShort*)(&tmp.reg[10*stno]);
1794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dstS = (UShort*)(&addrS[16 + 8*stno]);
1795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dstS[0] = srcS[0];
1796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dstS[1] = srcS[1];
1797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dstS[2] = srcS[2];
1798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dstS[3] = srcS[3];
1799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dstS[4] = srcS[4];
1800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dstS[5] = 0;
1801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dstS[6] = 0;
1802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dstS[7] = 0;
1803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* That's the first 160 bytes of the image done.  Now only %xmm0
1806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      .. %xmm15 remain to be copied.  If the host is big-endian, these
1807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      need to be byte-swapped. */
1808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(host_is_little_endian());
1809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define COPY_U128(_dst,_src)                       \
1811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do { _dst[0] = _src[0]; _dst[1] = _src[1];     \
1812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           _dst[2] = _src[2]; _dst[3] = _src[3]; }   \
1813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (0)
1814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1815663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( xmm[0],  gst->guest_YMM0 );
1816663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( xmm[1],  gst->guest_YMM1 );
1817663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( xmm[2],  gst->guest_YMM2 );
1818663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( xmm[3],  gst->guest_YMM3 );
1819663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( xmm[4],  gst->guest_YMM4 );
1820663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( xmm[5],  gst->guest_YMM5 );
1821663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( xmm[6],  gst->guest_YMM6 );
1822663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( xmm[7],  gst->guest_YMM7 );
1823663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( xmm[8],  gst->guest_YMM8 );
1824663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( xmm[9],  gst->guest_YMM9 );
1825663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( xmm[10], gst->guest_YMM10 );
1826663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( xmm[11], gst->guest_YMM11 );
1827663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( xmm[12], gst->guest_YMM12 );
1828663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( xmm[13], gst->guest_YMM13 );
1829663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( xmm[14], gst->guest_YMM14 );
1830663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( xmm[15], gst->guest_YMM15 );
1831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef COPY_U128
1833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1836f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root/* CALLED FROM GENERATED CODE */
1837f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root/* DIRTY HELPER (writes guest state, reads guest mem) */
1838436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovVexEmNote amd64g_dirtyhelper_FXRSTOR ( VexGuestAMD64State* gst, HWord addr )
1839f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root{
1840f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   Fpu_State tmp;
1841436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   VexEmNote warnX87 = EmNote_NONE;
1842436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   VexEmNote warnXMM = EmNote_NONE;
1843f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   UShort*   addrS   = (UShort*)addr;
1844f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   UChar*    addrC   = (UChar*)addr;
1845f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   U128*     xmm     = (U128*)(addr + 160);
1846f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   UShort    fp_tags;
1847f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   Int       r, stno, i;
1848f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
1849f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   /* Restore %xmm0 .. %xmm15.  If the host is big-endian, these need
1850f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      to be byte-swapped. */
1851f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   vassert(host_is_little_endian());
1852f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
1853f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root#  define COPY_U128(_dst,_src)                       \
1854f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      do { _dst[0] = _src[0]; _dst[1] = _src[1];     \
1855f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root           _dst[2] = _src[2]; _dst[3] = _src[3]; }   \
1856f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      while (0)
1857f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
1858663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( gst->guest_YMM0, xmm[0] );
1859663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( gst->guest_YMM1, xmm[1] );
1860663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( gst->guest_YMM2, xmm[2] );
1861663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( gst->guest_YMM3, xmm[3] );
1862663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( gst->guest_YMM4, xmm[4] );
1863663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( gst->guest_YMM5, xmm[5] );
1864663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( gst->guest_YMM6, xmm[6] );
1865663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( gst->guest_YMM7, xmm[7] );
1866663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( gst->guest_YMM8, xmm[8] );
1867663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( gst->guest_YMM9, xmm[9] );
1868663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( gst->guest_YMM10, xmm[10] );
1869663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( gst->guest_YMM11, xmm[11] );
1870663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( gst->guest_YMM12, xmm[12] );
1871663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( gst->guest_YMM13, xmm[13] );
1872663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( gst->guest_YMM14, xmm[14] );
1873663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( gst->guest_YMM15, xmm[15] );
1874f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
1875f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root#  undef COPY_U128
1876f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
1877f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   /* Copy the x87 registers out of the image, into a temporary
1878f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      Fpu_State struct. */
1879f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   for (i = 0; i < 14; i++) tmp.env[i] = 0;
1880f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   for (i = 0; i < 80; i++) tmp.reg[i] = 0;
1881f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   /* fill in tmp.reg[0..7] */
1882f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   for (stno = 0; stno < 8; stno++) {
1883f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      UShort* dstS = (UShort*)(&tmp.reg[10*stno]);
1884f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      UShort* srcS = (UShort*)(&addrS[16 + 8*stno]);
1885f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      dstS[0] = srcS[0];
1886f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      dstS[1] = srcS[1];
1887f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      dstS[2] = srcS[2];
1888f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      dstS[3] = srcS[3];
1889f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      dstS[4] = srcS[4];
1890f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   }
1891f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   /* fill in tmp.env[0..13] */
1892f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   tmp.env[FP_ENV_CTRL] = addrS[0]; /* FCW: fpu control word */
1893f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   tmp.env[FP_ENV_STAT] = addrS[1]; /* FCW: fpu status word */
1894f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
1895f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   fp_tags = 0;
1896f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   for (r = 0; r < 8; r++) {
1897f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      if (addrC[4] & (1<<r))
1898f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         fp_tags |= (0 << (2*r)); /* EMPTY */
1899f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      else
1900f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         fp_tags |= (3 << (2*r)); /* VALID -- not really precise enough. */
1901f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   }
1902f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   tmp.env[FP_ENV_TAG] = fp_tags;
1903f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
1904f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   /* Now write 'tmp' into the guest state. */
1905f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   warnX87 = do_put_x87( True/*moveRegs*/, (UChar*)&tmp, gst );
1906f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
1907f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   { UInt w32 = (((UInt)addrS[12]) & 0xFFFF)
1908f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root                | ((((UInt)addrS[13]) & 0xFFFF) << 16);
1909f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root     ULong w64 = amd64g_check_ldmxcsr( (ULong)w32 );
1910f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
1911436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     warnXMM = (VexEmNote)(w64 >> 32);
1912f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
1913f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root     gst->guest_SSEROUND = w64 & 0xFFFFFFFFULL;
1914f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   }
1915f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
1916f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   /* Prefer an X87 emwarn over an XMM one, if both exist. */
1917436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (warnX87 != EmNote_NONE)
1918f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      return warnX87;
1919f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   else
1920f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      return warnXMM;
1921f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root}
1922f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
1923f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
1924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DIRTY HELPER (writes guest state) */
1925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Initialise the x87 FPU state as per 'finit'. */
1926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid amd64g_dirtyhelper_FINIT ( VexGuestAMD64State* gst )
1927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i;
1929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   gst->guest_FTOP = 0;
1930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < 8; i++) {
1931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      gst->guest_FPTAG[i] = 0; /* empty */
1932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      gst->guest_FPREG[i] = 0; /* IEEE754 64-bit zero */
1933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   gst->guest_FPROUND = (ULong)Irrm_NEAREST;
1935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   gst->guest_FC3210  = 0;
1936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CALLED FROM GENERATED CODE */
1940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DIRTY HELPER (reads guest memory) */
1941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong amd64g_dirtyhelper_loadF80le ( ULong addrU )
1942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong f64;
1944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   convert_f80le_to_f64le ( (UChar*)ULong_to_Ptr(addrU), (UChar*)&f64 );
1945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return f64;
1946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CALLED FROM GENERATED CODE */
1949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DIRTY HELPER (writes guest memory) */
1950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid amd64g_dirtyhelper_storeF80le ( ULong addrU, ULong f64 )
1951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   convert_f64le_to_f80le( (UChar*)&f64, (UChar*)ULong_to_Ptr(addrU) );
1953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CALLED FROM GENERATED CODE */
1957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CLEAN HELPER */
1958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* mxcsr[15:0] contains a SSE native format MXCSR value.
1959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Extract from it the required SSEROUND value and any resulting
1960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   emulation warning, and return (warn << 32) | sseround value.
1961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong amd64g_check_ldmxcsr ( ULong mxcsr )
1963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Decide on a rounding mode.  mxcsr[14:13] holds it. */
1965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* NOTE, encoded exactly as per enum IRRoundingMode. */
1966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong rmode = (mxcsr >> 13) & 3;
1967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Detect any required emulation warnings. */
1969436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   VexEmNote ew = EmNote_NONE;
1970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((mxcsr & 0x1F80) != 0x1F80) {
1972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* unmasked exceptions! */
1973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ew = EmWarn_X86_sseExns;
1974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
1976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (mxcsr & (1<<15)) {
1977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* FZ is set */
1978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ew = EmWarn_X86_fz;
1979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
1981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (mxcsr & (1<<6)) {
1982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* DAZ is set */
1983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ew = EmWarn_X86_daz;
1984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (((ULong)ew) << 32) | ((ULong)rmode);
1987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1989ed07e00d438c74b7a23c01bfffde77e3968305e4