guest_amd64_helpers.c revision 663860b1408516d02ebfcb3a9999a134e6cfb223
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
10663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Copyright (C) 2004-2012 OpenWorks LLP
11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      info@open-works.net
12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is free software; you can redistribute it and/or
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   modify it under the terms of the GNU General Public License as
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   published by the Free Software Foundation; either version 2 of the
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   License, or (at your option) any later version.
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is distributed in the hope that it will be useful, but
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   WITHOUT ANY WARRANTY; without even the implied warranty of
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   General Public License for more details.
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   You should have received a copy of the GNU General Public License
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   along with this program; if not, write to the Free Software
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   02110-1301, USA.
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The GNU General Public License is contained in the file COPYING.
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Neither the names of the U.S. Department of Energy nor the
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   University of California nor the names of its contributors may be
32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   used to endorse or promote products derived from this software
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   without prior written permission.
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex_basictypes.h"
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex_emwarn.h"
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex_guest_amd64.h"
39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex_ir.h"
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex.h"
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "main_util.h"
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "guest_generic_bb_to_IR.h"
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "guest_amd64_defs.h"
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "guest_generic_x87.h"
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This file contains helper functions for amd64 guest code.
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Calls to these functions are generated by the back end.
50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   These calls are of course in the host machine code and
51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   this file will be compiled to host machine code, so that
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   all makes sense.
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Only change the signatures of these helper functions very
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   carefully.  If you change the signature here, you'll have to change
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the parameters passed to it in the IR calls constructed by
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   guest-amd64/toIR.c.
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The convention used is that all functions called from generated
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   code are named amd64g_<something>, and any function whose name lacks
61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   that prefix is not called from generated code.  Note that some
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LibVEX_* functions can however be called by VEX's client, but that
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   is not the same as calling them from VEX-generated code.
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Set to 1 to get detailed profiling info about use of the flag
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   machinery. */
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define PROFILE_RFLAGS 0
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- %rflags run-time helpers.                               ---*/
74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Do 64x64 -> 128 signed/unsigned multiplies, for computing flags
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   after imulq/mulq. */
78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void mullS64 ( Long u, Long v, Long* rHi, Long* rLo )
80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong u0, v0, w0;
82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Long u1, v1, w1, w2, t;
83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   u0   = u & 0xFFFFFFFFULL;
84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   u1   = u >> 32;
85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   v0   = v & 0xFFFFFFFFULL;
86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   v1   = v >> 32;
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w0   = u0 * v0;
88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   t    = u1 * v0 + (w0 >> 32);
89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w1   = t & 0xFFFFFFFFULL;
90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w2   = t >> 32;
91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w1   = u0 * v1 + w1;
92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *rHi = u1 * v1 + w2 + (w1 >> 32);
93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *rLo = u * v;
94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void mullU64 ( ULong u, ULong v, ULong* rHi, ULong* rLo )
97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong u0, v0, w0;
99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong u1, v1, w1,w2,t;
100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   u0   = u & 0xFFFFFFFFULL;
101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   u1   = u >> 32;
102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   v0   = v & 0xFFFFFFFFULL;
103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   v1   = v >> 32;
104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w0   = u0 * v0;
105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   t    = u1 * v0 + (w0 >> 32);
106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w1   = t & 0xFFFFFFFFULL;
107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w2   = t >> 32;
108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w1   = u0 * v1 + w1;
109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *rHi = u1 * v1 + w2 + (w1 >> 32);
110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *rLo = u * v;
111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic const UChar parity_table[256] = {
115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* generalised left-shifter */
150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline Long lshift ( Long x, Int n )
151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (n >= 0)
153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return x << n;
154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return x >> (-n);
156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* identity on ULong */
159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline ULong idULong ( ULong x )
160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return x;
162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define PREAMBLE(__data_bits)					\
166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* const */ ULong DATA_MASK 					\
167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = __data_bits==8                                          \
168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           ? 0xFFULL 					        \
169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           : (__data_bits==16                                   \
170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ? 0xFFFFULL 		                        \
171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : (__data_bits==32                              \
172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     ? 0xFFFFFFFFULL                            \
173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     : 0xFFFFFFFFFFFFFFFFULL));                 \
174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* const */ ULong SIGN_MASK = 1ULL << (__data_bits - 1);     \
175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* const */ ULong CC_DEP1 = cc_dep1_formal;			\
176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* const */ ULong CC_DEP2 = cc_dep2_formal;			\
177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* const */ ULong CC_NDEP = cc_ndep_formal;			\
178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Four bogus assignments, which hopefully gcc can     */	\
179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* optimise away, and which stop it complaining about  */	\
180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* unused variables.                                   */	\
181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SIGN_MASK = SIGN_MASK;					\
182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DATA_MASK = DATA_MASK;					\
183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CC_DEP2 = CC_DEP2;						\
184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CC_NDEP = CC_NDEP;
185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-------------------------------------------------------------*/
188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ACTIONS_ADD(DATA_BITS,DATA_UTYPE)			\
190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{								\
191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PREAMBLE(DATA_BITS);						\
192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { Long cf, pf, af, zf, sf, of;				\
193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Long argL, argR, res;					\
194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     argL = CC_DEP1;						\
195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     argR = CC_DEP2;						\
196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     res  = argL + argR;					\
197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     cf = (DATA_UTYPE)res < (DATA_UTYPE)argL;			\
198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     pf = parity_table[(UChar)res];				\
199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     af = (res ^ argL ^ argR) & 0x10;				\
200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     zf = ((DATA_UTYPE)res == 0) << 6;				\
201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     sf = lshift(res, 8 - DATA_BITS) & 0x80;			\
202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     of = lshift((argL ^ argR ^ -1) & (argL ^ res), 		\
203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 12 - DATA_BITS) & AMD64G_CC_MASK_O;		\
204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     return cf | pf | af | zf | sf | of;			\
205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }								\
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-------------------------------------------------------------*/
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ACTIONS_SUB(DATA_BITS,DATA_UTYPE)			\
211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{								\
212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PREAMBLE(DATA_BITS);						\
213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { Long cf, pf, af, zf, sf, of;				\
214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Long argL, argR, res;					\
215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     argL = CC_DEP1;						\
216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     argR = CC_DEP2;						\
217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     res  = argL - argR;					\
218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     cf = (DATA_UTYPE)argL < (DATA_UTYPE)argR;			\
219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     pf = parity_table[(UChar)res];				\
220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     af = (res ^ argL ^ argR) & 0x10;				\
221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     zf = ((DATA_UTYPE)res == 0) << 6;				\
222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     sf = lshift(res, 8 - DATA_BITS) & 0x80;			\
223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     of = lshift((argL ^ argR) & (argL ^ res),	 		\
224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 12 - DATA_BITS) & AMD64G_CC_MASK_O; 		\
225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     return cf | pf | af | zf | sf | of;			\
226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }								\
227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-------------------------------------------------------------*/
230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ACTIONS_ADC(DATA_BITS,DATA_UTYPE)			\
232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{								\
233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PREAMBLE(DATA_BITS);						\
234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { Long cf, pf, af, zf, sf, of;				\
235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Long argL, argR, oldC, res;		 		\
236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     oldC = CC_NDEP & AMD64G_CC_MASK_C;				\
237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     argL = CC_DEP1;						\
238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     argR = CC_DEP2 ^ oldC;	       				\
239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     res  = (argL + argR) + oldC;				\
240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (oldC)							\
241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cf = (DATA_UTYPE)res <= (DATA_UTYPE)argL;		\
242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     else							\
243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cf = (DATA_UTYPE)res < (DATA_UTYPE)argL;		\
244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     pf = parity_table[(UChar)res];				\
245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     af = (res ^ argL ^ argR) & 0x10;				\
246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     zf = ((DATA_UTYPE)res == 0) << 6;				\
247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     sf = lshift(res, 8 - DATA_BITS) & 0x80;			\
248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     of = lshift((argL ^ argR ^ -1) & (argL ^ res), 		\
249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  12 - DATA_BITS) & AMD64G_CC_MASK_O;		\
250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     return cf | pf | af | zf | sf | of;			\
251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }								\
252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-------------------------------------------------------------*/
255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ACTIONS_SBB(DATA_BITS,DATA_UTYPE)			\
257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{								\
258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PREAMBLE(DATA_BITS);						\
259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { Long cf, pf, af, zf, sf, of;				\
260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Long argL, argR, oldC, res;	       			\
261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     oldC = CC_NDEP & AMD64G_CC_MASK_C;				\
262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     argL = CC_DEP1;						\
263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     argR = CC_DEP2 ^ oldC;	       				\
264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     res  = (argL - argR) - oldC;				\
265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (oldC)							\
266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cf = (DATA_UTYPE)argL <= (DATA_UTYPE)argR;		\
267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     else							\
268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cf = (DATA_UTYPE)argL < (DATA_UTYPE)argR;		\
269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     pf = parity_table[(UChar)res];				\
270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     af = (res ^ argL ^ argR) & 0x10;				\
271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     zf = ((DATA_UTYPE)res == 0) << 6;				\
272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     sf = lshift(res, 8 - DATA_BITS) & 0x80;			\
273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     of = lshift((argL ^ argR) & (argL ^ res), 			\
274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 12 - DATA_BITS) & AMD64G_CC_MASK_O;		\
275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     return cf | pf | af | zf | sf | of;			\
276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }								\
277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-------------------------------------------------------------*/
280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ACTIONS_LOGIC(DATA_BITS,DATA_UTYPE)			\
282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{								\
283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PREAMBLE(DATA_BITS);						\
284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { Long cf, pf, af, zf, sf, of;				\
285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     cf = 0;							\
286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     pf = parity_table[(UChar)CC_DEP1];				\
287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     af = 0;							\
288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     zf = ((DATA_UTYPE)CC_DEP1 == 0) << 6;			\
289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     sf = lshift(CC_DEP1, 8 - DATA_BITS) & 0x80;		\
290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     of = 0;							\
291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     return cf | pf | af | zf | sf | of;			\
292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }								\
293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-------------------------------------------------------------*/
296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ACTIONS_INC(DATA_BITS,DATA_UTYPE)			\
298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{								\
299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PREAMBLE(DATA_BITS);						\
300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { Long cf, pf, af, zf, sf, of;				\
301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Long argL, argR, res;					\
302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     res  = CC_DEP1;						\
303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     argL = res - 1;						\
304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     argR = 1;							\
305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     cf = CC_NDEP & AMD64G_CC_MASK_C;				\
306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     pf = parity_table[(UChar)res];				\
307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     af = (res ^ argL ^ argR) & 0x10;				\
308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     zf = ((DATA_UTYPE)res == 0) << 6;				\
309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     sf = lshift(res, 8 - DATA_BITS) & 0x80;			\
310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     of = ((res & DATA_MASK) == SIGN_MASK) << 11;		\
311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     return cf | pf | af | zf | sf | of;			\
312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }								\
313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-------------------------------------------------------------*/
316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ACTIONS_DEC(DATA_BITS,DATA_UTYPE)			\
318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{								\
319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PREAMBLE(DATA_BITS);						\
320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { Long cf, pf, af, zf, sf, of;				\
321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Long argL, argR, res;					\
322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     res  = CC_DEP1;						\
323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     argL = res + 1;						\
324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     argR = 1;							\
325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     cf = CC_NDEP & AMD64G_CC_MASK_C;				\
326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     pf = parity_table[(UChar)res];				\
327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     af = (res ^ argL ^ argR) & 0x10;				\
328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     zf = ((DATA_UTYPE)res == 0) << 6;				\
329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     sf = lshift(res, 8 - DATA_BITS) & 0x80;			\
330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     of = ((res & DATA_MASK) 					\
331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          == ((ULong)SIGN_MASK - 1)) << 11;			\
332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     return cf | pf | af | zf | sf | of;			\
333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }								\
334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-------------------------------------------------------------*/
337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ACTIONS_SHL(DATA_BITS,DATA_UTYPE)			\
339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{								\
340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PREAMBLE(DATA_BITS);						\
341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { Long cf, pf, af, zf, sf, of;				\
342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     cf = (CC_DEP2 >> (DATA_BITS - 1)) & AMD64G_CC_MASK_C;	\
343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     pf = parity_table[(UChar)CC_DEP1];				\
344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     af = 0; /* undefined */					\
345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     zf = ((DATA_UTYPE)CC_DEP1 == 0) << 6;			\
346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     sf = lshift(CC_DEP1, 8 - DATA_BITS) & 0x80;		\
347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* of is defined if shift count == 1 */			\
348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     of = lshift(CC_DEP2 ^ CC_DEP1, 12 - DATA_BITS) 		\
349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          & AMD64G_CC_MASK_O;					\
350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     return cf | pf | af | zf | sf | of;			\
351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }								\
352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-------------------------------------------------------------*/
355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ACTIONS_SHR(DATA_BITS,DATA_UTYPE)			\
357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{								\
358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PREAMBLE(DATA_BITS);  					\
359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { Long cf, pf, af, zf, sf, of;				\
360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     cf = CC_DEP2 & 1;						\
361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     pf = parity_table[(UChar)CC_DEP1];				\
362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     af = 0; /* undefined */					\
363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     zf = ((DATA_UTYPE)CC_DEP1 == 0) << 6;			\
364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     sf = lshift(CC_DEP1, 8 - DATA_BITS) & 0x80;		\
365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* of is defined if shift count == 1 */			\
366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     of = lshift(CC_DEP2 ^ CC_DEP1, 12 - DATA_BITS)		\
367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          & AMD64G_CC_MASK_O;					\
368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     return cf | pf | af | zf | sf | of;			\
369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }								\
370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-------------------------------------------------------------*/
373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ROL: cf' = lsb(result).  of' = msb(result) ^ lsb(result). */
375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DEP1 = result, NDEP = old flags */
376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ACTIONS_ROL(DATA_BITS,DATA_UTYPE)			\
377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{								\
378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PREAMBLE(DATA_BITS);						\
379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { Long fl 							\
380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        = (CC_NDEP & ~(AMD64G_CC_MASK_O | AMD64G_CC_MASK_C))	\
381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          | (AMD64G_CC_MASK_C & CC_DEP1)			\
382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          | (AMD64G_CC_MASK_O & (lshift(CC_DEP1,  		\
383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      11-(DATA_BITS-1)) 	\
384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     ^ lshift(CC_DEP1, 11)));			\
385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     return fl;							\
386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }								\
387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-------------------------------------------------------------*/
390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ROR: cf' = msb(result).  of' = msb(result) ^ msb-1(result). */
392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DEP1 = result, NDEP = old flags */
393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ACTIONS_ROR(DATA_BITS,DATA_UTYPE)			\
394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{								\
395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PREAMBLE(DATA_BITS);						\
396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { Long fl 							\
397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        = (CC_NDEP & ~(AMD64G_CC_MASK_O | AMD64G_CC_MASK_C))	\
398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          | (AMD64G_CC_MASK_C & (CC_DEP1 >> (DATA_BITS-1)))	\
399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          | (AMD64G_CC_MASK_O & (lshift(CC_DEP1, 		\
400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      11-(DATA_BITS-1)) 	\
401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     ^ lshift(CC_DEP1, 11-(DATA_BITS-1)+1)));	\
402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     return fl;							\
403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }								\
404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-------------------------------------------------------------*/
407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ACTIONS_UMUL(DATA_BITS, DATA_UTYPE,  NARROWtoU,         \
409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                DATA_U2TYPE, NARROWto2U)        \
410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{                                                               \
411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PREAMBLE(DATA_BITS);                                         \
412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { Long cf, pf, af, zf, sf, of;                               \
413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DATA_UTYPE  hi;                                            \
414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DATA_UTYPE  lo                                             \
415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        = NARROWtoU( ((DATA_UTYPE)CC_DEP1)                      \
416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     * ((DATA_UTYPE)CC_DEP2) );                 \
417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DATA_U2TYPE rr                                             \
418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        = NARROWto2U(                                           \
419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             ((DATA_U2TYPE)((DATA_UTYPE)CC_DEP1))               \
420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             * ((DATA_U2TYPE)((DATA_UTYPE)CC_DEP2)) );          \
421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     hi = NARROWtoU(rr >>/*u*/ DATA_BITS);                      \
422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     cf = (hi != 0);                                            \
423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     pf = parity_table[(UChar)lo];                              \
424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     af = 0; /* undefined */                                    \
425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     zf = (lo == 0) << 6;                                       \
426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     sf = lshift(lo, 8 - DATA_BITS) & 0x80;                     \
427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     of = cf << 11;                                             \
428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     return cf | pf | af | zf | sf | of;                        \
429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }								\
430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-------------------------------------------------------------*/
433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ACTIONS_SMUL(DATA_BITS, DATA_STYPE,  NARROWtoS,         \
435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                DATA_S2TYPE, NARROWto2S)        \
436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{                                                               \
437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PREAMBLE(DATA_BITS);                                         \
438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { Long cf, pf, af, zf, sf, of;                               \
439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DATA_STYPE  hi;                                            \
440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DATA_STYPE  lo                                             \
441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        = NARROWtoS( ((DATA_STYPE)CC_DEP1)                      \
442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     * ((DATA_STYPE)CC_DEP2) );                 \
443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DATA_S2TYPE rr                                             \
444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        = NARROWto2S(                                           \
445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             ((DATA_S2TYPE)((DATA_STYPE)CC_DEP1))               \
446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             * ((DATA_S2TYPE)((DATA_STYPE)CC_DEP2)) );          \
447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     hi = NARROWtoS(rr >>/*s*/ DATA_BITS);                      \
448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     cf = (hi != (lo >>/*s*/ (DATA_BITS-1)));                   \
449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     pf = parity_table[(UChar)lo];                              \
450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     af = 0; /* undefined */                                    \
451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     zf = (lo == 0) << 6;                                       \
452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     sf = lshift(lo, 8 - DATA_BITS) & 0x80;                     \
453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     of = cf << 11;                                             \
454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     return cf | pf | af | zf | sf | of;                        \
455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }								\
456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-------------------------------------------------------------*/
459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ACTIONS_UMULQ                                           \
461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{                                                               \
462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PREAMBLE(64);                                                \
463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { Long cf, pf, af, zf, sf, of;                               \
464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     ULong lo, hi;                                              \
465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     mullU64( (ULong)CC_DEP1, (ULong)CC_DEP2, &hi, &lo );       \
466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     cf = (hi != 0);                                            \
467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     pf = parity_table[(UChar)lo];                              \
468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     af = 0; /* undefined */                                    \
469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     zf = (lo == 0) << 6;                                       \
470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     sf = lshift(lo, 8 - 64) & 0x80;                            \
471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     of = cf << 11;                                             \
472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     return cf | pf | af | zf | sf | of;                        \
473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }								\
474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-------------------------------------------------------------*/
477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ACTIONS_SMULQ                                           \
479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{                                                               \
480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PREAMBLE(64);                                                \
481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { Long cf, pf, af, zf, sf, of;                               \
482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Long lo, hi;                                               \
483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     mullS64( (Long)CC_DEP1, (Long)CC_DEP2, &hi, &lo );         \
484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     cf = (hi != (lo >>/*s*/ (64-1)));                          \
485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     pf = parity_table[(UChar)lo];                              \
486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     af = 0; /* undefined */                                    \
487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     zf = (lo == 0) << 6;                                       \
488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     sf = lshift(lo, 8 - 64) & 0x80;                            \
489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     of = cf << 11;                                             \
490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     return cf | pf | af | zf | sf | of;                        \
491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }								\
492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if PROFILE_RFLAGS
496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool initted     = False;
498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* C flag, fast route */
500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt tabc_fast[AMD64G_CC_OP_NUMBER];
501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* C flag, slow route */
502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt tabc_slow[AMD64G_CC_OP_NUMBER];
503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* table for calculate_cond */
504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt tab_cond[AMD64G_CC_OP_NUMBER][16];
505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* total entry counts for calc_all, calc_c, calc_cond. */
506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt n_calc_all  = 0;
507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt n_calc_c    = 0;
508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt n_calc_cond = 0;
509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHOW_COUNTS_NOW (0 == (0x3FFFFF & (n_calc_all+n_calc_c+n_calc_cond)))
511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void showCounts ( void )
514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int op, co;
516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Char ch;
517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("\nTotal calls: calc_all=%u   calc_cond=%u   calc_c=%u\n",
518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              n_calc_all, n_calc_cond, n_calc_c);
519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("      cSLOW  cFAST    O   NO    B   NB    Z   NZ   BE  NBE"
521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              "    S   NS    P   NP    L   NL   LE  NLE\n");
522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("     -----------------------------------------------------"
523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              "----------------------------------------\n");
524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (op = 0; op < AMD64G_CC_OP_NUMBER; op++) {
525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ch = ' ';
527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (op > 0 && (op-1) % 4 == 0)
528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ch = 'B';
529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (op > 0 && (op-1) % 4 == 1)
530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ch = 'W';
531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (op > 0 && (op-1) % 4 == 2)
532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ch = 'L';
533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (op > 0 && (op-1) % 4 == 3)
534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ch = 'Q';
535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("%2d%c: ", op, ch);
537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("%6u ", tabc_slow[op]);
538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("%6u ", tabc_fast[op]);
539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (co = 0; co < 16; co++) {
540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Int n = tab_cond[op][co];
541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (n >= 1000) {
542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf(" %3dK", n / 1000);
543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else
544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (n >= 0) {
545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf(" %3d ", n );
546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("     ");
548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\n");
551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("\n");
553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void initCounts ( void )
556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int op, co;
558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   initted = True;
559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (op = 0; op < AMD64G_CC_OP_NUMBER; op++) {
560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tabc_fast[op] = tabc_slow[op] = 0;
561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (co = 0; co < 16; co++)
562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tab_cond[op][co] = 0;
563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif /* PROFILE_RFLAGS */
567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CALLED FROM GENERATED CODE: CLEAN HELPER */
570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Calculate all the 6 flags from the supplied thunk parameters.
571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Worker function, not directly called from generated code. */
572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong amd64g_calculate_rflags_all_WRK ( ULong cc_op,
574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        ULong cc_dep1_formal,
575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        ULong cc_dep2_formal,
576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        ULong cc_ndep_formal )
577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (cc_op) {
579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_COPY:
580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return cc_dep1_formal
581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                & (AMD64G_CC_MASK_O | AMD64G_CC_MASK_S | AMD64G_CC_MASK_Z
582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   | AMD64G_CC_MASK_A | AMD64G_CC_MASK_C | AMD64G_CC_MASK_P);
583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_ADDB:   ACTIONS_ADD( 8,  UChar  );
585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_ADDW:   ACTIONS_ADD( 16, UShort );
586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_ADDL:   ACTIONS_ADD( 32, UInt   );
587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_ADDQ:   ACTIONS_ADD( 64, ULong  );
588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_ADCB:   ACTIONS_ADC( 8,  UChar  );
590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_ADCW:   ACTIONS_ADC( 16, UShort );
591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_ADCL:   ACTIONS_ADC( 32, UInt   );
592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_ADCQ:   ACTIONS_ADC( 64, ULong  );
593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_SUBB:   ACTIONS_SUB(  8, UChar  );
595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_SUBW:   ACTIONS_SUB( 16, UShort );
596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_SUBL:   ACTIONS_SUB( 32, UInt   );
597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_SUBQ:   ACTIONS_SUB( 64, ULong  );
598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_SBBB:   ACTIONS_SBB(  8, UChar  );
600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_SBBW:   ACTIONS_SBB( 16, UShort );
601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_SBBL:   ACTIONS_SBB( 32, UInt   );
602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_SBBQ:   ACTIONS_SBB( 64, ULong  );
603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_LOGICB: ACTIONS_LOGIC(  8, UChar  );
605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_LOGICW: ACTIONS_LOGIC( 16, UShort );
606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_LOGICL: ACTIONS_LOGIC( 32, UInt   );
607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_LOGICQ: ACTIONS_LOGIC( 64, ULong  );
608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_INCB:   ACTIONS_INC(  8, UChar  );
610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_INCW:   ACTIONS_INC( 16, UShort );
611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_INCL:   ACTIONS_INC( 32, UInt   );
612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_INCQ:   ACTIONS_INC( 64, ULong  );
613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_DECB:   ACTIONS_DEC(  8, UChar  );
615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_DECW:   ACTIONS_DEC( 16, UShort );
616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_DECL:   ACTIONS_DEC( 32, UInt   );
617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_DECQ:   ACTIONS_DEC( 64, ULong  );
618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_SHLB:   ACTIONS_SHL(  8, UChar  );
620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_SHLW:   ACTIONS_SHL( 16, UShort );
621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_SHLL:   ACTIONS_SHL( 32, UInt   );
622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_SHLQ:   ACTIONS_SHL( 64, ULong  );
623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_SHRB:   ACTIONS_SHR(  8, UChar  );
625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_SHRW:   ACTIONS_SHR( 16, UShort );
626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_SHRL:   ACTIONS_SHR( 32, UInt   );
627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_SHRQ:   ACTIONS_SHR( 64, ULong  );
628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_ROLB:   ACTIONS_ROL(  8, UChar  );
630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_ROLW:   ACTIONS_ROL( 16, UShort );
631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_ROLL:   ACTIONS_ROL( 32, UInt   );
632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_ROLQ:   ACTIONS_ROL( 64, ULong  );
633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_RORB:   ACTIONS_ROR(  8, UChar  );
635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_RORW:   ACTIONS_ROR( 16, UShort );
636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_RORL:   ACTIONS_ROR( 32, UInt   );
637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_RORQ:   ACTIONS_ROR( 64, ULong  );
638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_UMULB:  ACTIONS_UMUL(  8, UChar,  toUChar,
640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                  UShort, toUShort );
641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_UMULW:  ACTIONS_UMUL( 16, UShort, toUShort,
642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                  UInt,   toUInt );
643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_UMULL:  ACTIONS_UMUL( 32, UInt,   toUInt,
644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                  ULong,  idULong );
645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_UMULQ:  ACTIONS_UMULQ;
647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_SMULB:  ACTIONS_SMUL(  8, Char,   toUChar,
649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                  Short,  toUShort );
650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_SMULW:  ACTIONS_SMUL( 16, Short,  toUShort,
651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                  Int,    toUInt   );
652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_SMULL:  ACTIONS_SMUL( 32, Int,    toUInt,
653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                  Long,   idULong );
654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_SMULQ:  ACTIONS_SMULQ;
656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* shouldn't really make these calls from generated code */
659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("amd64g_calculate_rflags_all_WRK(AMD64)"
660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    "( %llu, 0x%llx, 0x%llx, 0x%llx )\n",
661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    cc_op, cc_dep1_formal, cc_dep2_formal, cc_ndep_formal );
662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("amd64g_calculate_rflags_all_WRK(AMD64)");
663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CALLED FROM GENERATED CODE: CLEAN HELPER */
668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Calculate all the 6 flags from the supplied thunk parameters. */
669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong amd64g_calculate_rflags_all ( ULong cc_op,
670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    ULong cc_dep1,
671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    ULong cc_dep2,
672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    ULong cc_ndep )
673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if PROFILE_RFLAGS
675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!initted) initCounts();
676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n_calc_all++;
677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (SHOW_COUNTS_NOW) showCounts();
678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return
680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      amd64g_calculate_rflags_all_WRK ( cc_op, cc_dep1, cc_dep2, cc_ndep );
681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CALLED FROM GENERATED CODE: CLEAN HELPER */
685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Calculate just the carry flag from the supplied thunk parameters. */
686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong amd64g_calculate_rflags_c ( ULong cc_op,
687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  ULong cc_dep1,
688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  ULong cc_dep2,
689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  ULong cc_ndep )
690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if PROFILE_RFLAGS
692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!initted) initCounts();
693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n_calc_c++;
694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tabc_fast[cc_op]++;
695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (SHOW_COUNTS_NOW) showCounts();
696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Fast-case some common ones. */
699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (cc_op) {
700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_COPY:
701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return (cc_dep1 >> AMD64G_CC_SHIFT_C) & 1;
702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_LOGICQ:
703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_LOGICL:
704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_LOGICW:
705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64G_CC_OP_LOGICB:
706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return 0;
707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 //      case AMD64G_CC_OP_SUBL:
708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 //         return ((UInt)cc_dep1) < ((UInt)cc_dep2)
709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 //                   ? AMD64G_CC_MASK_C : 0;
710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 //      case AMD64G_CC_OP_SUBW:
711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 //         return ((UInt)(cc_dep1 & 0xFFFF)) < ((UInt)(cc_dep2 & 0xFFFF))
712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 //                   ? AMD64G_CC_MASK_C : 0;
713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 //      case AMD64G_CC_OP_SUBB:
714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 //         return ((UInt)(cc_dep1 & 0xFF)) < ((UInt)(cc_dep2 & 0xFF))
715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 //                   ? AMD64G_CC_MASK_C : 0;
716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 //      case AMD64G_CC_OP_INCL:
717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 //      case AMD64G_CC_OP_DECL:
718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 //         return cc_ndep & AMD64G_CC_MASK_C;
719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if PROFILE_RFLAGS
724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tabc_fast[cc_op]--;
725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tabc_slow[cc_op]++;
726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return amd64g_calculate_rflags_all_WRK(cc_op,cc_dep1,cc_dep2,cc_ndep)
729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          & AMD64G_CC_MASK_C;
730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CALLED FROM GENERATED CODE: CLEAN HELPER */
734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* returns 1 or 0 */
735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong amd64g_calculate_condition ( ULong/*AMD64Condcode*/ cond,
736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   ULong cc_op,
737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   ULong cc_dep1,
738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   ULong cc_dep2,
739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   ULong cc_ndep )
740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong rflags = amd64g_calculate_rflags_all_WRK(cc_op, cc_dep1,
742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                  cc_dep2, cc_ndep);
743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong of,sf,zf,cf,pf;
744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong inv = cond & 1;
745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if PROFILE_RFLAGS
747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!initted) initCounts();
748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tab_cond[cc_op][cond]++;
749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n_calc_cond++;
750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (SHOW_COUNTS_NOW) showCounts();
751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (cond) {
754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64CondNO:
755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64CondO: /* OF == 1 */
756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         of = rflags >> AMD64G_CC_SHIFT_O;
757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return 1 & (inv ^ of);
758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64CondNZ:
760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64CondZ: /* ZF == 1 */
761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         zf = rflags >> AMD64G_CC_SHIFT_Z;
762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return 1 & (inv ^ zf);
763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64CondNB:
765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64CondB: /* CF == 1 */
766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cf = rflags >> AMD64G_CC_SHIFT_C;
767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return 1 & (inv ^ cf);
768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64CondNBE:
771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64CondBE: /* (CF or ZF) == 1 */
772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cf = rflags >> AMD64G_CC_SHIFT_C;
773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         zf = rflags >> AMD64G_CC_SHIFT_Z;
774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return 1 & (inv ^ (cf | zf));
775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64CondNS:
778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64CondS: /* SF == 1 */
779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         sf = rflags >> AMD64G_CC_SHIFT_S;
780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return 1 & (inv ^ sf);
781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64CondNP:
783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64CondP: /* PF == 1 */
784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         pf = rflags >> AMD64G_CC_SHIFT_P;
785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return 1 & (inv ^ pf);
786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64CondNL:
788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64CondL: /* (SF xor OF) == 1 */
789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         sf = rflags >> AMD64G_CC_SHIFT_S;
790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         of = rflags >> AMD64G_CC_SHIFT_O;
791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return 1 & (inv ^ (sf ^ of));
792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64CondNLE:
795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64CondLE: /* ((SF xor OF) or ZF)  == 1 */
796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         sf = rflags >> AMD64G_CC_SHIFT_S;
797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         of = rflags >> AMD64G_CC_SHIFT_O;
798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         zf = rflags >> AMD64G_CC_SHIFT_Z;
799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return 1 & (inv ^ ((sf ^ of) | zf));
800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* shouldn't really make these calls from generated code */
804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("amd64g_calculate_condition"
805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    "( %llu, %llu, 0x%llx, 0x%llx, 0x%llx )\n",
806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    cond, cc_op, cc_dep1, cc_dep2, cc_ndep );
807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("amd64g_calculate_condition");
808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* VISIBLE TO LIBVEX CLIENT */
813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong LibVEX_GuestAMD64_get_rflags ( /*IN*/VexGuestAMD64State* vex_state )
814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong rflags = amd64g_calculate_rflags_all_WRK(
816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vex_state->guest_CC_OP,
817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vex_state->guest_CC_DEP1,
818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vex_state->guest_CC_DEP2,
819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vex_state->guest_CC_NDEP
820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  );
821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Long dflag = vex_state->guest_DFLAG;
822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(dflag == 1 || dflag == -1);
823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (dflag == -1)
824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      rflags |= (1<<10);
825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vex_state->guest_IDFLAG == 1)
826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      rflags |= (1<<21);
827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vex_state->guest_ACFLAG == 1)
828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      rflags |= (1<<18);
829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return rflags;
831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* VISIBLE TO LIBVEX CLIENT */
834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid
835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownLibVEX_GuestAMD64_put_rflag_c ( ULong new_carry_flag,
836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               /*MOD*/VexGuestAMD64State* vex_state )
837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong oszacp = amd64g_calculate_rflags_all_WRK(
839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vex_state->guest_CC_OP,
840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vex_state->guest_CC_DEP1,
841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vex_state->guest_CC_DEP2,
842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vex_state->guest_CC_NDEP
843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  );
844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (new_carry_flag & 1) {
845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      oszacp |= AMD64G_CC_MASK_C;
846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      oszacp &= ~AMD64G_CC_MASK_C;
848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_state->guest_CC_OP   = AMD64G_CC_OP_COPY;
850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_state->guest_CC_DEP1 = oszacp;
851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_state->guest_CC_DEP2 = 0;
852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_state->guest_CC_NDEP = 0;
853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- %rflags translation-time function specialisers.         ---*/
858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- These help iropt specialise calls the above run-time    ---*/
859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- %rflags functions.                                      ---*/
860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Used by the optimiser to try specialisations.  Returns an
863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   equivalent expression, or NULL if none. */
864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool isU64 ( IRExpr* e, ULong n )
866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toBool( e->tag == Iex_Const
868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  && e->Iex.Const.con->tag == Ico_U64
869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  && e->Iex.Const.con->Ico.U64 == n );
870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRExpr* guest_amd64_spechelper ( HChar* function_name,
873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 IRExpr** args,
874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 IRStmt** precedingStmts,
875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 Int      n_precedingStmts )
876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define unop(_op,_a1) IRExpr_Unop((_op),(_a1))
878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define binop(_op,_a1,_a2) IRExpr_Binop((_op),(_a1),(_a2))
879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define mkU64(_n) IRExpr_Const(IRConst_U64(_n))
880b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#  define mkU32(_n) IRExpr_Const(IRConst_U32(_n))
881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define mkU8(_n)  IRExpr_Const(IRConst_U8(_n))
882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i, arity = 0;
884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; args[i]; i++)
885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      arity++;
886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if 0
887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("spec request:\n");
888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("   %s  ", function_name);
889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < arity; i++) {
890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("  ");
891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRExpr(args[i]);
892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("\n");
894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- specialising "amd64g_calculate_condition" --------- */
897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vex_streq(function_name, "amd64g_calculate_condition")) {
899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* specialise calls to above "calculate condition" function */
900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRExpr *cond, *cc_op, *cc_dep1, *cc_dep2;
901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(arity == 5);
902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cond    = args[0];
903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cc_op   = args[1];
904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cc_dep1 = args[2];
905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cc_dep2 = args[3];
906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*---------------- ADDQ ----------------*/
908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_ADDQ) && isU64(cond, AMD64CondZ)) {
910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* long long add, then Z --> test (dst+src == 0) */
911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_CmpEQ64,
913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           binop(Iop_Add64, cc_dep1, cc_dep2),
914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           mkU64(0)));
915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*---------------- SUBQ ----------------*/
918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_SUBQ) && isU64(cond, AMD64CondZ)) {
920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* long long sub/cmp, then Z --> test dst==src */
921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_CmpEQ64,cc_dep1,cc_dep2));
923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_SUBQ) && isU64(cond, AMD64CondNZ)) {
925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* long long sub/cmp, then NZ --> test dst!=src */
926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_CmpNE64,cc_dep1,cc_dep2));
928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_SUBQ) && isU64(cond, AMD64CondL)) {
931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* long long sub/cmp, then L (signed less than)
932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            --> test dst <s src */
933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_CmpLT64S, cc_dep1, cc_dep2));
935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_SUBQ) && isU64(cond, AMD64CondB)) {
938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* long long sub/cmp, then B (unsigned less than)
939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            --> test dst <u src */
940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_CmpLT64U, cc_dep1, cc_dep2));
942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_SUBQ) && isU64(cond, AMD64CondNB)) {
944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* long long sub/cmp, then NB (unsigned greater than or equal)
945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            --> test src <=u dst */
946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Note, args are opposite way round from the usual */
947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_CmpLE64U, cc_dep2, cc_dep1));
949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_SUBQ) && isU64(cond, AMD64CondBE)) {
952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* long long sub/cmp, then BE (unsigned less than or equal)
953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            --> test dst <=u src */
954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_CmpLE64U, cc_dep1, cc_dep2));
956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
957663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (isU64(cc_op, AMD64G_CC_OP_SUBQ) && isU64(cond, AMD64CondNBE)) {
958663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* long long sub/cmp, then NBE (unsigned greater than)
959663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            --> test !(dst <=u src) */
960663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return binop(Iop_Xor64,
961663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      unop(Iop_1Uto64,
962663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           binop(Iop_CmpLE64U, cc_dep1, cc_dep2)),
963663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      mkU64(1));
964663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*---------------- SUBL ----------------*/
967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondZ)) {
969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* long sub/cmp, then Z --> test dst==src */
970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
971b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     binop(Iop_CmpEQ32,
972b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop(Iop_64to32, cc_dep1),
973b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop(Iop_64to32, cc_dep2)));
974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondNZ)) {
976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* long sub/cmp, then NZ --> test dst!=src */
977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
978b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     binop(Iop_CmpNE32,
979b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop(Iop_64to32, cc_dep1),
980b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop(Iop_64to32, cc_dep2)));
981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondL)) {
984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* long sub/cmp, then L (signed less than)
985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            --> test dst <s src */
986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
987b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     binop(Iop_CmpLT32S,
988b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop(Iop_64to32, cc_dep1),
989b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop(Iop_64to32, cc_dep2)));
990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondLE)) {
993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* long sub/cmp, then LE (signed less than or equal)
994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            --> test dst <=s src */
995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
996b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     binop(Iop_CmpLE32S,
997b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop(Iop_64to32, cc_dep1),
998b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop(Iop_64to32, cc_dep2)));
999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondNLE)) {
1002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* long sub/cmp, then NLE (signed greater than)
1003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            --> test !(dst <=s src)
1004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            --> test (dst >s src)
1005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            --> test (src <s dst) */
1006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1007b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     binop(Iop_CmpLT32S,
1008b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop(Iop_64to32, cc_dep2),
1009b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop(Iop_64to32, cc_dep1)));
1010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondBE)) {
1014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* long sub/cmp, then BE (unsigned less than or equal)
1015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            --> test dst <=u src */
1016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1017b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     binop(Iop_CmpLE32U,
1018b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop(Iop_64to32, cc_dep1),
1019b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop(Iop_64to32, cc_dep2)));
1020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondNBE)) {
1022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* long sub/cmp, then NBE (unsigned greater than)
1023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            --> test src <u dst */
1024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Note, args are opposite way round from the usual */
1025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1026b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     binop(Iop_CmpLT32U,
1027b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop(Iop_64to32, cc_dep2),
1028b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop(Iop_64to32, cc_dep1)));
1029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondS)) {
1032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* long sub/cmp, then S (negative) --> test (dst-src <s 0) */
1033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1034b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     binop(Iop_CmpLT32S,
1035b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           binop(Iop_Sub32,
1036b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 unop(Iop_64to32, cc_dep1),
1037b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 unop(Iop_64to32, cc_dep2)),
1038b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           mkU32(0)));
1039b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
1040b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1041b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondB)) {
1042b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* long sub/cmp, then B (unsigned less than)
1043b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            --> test dst <u src */
1044b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return unop(Iop_1Uto64,
1045b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     binop(Iop_CmpLT32U,
1046b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop(Iop_64to32, cc_dep1),
1047b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop(Iop_64to32, cc_dep2)));
1048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*---------------- SUBW ----------------*/
1051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_SUBW) && isU64(cond, AMD64CondZ)) {
1053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* word sub/cmp, then Z --> test dst==src */
1054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_CmpEQ16,
1056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           unop(Iop_64to16,cc_dep1),
1057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           unop(Iop_64to16,cc_dep2)));
1058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_SUBW) && isU64(cond, AMD64CondNZ)) {
1060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* word sub/cmp, then NZ --> test dst!=src */
1061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_CmpNE16,
1063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           unop(Iop_64to16,cc_dep1),
1064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           unop(Iop_64to16,cc_dep2)));
1065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_SUBW) && isU64(cond, AMD64CondLE)) {
1068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* word sub/cmp, then LE (signed less than or equal)
1069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            --> test dst <=s src */
1070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_CmpLE64S,
1072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           binop(Iop_Shl64,cc_dep1,mkU8(48)),
1073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           binop(Iop_Shl64,cc_dep2,mkU8(48))));
1074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*---------------- SUBB ----------------*/
1078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_SUBB) && isU64(cond, AMD64CondZ)) {
1080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* byte sub/cmp, then Z --> test dst==src */
1081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_CmpEQ8,
1083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           unop(Iop_64to8,cc_dep1),
1084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           unop(Iop_64to8,cc_dep2)));
1085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_SUBB) && isU64(cond, AMD64CondNZ)) {
1087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* byte sub/cmp, then NZ --> test dst!=src */
1088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_CmpNE8,
1090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           unop(Iop_64to8,cc_dep1),
1091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           unop(Iop_64to8,cc_dep2)));
1092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1094b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (isU64(cc_op, AMD64G_CC_OP_SUBB) && isU64(cond, AMD64CondBE)) {
1095b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* byte sub/cmp, then BE (unsigned less than or equal)
1096b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            --> test dst <=u src */
1097b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return unop(Iop_1Uto64,
1098b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     binop(Iop_CmpLE64U,
1099b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           binop(Iop_And64, cc_dep1, mkU64(0xFF)),
1100b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           binop(Iop_And64, cc_dep2, mkU64(0xFF))));
1101b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
1102b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_SUBB) && isU64(cond, AMD64CondS)
1104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          && isU64(cc_dep2, 0)) {
1105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* byte sub/cmp of zero, then S --> test (dst-0 <s 0)
1106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         --> test dst <s 0
1107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         --> (ULong)dst[7]
1108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            This is yet another scheme by which gcc figures out if the
1109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            top bit of a byte is 1 or 0.  See also LOGICB/CondS below. */
1110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Note: isU64(cc_dep2, 0) is correct, even though this is
1111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for an 8-bit comparison, since the args to the helper
1112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            function are always U64s. */
1113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return binop(Iop_And64,
1114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_Shr64,cc_dep1,mkU8(7)),
1115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      mkU64(1));
1116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_SUBB) && isU64(cond, AMD64CondNS)
1118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          && isU64(cc_dep2, 0)) {
1119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* byte sub/cmp of zero, then NS --> test !(dst-0 <s 0)
1120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          --> test !(dst <s 0)
1121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          --> (ULong) !dst[7]
1122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         */
1123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return binop(Iop_Xor64,
1124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_And64,
1125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(Iop_Shr64,cc_dep1,mkU8(7)),
1126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkU64(1)),
1127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      mkU64(1));
1128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*---------------- LOGICQ ----------------*/
1131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_LOGICQ) && isU64(cond, AMD64CondZ)) {
1133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* long long and/or/xor, then Z --> test dst==0 */
1134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_CmpEQ64, cc_dep1, mkU64(0)));
1136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1137b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (isU64(cc_op, AMD64G_CC_OP_LOGICQ) && isU64(cond, AMD64CondNZ)) {
1138b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* long long and/or/xor, then NZ --> test dst!=0 */
1139b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return unop(Iop_1Uto64,
1140b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     binop(Iop_CmpNE64, cc_dep1, mkU64(0)));
1141b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
1142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_LOGICQ) && isU64(cond, AMD64CondL)) {
1144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* long long and/or/xor, then L
1145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            LOGIC sets SF and ZF according to the
1146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            result and makes OF be zero.  L computes SF ^ OF, but
1147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            OF is zero, so this reduces to SF -- which will be 1 iff
1148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            the result is < signed 0.  Hence ...
1149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         */
1150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_CmpLT64S,
1152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           cc_dep1,
1153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           mkU64(0)));
1154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*---------------- LOGICL ----------------*/
1157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_LOGICL) && isU64(cond, AMD64CondZ)) {
1159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* long and/or/xor, then Z --> test dst==0 */
1160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1161b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     binop(Iop_CmpEQ32,
1162b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop(Iop_64to32, cc_dep1),
1163b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           mkU32(0)));
1164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_LOGICL) && isU64(cond, AMD64CondNZ)) {
1166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* long and/or/xor, then NZ --> test dst!=0 */
1167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1168b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     binop(Iop_CmpNE32,
1169b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop(Iop_64to32, cc_dep1),
1170b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           mkU32(0)));
1171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_LOGICL) && isU64(cond, AMD64CondLE)) {
1174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* long and/or/xor, then LE
1175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            This is pretty subtle.  LOGIC sets SF and ZF according to the
1176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            result and makes OF be zero.  LE computes (SF ^ OF) | ZF, but
1177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            OF is zero, so this reduces to SF | ZF -- which will be 1 iff
1178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            the result is <=signed 0.  Hence ...
1179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         */
1180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1181b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     binop(Iop_CmpLE32S,
1182b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop(Iop_64to32, cc_dep1),
1183b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           mkU32(0)));
1184b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
1185b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1186b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (isU64(cc_op, AMD64G_CC_OP_LOGICL) && isU64(cond, AMD64CondS)) {
1187b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* long and/or/xor, then S --> (ULong)result[31] */
1188b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return binop(Iop_And64,
1189b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                      binop(Iop_Shr64, cc_dep1, mkU8(31)),
1190b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                      mkU64(1));
1191b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
1192b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (isU64(cc_op, AMD64G_CC_OP_LOGICL) && isU64(cond, AMD64CondNS)) {
1193b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* long and/or/xor, then S --> (ULong) ~ result[31] */
1194b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return binop(Iop_Xor64,
1195b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                binop(Iop_And64,
1196b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                      binop(Iop_Shr64, cc_dep1, mkU8(31)),
1197b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                      mkU64(1)),
1198b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                mkU64(1));
1199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1201663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /*---------------- LOGICW ----------------*/
1202663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1203663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (isU64(cc_op, AMD64G_CC_OP_LOGICW) && isU64(cond, AMD64CondZ)) {
1204663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* word and/or/xor, then Z --> test dst==0 */
1205663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return unop(Iop_1Uto64,
1206663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     binop(Iop_CmpEQ64,
1207663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           binop(Iop_And64, cc_dep1, mkU64(0xFFFF)),
1208663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           mkU64(0)));
1209663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
1210663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (isU64(cc_op, AMD64G_CC_OP_LOGICW) && isU64(cond, AMD64CondNZ)) {
1211663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* word and/or/xor, then NZ --> test dst!=0 */
1212663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return unop(Iop_1Uto64,
1213663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     binop(Iop_CmpNE64,
1214663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           binop(Iop_And64, cc_dep1, mkU64(0xFFFF)),
1215663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           mkU64(0)));
1216663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
1217663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*---------------- LOGICB ----------------*/
1219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_LOGICB) && isU64(cond, AMD64CondZ)) {
1221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* byte and/or/xor, then Z --> test dst==0 */
1222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_CmpEQ64, binop(Iop_And64,cc_dep1,mkU64(255)),
1224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        mkU64(0)));
1225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_LOGICB) && isU64(cond, AMD64CondNZ)) {
1227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* byte and/or/xor, then NZ --> test dst!=0 */
1228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_CmpNE64, binop(Iop_And64,cc_dep1,mkU64(255)),
1230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        mkU64(0)));
1231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_LOGICB) && isU64(cond, AMD64CondS)) {
1234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* this is an idiom gcc sometimes uses to find out if the top
1235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bit of a byte register is set: eg testb %al,%al; js ..
1236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Since it just depends on the top bit of the byte, extract
1237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            that bit and explicitly get rid of all the rest.  This
1238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            helps memcheck avoid false positives in the case where any
1239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            of the other bits in the byte are undefined. */
1240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* byte and/or/xor, then S --> (UInt)result[7] */
1241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return binop(Iop_And64,
1242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_Shr64,cc_dep1,mkU8(7)),
1243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      mkU64(1));
1244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1245b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (isU64(cc_op, AMD64G_CC_OP_LOGICB) && isU64(cond, AMD64CondNS)) {
1246b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* byte and/or/xor, then NS --> (UInt)!result[7] */
1247b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return binop(Iop_Xor64,
1248b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                      binop(Iop_And64,
1249b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                            binop(Iop_Shr64,cc_dep1,mkU8(7)),
1250b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                            mkU64(1)),
1251b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                      mkU64(1));
1252b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
1253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*---------------- INCB ----------------*/
1255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_INCB) && isU64(cond, AMD64CondLE)) {
1257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* 8-bit inc, then LE --> sign bit of the arg */
1258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return binop(Iop_And64,
1259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_Shr64,
1260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(Iop_Sub64, cc_dep1, mkU64(1)),
1261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkU8(7)),
1262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      mkU64(1));
1263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*---------------- INCW ----------------*/
1266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_INCW) && isU64(cond, AMD64CondZ)) {
1268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* 16-bit inc, then Z --> test dst == 0 */
1269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_CmpEQ64,
1271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           binop(Iop_Shl64,cc_dep1,mkU8(48)),
1272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           mkU64(0)));
1273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*---------------- DECL ----------------*/
1276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_DECL) && isU64(cond, AMD64CondZ)) {
1278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* dec L, then Z --> test dst == 0 */
1279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1280b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     binop(Iop_CmpEQ32,
1281b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop(Iop_64to32, cc_dep1),
1282b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           mkU32(0)));
1283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*---------------- DECW ----------------*/
1286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_DECW) && isU64(cond, AMD64CondNZ)) {
1288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* 16-bit dec, then NZ --> test dst != 0 */
1289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_CmpNE64,
1291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           binop(Iop_Shl64,cc_dep1,mkU8(48)),
1292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           mkU64(0)));
1293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*---------------- COPY ----------------*/
1296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* This can happen, as a result of amd64 FP compares: "comisd ... ;
1297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         jbe" for example. */
1298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_COPY) &&
1300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          (isU64(cond, AMD64CondBE) || isU64(cond, AMD64CondNBE))) {
1301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* COPY, then BE --> extract C and Z from dep1, and test (C
1302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            or Z == 1). */
1303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* COPY, then NBE --> extract C and Z from dep1, and test (C
1304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            or Z == 0). */
1305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ULong nnn = isU64(cond, AMD64CondBE) ? 1 : 0;
1306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return
1307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            unop(
1308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Iop_1Uto64,
1309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(
1310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  Iop_CmpEQ64,
1311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(
1312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     Iop_And64,
1313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(
1314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        Iop_Or64,
1315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_Shr64, cc_dep1, mkU8(AMD64G_CC_SHIFT_C)),
1316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_Shr64, cc_dep1, mkU8(AMD64G_CC_SHIFT_Z))
1317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     ),
1318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkU64(1)
1319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  ),
1320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  mkU64(nnn)
1321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               )
1322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            );
1323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_COPY) && isU64(cond, AMD64CondB)) {
1326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* COPY, then B --> extract C dep1, and test (C == 1). */
1327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return
1328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            unop(
1329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Iop_1Uto64,
1330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(
1331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  Iop_CmpNE64,
1332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(
1333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     Iop_And64,
1334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_Shr64, cc_dep1, mkU8(AMD64G_CC_SHIFT_C)),
1335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkU64(1)
1336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  ),
1337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  mkU64(0)
1338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               )
1339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            );
1340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_COPY)
1343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && (isU64(cond, AMD64CondZ) || isU64(cond, AMD64CondNZ))) {
1344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* COPY, then Z --> extract Z from dep1, and test (Z == 1). */
1345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* COPY, then NZ --> extract Z from dep1, and test (Z == 0). */
1346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt nnn = isU64(cond, AMD64CondZ) ? 1 : 0;
1347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return
1348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            unop(
1349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Iop_1Uto64,
1350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(
1351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  Iop_CmpEQ64,
1352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(
1353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     Iop_And64,
1354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_Shr64, cc_dep1, mkU8(AMD64G_CC_SHIFT_Z)),
1355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkU64(1)
1356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  ),
1357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  mkU64(nnn)
1358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               )
1359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            );
1360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_COPY) && isU64(cond, AMD64CondP)) {
1363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* COPY, then P --> extract P from dep1, and test (P == 1). */
1364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return
1365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            unop(
1366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Iop_1Uto64,
1367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(
1368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  Iop_CmpNE64,
1369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(
1370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     Iop_And64,
1371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_Shr64, cc_dep1, mkU8(AMD64G_CC_SHIFT_P)),
1372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkU64(1)
1373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  ),
1374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  mkU64(0)
1375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               )
1376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            );
1377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return NULL;
1380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- specialising "amd64g_calculate_rflags_c" --------- */
1383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vex_streq(function_name, "amd64g_calculate_rflags_c")) {
1385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* specialise calls to above "calculate_rflags_c" function */
1386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRExpr *cc_op, *cc_dep1, *cc_dep2, *cc_ndep;
1387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(arity == 4);
1388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cc_op   = args[0];
1389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cc_dep1 = args[1];
1390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cc_dep2 = args[2];
1391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cc_ndep = args[3];
1392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_SUBQ)) {
1394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* C after sub denotes unsigned less than */
1395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_CmpLT64U,
1397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           cc_dep1,
1398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           cc_dep2));
1399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_SUBL)) {
1401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* C after sub denotes unsigned less than */
1402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1403b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     binop(Iop_CmpLT32U,
1404b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop(Iop_64to32, cc_dep1),
1405b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop(Iop_64to32, cc_dep2)));
1406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_SUBB)) {
1408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* C after sub denotes unsigned less than */
1409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unop(Iop_1Uto64,
1410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_CmpLT64U,
1411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           binop(Iop_And64,cc_dep1,mkU64(0xFF)),
1412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           binop(Iop_And64,cc_dep2,mkU64(0xFF))));
1413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_LOGICQ)
1415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          || isU64(cc_op, AMD64G_CC_OP_LOGICL)
1416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          || isU64(cc_op, AMD64G_CC_OP_LOGICW)
1417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          || isU64(cc_op, AMD64G_CC_OP_LOGICB)) {
1418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* cflag after logic is zero */
1419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkU64(0);
1420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isU64(cc_op, AMD64G_CC_OP_DECL) || isU64(cc_op, AMD64G_CC_OP_INCL)
1422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          || isU64(cc_op, AMD64G_CC_OP_DECQ) || isU64(cc_op, AMD64G_CC_OP_INCQ)) {
1423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* If the thunk is dec or inc, the cflag is supplied as CC_NDEP. */
1424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return cc_ndep;
1425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#     if 0
1428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (cc_op->tag == Iex_Const) {
1429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("CFLAG "); ppIRExpr(cc_op); vex_printf("\n");
1430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#     endif
1432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return NULL;
1434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef unop
1437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef binop
1438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef mkU64
1439b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#  undef mkU32
1440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef mkU8
1441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return NULL;
1443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
1447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Supporting functions for x87 FPU activities.            ---*/
1448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
1449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline Bool host_is_little_endian ( void )
1451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt x = 0x76543210;
1453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar* p = (UChar*)(&x);
1454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toBool(*p == 0x10);
1455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Inspect a value and its tag, as per the x87 'FXAM' instruction. */
1458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CALLED FROM GENERATED CODE: CLEAN HELPER */
1459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong amd64g_calculate_FXAM ( ULong tag, ULong dbl )
1460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool   mantissaIsZero;
1462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int    bexp;
1463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar  sign;
1464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar* f64;
1465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(host_is_little_endian());
1467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* vex_printf("calculate_FXAM ( %d, %llx ) .. ", tag, dbl ); */
1469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   f64  = (UChar*)(&dbl);
1471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sign = toUChar( (f64[7] >> 7) & 1 );
1472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* First off, if the tag indicates the register was empty,
1474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return 1,0,sign,1 */
1475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (tag == 0) {
1476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* vex_printf("Empty\n"); */
1477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return AMD64G_FC_MASK_C3 | 0 | (sign << AMD64G_FC_SHIFT_C1)
1478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   | AMD64G_FC_MASK_C0;
1479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bexp = (f64[7] << 4) | ((f64[6] >> 4) & 0x0F);
1482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bexp &= 0x7FF;
1483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mantissaIsZero
1485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = toBool(
1486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           (f64[6] & 0x0F) == 0
1487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           && (f64[5] | f64[4] | f64[3] | f64[2] | f64[1] | f64[0]) == 0
1488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        );
1489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* If both exponent and mantissa are zero, the value is zero.
1491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Return 1,0,sign,0. */
1492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (bexp == 0 && mantissaIsZero) {
1493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* vex_printf("Zero\n"); */
1494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return AMD64G_FC_MASK_C3 | 0
1495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               | (sign << AMD64G_FC_SHIFT_C1) | 0;
1496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* If exponent is zero but mantissa isn't, it's a denormal.
1499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Return 1,1,sign,0. */
1500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (bexp == 0 && !mantissaIsZero) {
1501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* vex_printf("Denormal\n"); */
1502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return AMD64G_FC_MASK_C3 | AMD64G_FC_MASK_C2
1503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               | (sign << AMD64G_FC_SHIFT_C1) | 0;
1504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* If the exponent is 7FF and the mantissa is zero, this is an infinity.
1507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Return 0,1,sign,1. */
1508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (bexp == 0x7FF && mantissaIsZero) {
1509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* vex_printf("Inf\n"); */
1510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return 0 | AMD64G_FC_MASK_C2 | (sign << AMD64G_FC_SHIFT_C1)
1511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   | AMD64G_FC_MASK_C0;
1512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* If the exponent is 7FF and the mantissa isn't zero, this is a NaN.
1515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Return 0,0,sign,1. */
1516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (bexp == 0x7FF && !mantissaIsZero) {
1517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* vex_printf("NaN\n"); */
1518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return 0 | 0 | (sign << AMD64G_FC_SHIFT_C1) | AMD64G_FC_MASK_C0;
1519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Uh, ok, we give up.  It must be a normal finite number.
1522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Return 0,1,sign,0.
1523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
1524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* vex_printf("normal\n"); */
1525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return 0 | AMD64G_FC_MASK_C2 | (sign << AMD64G_FC_SHIFT_C1) | 0;
1526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1529f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root/* This is used to implement both 'frstor' and 'fldenv'.  The latter
1530f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   appears to differ from the former only in that the 8 FP registers
1531f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   themselves are not transferred into the guest state. */
1532f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Rootstatic
1533f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny RootVexEmWarn do_put_x87 ( Bool moveRegs,
1534f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root                       /*IN*/UChar* x87_state,
1535f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root                       /*OUT*/VexGuestAMD64State* vex_state )
1536f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root{
1537f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   Int        stno, preg;
1538f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   UInt       tag;
1539f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   ULong*     vexRegs = (ULong*)(&vex_state->guest_FPREG[0]);
1540f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   UChar*     vexTags = (UChar*)(&vex_state->guest_FPTAG[0]);
1541f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   Fpu_State* x87     = (Fpu_State*)x87_state;
1542f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   UInt       ftop    = (x87->env[FP_ENV_STAT] >> 11) & 7;
1543f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   UInt       tagw    = x87->env[FP_ENV_TAG];
1544f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   UInt       fpucw   = x87->env[FP_ENV_CTRL];
1545f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   UInt       c3210   = x87->env[FP_ENV_STAT] & 0x4700;
1546f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   VexEmWarn  ew;
1547f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   UInt       fpround;
1548f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   ULong      pair;
1549f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
1550f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   /* Copy registers and tags */
1551f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   for (stno = 0; stno < 8; stno++) {
1552f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      preg = (stno + ftop) & 7;
1553f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      tag = (tagw >> (2*preg)) & 3;
1554f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      if (tag == 3) {
1555f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         /* register is empty */
1556f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         /* hmm, if it's empty, does it still get written?  Probably
1557f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root            safer to say it does.  If we don't, memcheck could get out
1558f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root            of sync, in that it thinks all FP registers are defined by
1559f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root            this helper, but in reality some have not been updated. */
1560f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         if (moveRegs)
1561f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root            vexRegs[preg] = 0; /* IEEE754 64-bit zero */
1562f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         vexTags[preg] = 0;
1563f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      } else {
1564f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         /* register is non-empty */
1565f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         if (moveRegs)
1566f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root            convert_f80le_to_f64le( &x87->reg[10*stno],
1567f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root                                    (UChar*)&vexRegs[preg] );
1568f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         vexTags[preg] = 1;
1569f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      }
1570f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   }
1571f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
1572f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   /* stack pointer */
1573f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   vex_state->guest_FTOP = ftop;
1574f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
1575f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   /* status word */
1576f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   vex_state->guest_FC3210 = c3210;
1577f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
1578f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   /* handle the control word, setting FPROUND and detecting any
1579f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      emulation warnings. */
1580f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   pair    = amd64g_check_fldcw ( (ULong)fpucw );
1581663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   fpround = (UInt)pair & 0xFFFFFFFFULL;
1582f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   ew      = (VexEmWarn)(pair >> 32);
1583f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
1584f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   vex_state->guest_FPROUND = fpround & 3;
1585f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
1586f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   /* emulation warnings --> caller */
1587f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   return ew;
1588f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root}
1589f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
1590f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
1591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Create an x87 FPU state from the guest state, as close as
1592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   we can approximate it. */
1593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid do_get_x87 ( /*IN*/VexGuestAMD64State* vex_state,
1595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  /*OUT*/UChar* x87_state )
1596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int        i, stno, preg;
1598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt       tagw;
1599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong*     vexRegs = (ULong*)(&vex_state->guest_FPREG[0]);
1600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar*     vexTags = (UChar*)(&vex_state->guest_FPTAG[0]);
1601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Fpu_State* x87     = (Fpu_State*)x87_state;
1602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt       ftop    = vex_state->guest_FTOP;
1603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt       c3210   = vex_state->guest_FC3210;
1604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < 14; i++)
1606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      x87->env[i] = 0;
1607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   x87->env[1] = x87->env[3] = x87->env[5] = x87->env[13] = 0xFFFF;
1609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   x87->env[FP_ENV_STAT]
1610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = toUShort(((ftop & 7) << 11) | (c3210 & 0x4700));
1611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   x87->env[FP_ENV_CTRL]
1612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = toUShort(amd64g_create_fpucw( vex_state->guest_FPROUND ));
1613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Dump the register stack in ST order. */
1615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tagw = 0;
1616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (stno = 0; stno < 8; stno++) {
1617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      preg = (stno + ftop) & 7;
1618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (vexTags[preg] == 0) {
1619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* register is empty */
1620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tagw |= (3 << (2*preg));
1621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         convert_f64le_to_f80le( (UChar*)&vexRegs[preg],
1622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 &x87->reg[10*stno] );
1623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
1624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* register is full. */
1625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tagw |= (0 << (2*preg));
1626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         convert_f64le_to_f80le( (UChar*)&vexRegs[preg],
1627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 &x87->reg[10*stno] );
1628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   x87->env[FP_ENV_TAG] = toUShort(tagw);
1631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CALLED FROM GENERATED CODE */
1635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DIRTY HELPER (reads guest state, writes guest mem) */
1636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* NOTE: only handles 32-bit format (no REX.W on the insn) */
1637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid amd64g_dirtyhelper_FXSAVE ( VexGuestAMD64State* gst, HWord addr )
1638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Derived from values obtained from
1640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vendor_id       : AuthenticAMD
1641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cpu family      : 15
1642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      model           : 12
1643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      model name      : AMD Athlon(tm) 64 Processor 3200+
1644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stepping        : 0
1645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cpu MHz         : 2200.000
1646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cache size      : 512 KB
1647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
1648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Somewhat roundabout, but at least it's simple. */
1649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Fpu_State tmp;
1650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UShort*   addrS = (UShort*)addr;
1651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar*    addrC = (UChar*)addr;
1652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   U128*     xmm   = (U128*)(addr + 160);
1653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt      mxcsr;
1654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UShort    fp_tags;
1655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt      summary_tags;
1656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int       r, stno;
1657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UShort    *srcS, *dstS;
1658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   do_get_x87( gst, (UChar*)&tmp );
1660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mxcsr = amd64g_create_mxcsr( gst->guest_SSEROUND );
1661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Now build the proper fxsave image from the x87 image we just
1663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      made. */
1664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addrS[0]  = tmp.env[FP_ENV_CTRL]; /* FCW: fpu control word */
1666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addrS[1]  = tmp.env[FP_ENV_STAT]; /* FCW: fpu status word */
1667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* set addrS[2] in an endian-independent way */
1669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   summary_tags = 0;
1670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   fp_tags = tmp.env[FP_ENV_TAG];
1671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (r = 0; r < 8; r++) {
1672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ( ((fp_tags >> (2*r)) & 3) != 3 )
1673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         summary_tags |= (1 << r);
1674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addrC[4]  = toUChar(summary_tags); /* FTW: tag summary byte */
1676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addrC[5]  = 0; /* pad */
1677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* FOP: faulting fpu opcode.  From experimentation, the real CPU
1679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      does not write this field. (?!) */
1680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addrS[3]  = 0; /* BOGUS */
1681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* RIP (Last x87 instruction pointer).  From experimentation, the
1683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      real CPU does not write this field. (?!) */
1684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addrS[4]  = 0; /* BOGUS */
1685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addrS[5]  = 0; /* BOGUS */
1686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addrS[6]  = 0; /* BOGUS */
1687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addrS[7]  = 0; /* BOGUS */
1688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* RDP (Last x87 data pointer).  From experimentation, the real CPU
1690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      does not write this field. (?!) */
1691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addrS[8]  = 0; /* BOGUS */
1692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addrS[9]  = 0; /* BOGUS */
1693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addrS[10] = 0; /* BOGUS */
1694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addrS[11] = 0; /* BOGUS */
1695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addrS[12] = toUShort(mxcsr);  /* MXCSR */
1697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addrS[13] = toUShort(mxcsr >> 16);
1698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addrS[14] = 0xFFFF; /* MXCSR mask (lo16) */
1700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addrS[15] = 0x0000; /* MXCSR mask (hi16) */
1701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Copy in the FP registers, in ST order. */
1703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (stno = 0; stno < 8; stno++) {
1704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      srcS = (UShort*)(&tmp.reg[10*stno]);
1705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dstS = (UShort*)(&addrS[16 + 8*stno]);
1706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dstS[0] = srcS[0];
1707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dstS[1] = srcS[1];
1708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dstS[2] = srcS[2];
1709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dstS[3] = srcS[3];
1710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dstS[4] = srcS[4];
1711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dstS[5] = 0;
1712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dstS[6] = 0;
1713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dstS[7] = 0;
1714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* That's the first 160 bytes of the image done.  Now only %xmm0
1717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      .. %xmm15 remain to be copied.  If the host is big-endian, these
1718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      need to be byte-swapped. */
1719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(host_is_little_endian());
1720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define COPY_U128(_dst,_src)                       \
1722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do { _dst[0] = _src[0]; _dst[1] = _src[1];     \
1723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           _dst[2] = _src[2]; _dst[3] = _src[3]; }   \
1724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (0)
1725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1726663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( xmm[0],  gst->guest_YMM0 );
1727663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( xmm[1],  gst->guest_YMM1 );
1728663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( xmm[2],  gst->guest_YMM2 );
1729663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( xmm[3],  gst->guest_YMM3 );
1730663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( xmm[4],  gst->guest_YMM4 );
1731663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( xmm[5],  gst->guest_YMM5 );
1732663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( xmm[6],  gst->guest_YMM6 );
1733663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( xmm[7],  gst->guest_YMM7 );
1734663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( xmm[8],  gst->guest_YMM8 );
1735663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( xmm[9],  gst->guest_YMM9 );
1736663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( xmm[10], gst->guest_YMM10 );
1737663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( xmm[11], gst->guest_YMM11 );
1738663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( xmm[12], gst->guest_YMM12 );
1739663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( xmm[13], gst->guest_YMM13 );
1740663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( xmm[14], gst->guest_YMM14 );
1741663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( xmm[15], gst->guest_YMM15 );
1742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef COPY_U128
1744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1747f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root/* CALLED FROM GENERATED CODE */
1748f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root/* DIRTY HELPER (writes guest state, reads guest mem) */
1749f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny RootVexEmWarn amd64g_dirtyhelper_FXRSTOR ( VexGuestAMD64State* gst, HWord addr )
1750f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root{
1751f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   Fpu_State tmp;
1752f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   VexEmWarn warnX87 = EmWarn_NONE;
1753f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   VexEmWarn warnXMM = EmWarn_NONE;
1754f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   UShort*   addrS   = (UShort*)addr;
1755f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   UChar*    addrC   = (UChar*)addr;
1756f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   U128*     xmm     = (U128*)(addr + 160);
1757f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   UShort    fp_tags;
1758f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   Int       r, stno, i;
1759f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
1760f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   /* Restore %xmm0 .. %xmm15.  If the host is big-endian, these need
1761f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      to be byte-swapped. */
1762f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   vassert(host_is_little_endian());
1763f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
1764f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root#  define COPY_U128(_dst,_src)                       \
1765f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      do { _dst[0] = _src[0]; _dst[1] = _src[1];     \
1766f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root           _dst[2] = _src[2]; _dst[3] = _src[3]; }   \
1767f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      while (0)
1768f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
1769663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( gst->guest_YMM0, xmm[0] );
1770663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( gst->guest_YMM1, xmm[1] );
1771663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( gst->guest_YMM2, xmm[2] );
1772663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( gst->guest_YMM3, xmm[3] );
1773663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( gst->guest_YMM4, xmm[4] );
1774663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( gst->guest_YMM5, xmm[5] );
1775663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( gst->guest_YMM6, xmm[6] );
1776663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( gst->guest_YMM7, xmm[7] );
1777663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( gst->guest_YMM8, xmm[8] );
1778663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( gst->guest_YMM9, xmm[9] );
1779663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( gst->guest_YMM10, xmm[10] );
1780663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( gst->guest_YMM11, xmm[11] );
1781663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( gst->guest_YMM12, xmm[12] );
1782663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( gst->guest_YMM13, xmm[13] );
1783663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( gst->guest_YMM14, xmm[14] );
1784663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   COPY_U128( gst->guest_YMM15, xmm[15] );
1785f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
1786f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root#  undef COPY_U128
1787f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
1788f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   /* Copy the x87 registers out of the image, into a temporary
1789f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      Fpu_State struct. */
1790f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   for (i = 0; i < 14; i++) tmp.env[i] = 0;
1791f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   for (i = 0; i < 80; i++) tmp.reg[i] = 0;
1792f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   /* fill in tmp.reg[0..7] */
1793f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   for (stno = 0; stno < 8; stno++) {
1794f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      UShort* dstS = (UShort*)(&tmp.reg[10*stno]);
1795f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      UShort* srcS = (UShort*)(&addrS[16 + 8*stno]);
1796f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      dstS[0] = srcS[0];
1797f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      dstS[1] = srcS[1];
1798f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      dstS[2] = srcS[2];
1799f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      dstS[3] = srcS[3];
1800f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      dstS[4] = srcS[4];
1801f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   }
1802f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   /* fill in tmp.env[0..13] */
1803f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   tmp.env[FP_ENV_CTRL] = addrS[0]; /* FCW: fpu control word */
1804f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   tmp.env[FP_ENV_STAT] = addrS[1]; /* FCW: fpu status word */
1805f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
1806f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   fp_tags = 0;
1807f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   for (r = 0; r < 8; r++) {
1808f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      if (addrC[4] & (1<<r))
1809f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         fp_tags |= (0 << (2*r)); /* EMPTY */
1810f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      else
1811f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         fp_tags |= (3 << (2*r)); /* VALID -- not really precise enough. */
1812f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   }
1813f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   tmp.env[FP_ENV_TAG] = fp_tags;
1814f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
1815f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   /* Now write 'tmp' into the guest state. */
1816f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   warnX87 = do_put_x87( True/*moveRegs*/, (UChar*)&tmp, gst );
1817f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
1818f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   { UInt w32 = (((UInt)addrS[12]) & 0xFFFF)
1819f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root                | ((((UInt)addrS[13]) & 0xFFFF) << 16);
1820f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root     ULong w64 = amd64g_check_ldmxcsr( (ULong)w32 );
1821f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
1822f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root     warnXMM = (VexEmWarn)(w64 >> 32);
1823f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
1824f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root     gst->guest_SSEROUND = w64 & 0xFFFFFFFFULL;
1825f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   }
1826f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
1827f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   /* Prefer an X87 emwarn over an XMM one, if both exist. */
1828f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   if (warnX87 != EmWarn_NONE)
1829f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      return warnX87;
1830f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   else
1831f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      return warnXMM;
1832f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root}
1833f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
1834f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
1835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DIRTY HELPER (writes guest state) */
1836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Initialise the x87 FPU state as per 'finit'. */
1837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid amd64g_dirtyhelper_FINIT ( VexGuestAMD64State* gst )
1838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i;
1840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   gst->guest_FTOP = 0;
1841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < 8; i++) {
1842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      gst->guest_FPTAG[i] = 0; /* empty */
1843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      gst->guest_FPREG[i] = 0; /* IEEE754 64-bit zero */
1844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   gst->guest_FPROUND = (ULong)Irrm_NEAREST;
1846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   gst->guest_FC3210  = 0;
1847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CALLED FROM GENERATED CODE */
1851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DIRTY HELPER (reads guest memory) */
1852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong amd64g_dirtyhelper_loadF80le ( ULong addrU )
1853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong f64;
1855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   convert_f80le_to_f64le ( (UChar*)ULong_to_Ptr(addrU), (UChar*)&f64 );
1856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return f64;
1857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CALLED FROM GENERATED CODE */
1860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DIRTY HELPER (writes guest memory) */
1861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid amd64g_dirtyhelper_storeF80le ( ULong addrU, ULong f64 )
1862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   convert_f64le_to_f80le( (UChar*)&f64, (UChar*)ULong_to_Ptr(addrU) );
1864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CALLED FROM GENERATED CODE */
1868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CLEAN HELPER */
1869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* mxcsr[15:0] contains a SSE native format MXCSR value.
1870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Extract from it the required SSEROUND value and any resulting
1871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   emulation warning, and return (warn << 32) | sseround value.
1872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong amd64g_check_ldmxcsr ( ULong mxcsr )
1874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Decide on a rounding mode.  mxcsr[14:13] holds it. */
1876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* NOTE, encoded exactly as per enum IRRoundingMode. */
1877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong rmode = (mxcsr >> 13) & 3;
1878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Detect any required emulation warnings. */
1880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VexEmWarn ew = EmWarn_NONE;
1881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((mxcsr & 0x1F80) != 0x1F80) {
1883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* unmasked exceptions! */
1884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ew = EmWarn_X86_sseExns;
1885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
1887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (mxcsr & (1<<15)) {
1888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* FZ is set */
1889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ew = EmWarn_X86_fz;
1890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
1892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (mxcsr & (1<<6)) {
1893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* DAZ is set */
1894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ew = EmWarn_X86_daz;
1895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (((ULong)ew) << 32) | ((ULong)rmode);
1898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CALLED FROM GENERATED CODE */
1902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CLEAN HELPER */
1903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Given sseround as an IRRoundingMode value, create a suitable SSE
1904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   native format MXCSR value. */
1905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong amd64g_create_mxcsr ( ULong sseround )
1906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sseround &= 3;
1908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return 0x1F80 | (sseround << 13);
1909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CLEAN HELPER */
1913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* fpucw[15:0] contains a x87 native format FPU control word.
1914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Extract from it the required FPROUND value and any resulting
1915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   emulation warning, and return (warn << 32) | fpround value.
1916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong amd64g_check_fldcw ( ULong fpucw )
1918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Decide on a rounding mode.  fpucw[11:10] holds it. */
1920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* NOTE, encoded exactly as per enum IRRoundingMode. */
1921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong rmode = (fpucw >> 10) & 3;
1922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Detect any required emulation warnings. */
1924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VexEmWarn ew = EmWarn_NONE;
1925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((fpucw & 0x3F) != 0x3F) {
1927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* unmasked exceptions! */
1928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ew = EmWarn_X86_x87exns;
1929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
1931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (((fpucw >> 8) & 3) != 3) {
1932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* unsupported precision */
1933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ew = EmWarn_X86_x87precision;
1934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (((ULong)ew) << 32) | ((ULong)rmode);
1937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CLEAN HELPER */
1941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Given fpround as an IRRoundingMode value, create a suitable x87
1942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   native format FPU control word. */
1943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong amd64g_create_fpucw ( ULong fpround )
1944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   fpround &= 3;
1946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return 0x037F | (fpround << 10);
1947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This is used to implement 'fldenv'.
1951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Reads 28 bytes at x87_state[0 .. 27]. */
1952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CALLED FROM GENERATED CODE */
1953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DIRTY HELPER */
1954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownVexEmWarn amd64g_dirtyhelper_FLDENV ( /*OUT*/VexGuestAMD64State* vex_state,
1955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      /*IN*/HWord x87_state)
1956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1957663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return do_put_x87( False, (UChar*)x87_state, vex_state );
1958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CALLED FROM GENERATED CODE */
1962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DIRTY HELPER */
1963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Create an x87 FPU env from the guest state, as close as we can
1964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   approximate it.  Writes 28 bytes at x87_state[0..27]. */
1965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid amd64g_dirtyhelper_FSTENV ( /*IN*/VexGuestAMD64State* vex_state,
1966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 /*OUT*/HWord x87_state )
1967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int        i, stno, preg;
1969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt       tagw;
1970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar*     vexTags = (UChar*)(&vex_state->guest_FPTAG[0]);
1971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Fpu_State* x87     = (Fpu_State*)x87_state;
1972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt       ftop    = vex_state->guest_FTOP;
1973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong      c3210   = vex_state->guest_FC3210;
1974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < 14; i++)
1976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      x87->env[i] = 0;
1977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   x87->env[1] = x87->env[3] = x87->env[5] = x87->env[13] = 0xFFFF;
1979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   x87->env[FP_ENV_STAT]
1980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = toUShort(toUInt( ((ftop & 7) << 11) | (c3210 & 0x4700) ));
1981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   x87->env[FP_ENV_CTRL]
1982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = toUShort(toUInt( amd64g_create_fpucw( vex_state->guest_FPROUND ) ));
1983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Compute the x87 tag word. */
1985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tagw = 0;
1986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (stno = 0; stno < 8; stno++) {
1987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      preg = (stno + ftop) & 7;
1988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (vexTags[preg] == 0) {
1989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* register is empty */
1990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tagw |= (3 << (2*preg));
1991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
1992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* register is full. */
1993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tagw |= (0 << (2*preg));
1994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   x87->env[FP_ENV_TAG] = toUShort(tagw);
1997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* We don't dump the x87 registers, tho. */
1999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2002663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* This is used to implement 'fnsave'.
2003663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Writes 108 bytes at x87_state[0 .. 107]. */
2004663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* CALLED FROM GENERATED CODE */
2005663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* DIRTY HELPER */
2006663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengvoid amd64g_dirtyhelper_FNSAVE ( /*IN*/VexGuestAMD64State* vex_state,
2007663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                 /*OUT*/HWord x87_state)
2008663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
2009663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   do_get_x87( vex_state, (UChar*)x87_state );
2010663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
2011663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2012663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2013663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* This is used to implement 'fnsaves'.
2014663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Writes 94 bytes at x87_state[0 .. 93]. */
2015663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* CALLED FROM GENERATED CODE */
2016663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* DIRTY HELPER */
2017663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengvoid amd64g_dirtyhelper_FNSAVES ( /*IN*/VexGuestAMD64State* vex_state,
2018663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  /*OUT*/HWord x87_state)
2019663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
2020663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int           i, stno, preg;
2021663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt          tagw;
2022663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   ULong*        vexRegs = (ULong*)(&vex_state->guest_FPREG[0]);
2023663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar*        vexTags = (UChar*)(&vex_state->guest_FPTAG[0]);
2024663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Fpu_State_16* x87     = (Fpu_State_16*)x87_state;
2025663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt          ftop    = vex_state->guest_FTOP;
2026663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt          c3210   = vex_state->guest_FC3210;
2027663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2028663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   for (i = 0; i < 7; i++)
2029663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      x87->env[i] = 0;
2030663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2031663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   x87->env[FPS_ENV_STAT]
2032663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      = toUShort(((ftop & 7) << 11) | (c3210 & 0x4700));
2033663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   x87->env[FPS_ENV_CTRL]
2034663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      = toUShort(amd64g_create_fpucw( vex_state->guest_FPROUND ));
2035663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2036663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Dump the register stack in ST order. */
2037663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   tagw = 0;
2038663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   for (stno = 0; stno < 8; stno++) {
2039663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      preg = (stno + ftop) & 7;
2040663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (vexTags[preg] == 0) {
2041663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* register is empty */
2042663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         tagw |= (3 << (2*preg));
2043663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         convert_f64le_to_f80le( (UChar*)&vexRegs[preg],
2044663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                 &x87->reg[10*stno] );
2045663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      } else {
2046663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* register is full. */
2047663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         tagw |= (0 << (2*preg));
2048663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         convert_f64le_to_f80le( (UChar*)&vexRegs[preg],
2049663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                 &x87->reg[10*stno] );
2050663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
2051663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
2052663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   x87->env[FPS_ENV_TAG] = toUShort(tagw);
2053663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
2054663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2055663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2056663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* This is used to implement 'frstor'.
2057663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Reads 108 bytes at x87_state[0 .. 107]. */
2058663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* CALLED FROM GENERATED CODE */
2059663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* DIRTY HELPER */
2060663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengVexEmWarn amd64g_dirtyhelper_FRSTOR ( /*OUT*/VexGuestAMD64State* vex_state,
2061663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                      /*IN*/HWord x87_state)
2062663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
2063663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return do_put_x87( True, (UChar*)x87_state, vex_state );
2064663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
2065663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2066663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2067663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* This is used to implement 'frstors'.
2068663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Reads 94 bytes at x87_state[0 .. 93]. */
2069663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* CALLED FROM GENERATED CODE */
2070663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* DIRTY HELPER */
2071663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengVexEmWarn amd64g_dirtyhelper_FRSTORS ( /*OUT*/VexGuestAMD64State* vex_state,
2072663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                       /*IN*/HWord x87_state)
2073663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
2074663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int           stno, preg;
2075663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt          tag;
2076663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   ULong*        vexRegs = (ULong*)(&vex_state->guest_FPREG[0]);
2077663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar*        vexTags = (UChar*)(&vex_state->guest_FPTAG[0]);
2078663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Fpu_State_16* x87     = (Fpu_State_16*)x87_state;
2079663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt          ftop    = (x87->env[FPS_ENV_STAT] >> 11) & 7;
2080663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt          tagw    = x87->env[FPS_ENV_TAG];
2081663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt          fpucw   = x87->env[FPS_ENV_CTRL];
2082663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt          c3210   = x87->env[FPS_ENV_STAT] & 0x4700;
2083663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   VexEmWarn     ew;
2084663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt          fpround;
2085663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   ULong         pair;
2086663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2087663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Copy registers and tags */
2088663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   for (stno = 0; stno < 8; stno++) {
2089663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      preg = (stno + ftop) & 7;
2090663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      tag = (tagw >> (2*preg)) & 3;
2091663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (tag == 3) {
2092663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* register is empty */
2093663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* hmm, if it's empty, does it still get written?  Probably
2094663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            safer to say it does.  If we don't, memcheck could get out
2095663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            of sync, in that it thinks all FP registers are defined by
2096663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            this helper, but in reality some have not been updated. */
2097663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vexRegs[preg] = 0; /* IEEE754 64-bit zero */
2098663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vexTags[preg] = 0;
2099663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      } else {
2100663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* register is non-empty */
2101663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         convert_f80le_to_f64le( &x87->reg[10*stno],
2102663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                 (UChar*)&vexRegs[preg] );
2103663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vexTags[preg] = 1;
2104663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
2105663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
2106663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2107663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* stack pointer */
2108663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vex_state->guest_FTOP = ftop;
2109663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2110663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* status word */
2111663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vex_state->guest_FC3210 = c3210;
2112663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2113663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* handle the control word, setting FPROUND and detecting any
2114663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      emulation warnings. */
2115663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   pair    = amd64g_check_fldcw ( (ULong)fpucw );
2116663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   fpround = (UInt)pair & 0xFFFFFFFFULL;
2117663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   ew      = (VexEmWarn)(pair >> 32);
2118663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2119663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vex_state->guest_FPROUND = fpround & 3;
2120663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2121663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* emulation warnings --> caller */
2122663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return ew;
2123663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
2124663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2125663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
2127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Misc integer helpers, including rotates and CPUID.      ---*/
2128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
2129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Claim to be the following CPU, which is probably representative of
2131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the lowliest (earliest) amd64 offerings.  It can do neither sse3
2132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   nor cx16.
2133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vendor_id       : AuthenticAMD
2135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cpu family      : 15
2136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   model           : 5
2137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   model name      : AMD Opteron (tm) Processor 848
2138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stepping        : 10
2139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cpu MHz         : 1797.682
2140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cache size      : 1024 KB
2141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   fpu             : yes
2142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   fpu_exception   : yes
2143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cpuid level     : 1
2144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   wp              : yes
2145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   flags           : fpu vme de pse tsc msr pae mce cx8 apic sep
2146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mtrr pge mca cmov pat pse36 clflush mmx fxsr
2147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     sse sse2 syscall nx mmxext lm 3dnowext 3dnow
2148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bogomips        : 3600.62
2149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   TLB size        : 1088 4K pages
2150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   clflush size    : 64
2151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cache_alignment : 64
2152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   address sizes   : 40 bits physical, 48 bits virtual
2153663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   power management: ts fid vid ttp
2154663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2155663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   2012-Feb-21: don't claim 3dnow or 3dnowext, since in fact
2156663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   we don't support them.  See #291568.  3dnow is 80000001.EDX.31
2157663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   and 3dnowext is 80000001.EDX.30.
2158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
2159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid amd64g_dirtyhelper_CPUID_baseline ( VexGuestAMD64State* st )
2160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define SET_ABCD(_a,_b,_c,_d)                \
2162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do { st->guest_RAX = (ULong)(_a);        \
2163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           st->guest_RBX = (ULong)(_b);        \
2164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           st->guest_RCX = (ULong)(_c);        \
2165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           st->guest_RDX = (ULong)(_d);        \
2166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } while (0)
2167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (0xFFFFFFFF & st->guest_RAX) {
2169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x00000000:
2170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_ABCD(0x00000001, 0x68747541, 0x444d4163, 0x69746e65);
2171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x00000001:
2173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_ABCD(0x00000f5a, 0x01000800, 0x00000000, 0x078bfbff);
2174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x80000000:
2176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_ABCD(0x80000018, 0x68747541, 0x444d4163, 0x69746e65);
2177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x80000001:
2179663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Don't claim to support 3dnow or 3dnowext.  0xe1d3fbff is
2180663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            the original it-is-supported value that the h/w provides.
2181663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            See #291568. */
2182663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         SET_ABCD(0x00000f5a, 0x00000505, 0x00000000, /*0xe1d3fbff*/
2183663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                                      0x21d3fbff);
2184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x80000002:
2186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_ABCD(0x20444d41, 0x6574704f, 0x206e6f72, 0x296d7428);
2187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x80000003:
2189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_ABCD(0x6f725020, 0x73736563, 0x3820726f, 0x00003834);
2190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x80000004:
2192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x80000005:
2195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_ABCD(0xff08ff08, 0xff20ff20, 0x40020140, 0x40020140);
2196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x80000006:
2198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_ABCD(0x00000000, 0x42004200, 0x04008140, 0x00000000);
2199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x80000007:
2201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x0000000f);
2202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x80000008:
2204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_ABCD(0x00003028, 0x00000000, 0x00000000, 0x00000000);
2205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
2207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef SET_ABCD
2211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Claim to be the following CPU (2 x ...), which is sse3 and cx16
2215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   capable.
2216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vendor_id       : GenuineIntel
2218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cpu family      : 6
2219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   model           : 15
2220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   model name      : Intel(R) Core(TM)2 CPU 6600 @ 2.40GHz
2221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stepping        : 6
2222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cpu MHz         : 2394.000
2223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cache size      : 4096 KB
2224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   physical id     : 0
2225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   siblings        : 2
2226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   core id         : 0
2227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cpu cores       : 2
2228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   fpu             : yes
2229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   fpu_exception   : yes
2230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cpuid level     : 10
2231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   wp              : yes
2232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   flags           : fpu vme de pse tsc msr pae mce cx8 apic sep
2233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mtrr pge mca cmov pat pse36 clflush dts acpi
2234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mmx fxsr sse sse2 ss ht tm syscall nx lm
2235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     constant_tsc pni monitor ds_cpl vmx est tm2
2236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     cx16 xtpr lahf_lm
2237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bogomips        : 4798.78
2238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   clflush size    : 64
2239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cache_alignment : 64
2240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   address sizes   : 36 bits physical, 48 bits virtual
2241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   power management:
2242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
2243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid amd64g_dirtyhelper_CPUID_sse3_and_cx16 ( VexGuestAMD64State* st )
2244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define SET_ABCD(_a,_b,_c,_d)                \
2246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do { st->guest_RAX = (ULong)(_a);        \
2247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           st->guest_RBX = (ULong)(_b);        \
2248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           st->guest_RCX = (ULong)(_c);        \
2249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           st->guest_RDX = (ULong)(_d);        \
2250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } while (0)
2251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (0xFFFFFFFF & st->guest_RAX) {
2253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x00000000:
2254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_ABCD(0x0000000a, 0x756e6547, 0x6c65746e, 0x49656e69);
2255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x00000001:
2257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_ABCD(0x000006f6, 0x00020800, 0x0000e3bd, 0xbfebfbff);
2258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x00000002:
2260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_ABCD(0x05b0b101, 0x005657f0, 0x00000000, 0x2cb43049);
2261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x00000003:
2263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x00000004: {
2266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (0xFFFFFFFF & st->guest_RCX) {
2267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0x00000000: SET_ABCD(0x04000121, 0x01c0003f,
2268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      0x0000003f, 0x00000001); break;
2269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0x00000001: SET_ABCD(0x04000122, 0x01c0003f,
2270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      0x0000003f, 0x00000001); break;
2271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0x00000002: SET_ABCD(0x04004143, 0x03c0003f,
2272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      0x00000fff, 0x00000001); break;
2273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:         SET_ABCD(0x00000000, 0x00000000,
2274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      0x00000000, 0x00000000); break;
2275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x00000005:
2279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_ABCD(0x00000040, 0x00000040, 0x00000003, 0x00000020);
2280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x00000006:
2282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_ABCD(0x00000001, 0x00000002, 0x00000001, 0x00000000);
2283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x00000007:
2285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x00000008:
2288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_ABCD(0x00000400, 0x00000000, 0x00000000, 0x00000000);
2289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x00000009:
2291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x0000000a:
2294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      unhandled_eax_value:
2295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_ABCD(0x07280202, 0x00000000, 0x00000000, 0x00000000);
2296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x80000000:
2298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_ABCD(0x80000008, 0x00000000, 0x00000000, 0x00000000);
2299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x80000001:
2301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_ABCD(0x00000000, 0x00000000, 0x00000001, 0x20100800);
2302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x80000002:
2304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_ABCD(0x65746e49, 0x2952286c, 0x726f4320, 0x4d542865);
2305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x80000003:
2307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_ABCD(0x43203229, 0x20205550, 0x20202020, 0x20202020);
2308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x80000004:
2310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_ABCD(0x30303636, 0x20402020, 0x30342e32, 0x007a4847);
2311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x80000005:
2313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x80000006:
2316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_ABCD(0x00000000, 0x00000000, 0x10008040, 0x00000000);
2317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x80000007:
2319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x80000008:
2322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_ABCD(0x00003024, 0x00000000, 0x00000000, 0x00000000);
2323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
2325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto unhandled_eax_value;
2326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef SET_ABCD
2328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Claim to be the following CPU (4 x ...), which is sse4.2 and cx16
2332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   capable.
2333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vendor_id       : GenuineIntel
2335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cpu family      : 6
2336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   model           : 37
2337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   model name      : Intel(R) Core(TM) i5 CPU         670  @ 3.47GHz
2338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stepping        : 2
2339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cpu MHz         : 3334.000
2340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cache size      : 4096 KB
2341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   physical id     : 0
2342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   siblings        : 4
2343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   core id         : 0
2344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cpu cores       : 2
2345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   apicid          : 0
2346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   initial apicid  : 0
2347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   fpu             : yes
2348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   fpu_exception   : yes
2349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cpuid level     : 11
2350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   wp              : yes
2351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   flags           : fpu vme de pse tsc msr pae mce cx8 apic sep
2352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mtrr pge mca cmov pat pse36 clflush dts acpi
2353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp
2354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     lm constant_tsc arch_perfmon pebs bts rep_good
2355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     xtopology nonstop_tsc aperfmperf pni pclmulqdq
2356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16
2357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     xtpr pdcm sse4_1 sse4_2 popcnt aes lahf_lm ida
2358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     arat tpr_shadow vnmi flexpriority ept vpid
2359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bogomips        : 6957.57
2360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   clflush size    : 64
2361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cache_alignment : 64
2362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   address sizes   : 36 bits physical, 48 bits virtual
2363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   power management:
2364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
2365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid amd64g_dirtyhelper_CPUID_sse42_and_cx16 ( VexGuestAMD64State* st )
2366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define SET_ABCD(_a,_b,_c,_d)                \
2368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do { st->guest_RAX = (ULong)(_a);        \
2369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           st->guest_RBX = (ULong)(_b);        \
2370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           st->guest_RCX = (ULong)(_c);        \
2371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           st->guest_RDX = (ULong)(_d);        \
2372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } while (0)
2373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt old_eax = (UInt)st->guest_RAX;
2375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt old_ecx = (UInt)st->guest_RCX;
2376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (old_eax) {
2378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x00000000:
2379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_ABCD(0x0000000b, 0x756e6547, 0x6c65746e, 0x49656e69);
2380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x00000001:
2382663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         SET_ABCD(0x00020652, 0x00100800, 0x0298e3ff, 0xbfebfbff);
2383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x00000002:
2385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_ABCD(0x55035a01, 0x00f0b2e3, 0x00000000, 0x09ca212c);
2386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x00000003:
2388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x00000004:
2391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (old_ecx) {
2392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0x00000000: SET_ABCD(0x1c004121, 0x01c0003f,
2393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      0x0000003f, 0x00000000); break;
2394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0x00000001: SET_ABCD(0x1c004122, 0x00c0003f,
2395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      0x0000007f, 0x00000000); break;
2396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0x00000002: SET_ABCD(0x1c004143, 0x01c0003f,
2397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      0x000001ff, 0x00000000); break;
2398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0x00000003: SET_ABCD(0x1c03c163, 0x03c0003f,
2399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      0x00000fff, 0x00000002); break;
2400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:         SET_ABCD(0x00000000, 0x00000000,
2401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      0x00000000, 0x00000000); break;
2402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x00000005:
2405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_ABCD(0x00000040, 0x00000040, 0x00000003, 0x00001120);
2406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x00000006:
2408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_ABCD(0x00000007, 0x00000002, 0x00000001, 0x00000000);
2409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x00000007:
2411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x00000008:
2414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x00000009:
2417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x0000000a:
2420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_ABCD(0x07300403, 0x00000004, 0x00000000, 0x00000603);
2421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x0000000b:
2423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (old_ecx) {
2424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0x00000000:
2425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               SET_ABCD(0x00000001, 0x00000002,
2426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        0x00000100, 0x00000000); break;
2427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0x00000001:
2428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               SET_ABCD(0x00000004, 0x00000004,
2429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        0x00000201, 0x00000000); break;
2430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
2431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               SET_ABCD(0x00000000, 0x00000000,
2432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        old_ecx,    0x00000000); break;
2433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x0000000c:
2436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_ABCD(0x00000001, 0x00000002, 0x00000100, 0x00000000);
2437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x0000000d:
2439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (old_ecx) {
2440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0x00000000: SET_ABCD(0x00000001, 0x00000002,
2441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      0x00000100, 0x00000000); break;
2442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0x00000001: SET_ABCD(0x00000004, 0x00000004,
2443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      0x00000201, 0x00000000); break;
2444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:         SET_ABCD(0x00000000, 0x00000000,
2445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      old_ecx,    0x00000000); break;
2446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x80000000:
2449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_ABCD(0x80000008, 0x00000000, 0x00000000, 0x00000000);
2450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x80000001:
2452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_ABCD(0x00000000, 0x00000000, 0x00000001, 0x28100800);
2453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x80000002:
2455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_ABCD(0x65746e49, 0x2952286c, 0x726f4320, 0x4d542865);
2456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x80000003:
2458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_ABCD(0x35692029, 0x55504320, 0x20202020, 0x20202020);
2459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x80000004:
2461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_ABCD(0x30373620, 0x20402020, 0x37342e33, 0x007a4847);
2462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x80000005:
2464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x80000006:
2467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_ABCD(0x00000000, 0x00000000, 0x01006040, 0x00000000);
2468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x80000007:
2470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000100);
2471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x80000008:
2473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_ABCD(0x00003024, 0x00000000, 0x00000000, 0x00000000);
2474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
2476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_ABCD(0x00000001, 0x00000002, 0x00000100, 0x00000000);
2477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef SET_ABCD
2480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2483663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Claim to be the following CPU (4 x ...), which is AVX and cx16
2484663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   capable.
2485663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2486663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vendor_id       : GenuineIntel
2487663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   cpu family      : 6
2488663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   model           : 42
2489663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   model name      : Intel(R) Core(TM) i5-2300 CPU @ 2.80GHz
2490663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   stepping        : 7
2491663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   cpu MHz         : 1600.000
2492663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   cache size      : 6144 KB
2493663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   physical id     : 0
2494663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   siblings        : 4
2495663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   core id         : 3
2496663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   cpu cores       : 4
2497663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   apicid          : 6
2498663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   initial apicid  : 6
2499663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   fpu             : yes
2500663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   fpu_exception   : yes
2501663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   cpuid level     : 13
2502663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   wp              : yes
2503663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   flags           : fpu vme de pse tsc msr pae mce cx8 apic sep
2504663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     mtrr pge mca cmov pat pse36 clflush dts acpi
2505663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp
2506663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     lm constant_tsc arch_perfmon pebs bts rep_good
2507663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     nopl xtopology nonstop_tsc aperfmperf pni pclmulqdq
2508663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16
2509663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     xtpr pdcm sse4_1 sse4_2 popcnt aes xsave avx
2510663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     lahf_lm ida arat epb xsaveopt pln pts dts
2511663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     tpr_shadow vnmi flexpriority ept vpid
2512663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2513663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   bogomips        : 5768.94
2514663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   clflush size    : 64
2515663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   cache_alignment : 64
2516663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   address sizes   : 36 bits physical, 48 bits virtual
2517663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   power management:
2518663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng*/
2519663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengvoid amd64g_dirtyhelper_CPUID_avx_and_cx16 ( VexGuestAMD64State* st )
2520663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
2521663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  define SET_ABCD(_a,_b,_c,_d)                \
2522663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      do { st->guest_RAX = (ULong)(_a);        \
2523663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           st->guest_RBX = (ULong)(_b);        \
2524663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           st->guest_RCX = (ULong)(_c);        \
2525663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           st->guest_RDX = (ULong)(_d);        \
2526663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      } while (0)
2527663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2528663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt old_eax = (UInt)st->guest_RAX;
2529663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt old_ecx = (UInt)st->guest_RCX;
2530663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2531663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (old_eax) {
2532663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x00000000:
2533663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         SET_ABCD(0x0000000d, 0x756e6547, 0x6c65746e, 0x49656e69);
2534663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
2535663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x00000001:
2536663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         SET_ABCD(0x000206a7, 0x00100800, 0x1f9ae3bf, 0xbfebfbff);
2537663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
2538663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x00000002:
2539663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         SET_ABCD(0x76035a01, 0x00f0b0ff, 0x00000000, 0x00ca0000);
2540663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
2541663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x00000003:
2542663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2543663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
2544663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x00000004:
2545663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         switch (old_ecx) {
2546663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 0x00000000: SET_ABCD(0x1c004121, 0x01c0003f,
2547663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                      0x0000003f, 0x00000000); break;
2548663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 0x00000001: SET_ABCD(0x1c004122, 0x01c0003f,
2549663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                      0x0000003f, 0x00000000); break;
2550663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 0x00000002: SET_ABCD(0x1c004143, 0x01c0003f,
2551663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                      0x000001ff, 0x00000000); break;
2552663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 0x00000003: SET_ABCD(0x1c03c163, 0x02c0003f,
2553663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                      0x00001fff, 0x00000006); break;
2554663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            default:         SET_ABCD(0x00000000, 0x00000000,
2555663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                      0x00000000, 0x00000000); break;
2556663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
2557663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
2558663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x00000005:
2559663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         SET_ABCD(0x00000040, 0x00000040, 0x00000003, 0x00001120);
2560663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
2561663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x00000006:
2562663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         SET_ABCD(0x00000077, 0x00000002, 0x00000009, 0x00000000);
2563663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
2564663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x00000007:
2565663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2566663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
2567663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x00000008:
2568663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2569663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
2570663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x00000009:
2571663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2572663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
2573663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x0000000a:
2574663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         SET_ABCD(0x07300803, 0x00000000, 0x00000000, 0x00000603);
2575663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
2576663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x0000000b:
2577663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         switch (old_ecx) {
2578663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 0x00000000:
2579663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               SET_ABCD(0x00000001, 0x00000001,
2580663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        0x00000100, 0x00000000); break;
2581663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 0x00000001:
2582663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               SET_ABCD(0x00000004, 0x00000004,
2583663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        0x00000201, 0x00000000); break;
2584663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            default:
2585663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               SET_ABCD(0x00000000, 0x00000000,
2586663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        old_ecx,    0x00000000); break;
2587663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
2588663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
2589663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x0000000c:
2590663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2591663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
2592663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x0000000d:
2593663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         switch (old_ecx) {
2594663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 0x00000000: SET_ABCD(0x00000007, 0x00000340,
2595663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                      0x00000340, 0x00000000); break;
2596663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 0x00000001: SET_ABCD(0x00000001, 0x00000000,
2597663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                      0x00000000, 0x00000000); break;
2598663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 0x00000002: SET_ABCD(0x00000100, 0x00000240,
2599663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                      0x00000000, 0x00000000); break;
2600663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            default:         SET_ABCD(0x00000000, 0x00000000,
2601663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                      0x00000000, 0x00000000); break;
2602663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
2603663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
2604663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x0000000e:
2605663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         SET_ABCD(0x00000007, 0x00000340, 0x00000340, 0x00000000);
2606663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
2607663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x0000000f:
2608663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         SET_ABCD(0x00000007, 0x00000340, 0x00000340, 0x00000000);
2609663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
2610663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x80000000:
2611663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         SET_ABCD(0x80000008, 0x00000000, 0x00000000, 0x00000000);
2612663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
2613663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x80000001:
2614663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         SET_ABCD(0x00000000, 0x00000000, 0x00000001, 0x28100800);
2615663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
2616663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x80000002:
2617663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         SET_ABCD(0x20202020, 0x20202020, 0x65746e49, 0x2952286c);
2618663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
2619663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x80000003:
2620663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         SET_ABCD(0x726f4320, 0x4d542865, 0x35692029, 0x3033322d);
2621663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
2622663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x80000004:
2623663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         SET_ABCD(0x50432030, 0x20402055, 0x30382e32, 0x007a4847);
2624663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
2625663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x80000005:
2626663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2627663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
2628663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x80000006:
2629663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         SET_ABCD(0x00000000, 0x00000000, 0x01006040, 0x00000000);
2630663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
2631663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x80000007:
2632663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000100);
2633663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
2634663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x80000008:
2635663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         SET_ABCD(0x00003024, 0x00000000, 0x00000000, 0x00000000);
2636663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
2637663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default:
2638663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         SET_ABCD(0x00000007, 0x00000340, 0x00000340, 0x00000000);
2639663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
2640663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
2641663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  undef SET_ABCD
2642663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
2643663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2644663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong amd64g_calculate_RCR ( ULong arg,
2646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             ULong rot_amt,
2647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             ULong rflags_in,
2648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             Long  szIN )
2649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool  wantRflags = toBool(szIN < 0);
2651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong sz         = wantRflags ? (-szIN) : szIN;
2652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong tempCOUNT  = rot_amt & (sz == 8 ? 0x3F : 0x1F);
2653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong cf=0, of=0, tempcf;
2654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (sz) {
2656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 8:
2657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cf        = (rflags_in >> AMD64G_CC_SHIFT_C) & 1;
2658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         of        = ((arg >> 63) ^ cf) & 1;
2659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         while (tempCOUNT > 0) {
2660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tempcf = arg & 1;
2661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            arg    = (arg >> 1) | (cf << 63);
2662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cf     = tempcf;
2663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tempCOUNT--;
2664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 4:
2667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         while (tempCOUNT >= 33) tempCOUNT -= 33;
2668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cf        = (rflags_in >> AMD64G_CC_SHIFT_C) & 1;
2669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         of        = ((arg >> 31) ^ cf) & 1;
2670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         while (tempCOUNT > 0) {
2671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tempcf = arg & 1;
2672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            arg    = ((arg >> 1) & 0x7FFFFFFFULL) | (cf << 31);
2673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cf     = tempcf;
2674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tempCOUNT--;
2675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2:
2678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         while (tempCOUNT >= 17) tempCOUNT -= 17;
2679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cf        = (rflags_in >> AMD64G_CC_SHIFT_C) & 1;
2680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         of        = ((arg >> 15) ^ cf) & 1;
2681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         while (tempCOUNT > 0) {
2682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tempcf = arg & 1;
2683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            arg    = ((arg >> 1) & 0x7FFFULL) | (cf << 15);
2684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cf     = tempcf;
2685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tempCOUNT--;
2686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 1:
2689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         while (tempCOUNT >= 9) tempCOUNT -= 9;
2690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cf        = (rflags_in >> AMD64G_CC_SHIFT_C) & 1;
2691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         of        = ((arg >> 7) ^ cf) & 1;
2692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         while (tempCOUNT > 0) {
2693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tempcf = arg & 1;
2694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            arg    = ((arg >> 1) & 0x7FULL) | (cf << 7);
2695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cf     = tempcf;
2696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tempCOUNT--;
2697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
2700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("calculate_RCR(amd64g): invalid size");
2701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cf &= 1;
2704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   of &= 1;
2705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   rflags_in &= ~(AMD64G_CC_MASK_C | AMD64G_CC_MASK_O);
2706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   rflags_in |= (cf << AMD64G_CC_SHIFT_C) | (of << AMD64G_CC_SHIFT_O);
2707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* caller can ask to have back either the resulting flags or
2709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      resulting value, but not both */
2710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return wantRflags ? rflags_in : arg;
2711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong amd64g_calculate_RCL ( ULong arg,
2714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             ULong rot_amt,
2715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             ULong rflags_in,
2716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             Long  szIN )
2717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool  wantRflags = toBool(szIN < 0);
2719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong sz         = wantRflags ? (-szIN) : szIN;
2720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong tempCOUNT  = rot_amt & (sz == 8 ? 0x3F : 0x1F);
2721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong cf=0, of=0, tempcf;
2722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (sz) {
2724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 8:
2725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cf = (rflags_in >> AMD64G_CC_SHIFT_C) & 1;
2726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         while (tempCOUNT > 0) {
2727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tempcf = (arg >> 63) & 1;
2728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            arg    = (arg << 1) | (cf & 1);
2729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cf     = tempcf;
2730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tempCOUNT--;
2731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         of = ((arg >> 63) ^ cf) & 1;
2733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 4:
2735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         while (tempCOUNT >= 33) tempCOUNT -= 33;
2736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cf = (rflags_in >> AMD64G_CC_SHIFT_C) & 1;
2737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         while (tempCOUNT > 0) {
2738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tempcf = (arg >> 31) & 1;
2739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            arg    = 0xFFFFFFFFULL & ((arg << 1) | (cf & 1));
2740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cf     = tempcf;
2741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tempCOUNT--;
2742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         of = ((arg >> 31) ^ cf) & 1;
2744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2:
2746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         while (tempCOUNT >= 17) tempCOUNT -= 17;
2747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cf = (rflags_in >> AMD64G_CC_SHIFT_C) & 1;
2748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         while (tempCOUNT > 0) {
2749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tempcf = (arg >> 15) & 1;
2750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            arg    = 0xFFFFULL & ((arg << 1) | (cf & 1));
2751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cf     = tempcf;
2752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tempCOUNT--;
2753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         of = ((arg >> 15) ^ cf) & 1;
2755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 1:
2757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         while (tempCOUNT >= 9) tempCOUNT -= 9;
2758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cf = (rflags_in >> AMD64G_CC_SHIFT_C) & 1;
2759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         while (tempCOUNT > 0) {
2760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tempcf = (arg >> 7) & 1;
2761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            arg    = 0xFFULL & ((arg << 1) | (cf & 1));
2762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cf     = tempcf;
2763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tempCOUNT--;
2764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         of = ((arg >> 7) ^ cf) & 1;
2766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
2768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("calculate_RCL(amd64g): invalid size");
2769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cf &= 1;
2772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   of &= 1;
2773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   rflags_in &= ~(AMD64G_CC_MASK_C | AMD64G_CC_MASK_O);
2774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   rflags_in |= (cf << AMD64G_CC_SHIFT_C) | (of << AMD64G_CC_SHIFT_O);
2775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return wantRflags ? rflags_in : arg;
2777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Taken from gf2x-0.9.5, released under GPLv2+ (later versions LGPLv2+)
2780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * svn://scm.gforge.inria.fr/svn/gf2x/trunk/hardware/opteron/gf2x_mul1.h@25
2781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
2782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong amd64g_calculate_pclmul(ULong a, ULong b, ULong which)
2783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ULong hi, lo, tmp, A[16];
2785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   A[0] = 0;            A[1] = a;
2787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   A[2] = A[1] << 1;    A[3] = A[2] ^ a;
2788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   A[4] = A[2] << 1;    A[5] = A[4] ^ a;
2789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   A[6] = A[3] << 1;    A[7] = A[6] ^ a;
2790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   A[8] = A[4] << 1;    A[9] = A[8] ^ a;
2791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   A[10] = A[5] << 1;   A[11] = A[10] ^ a;
2792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   A[12] = A[6] << 1;   A[13] = A[12] ^ a;
2793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   A[14] = A[7] << 1;   A[15] = A[14] ^ a;
2794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   lo = (A[b >> 60] << 4) ^ A[(b >> 56) & 15];
2796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   hi = lo >> 56;
2797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   lo = (lo << 8) ^ (A[(b >> 52) & 15] << 4) ^ A[(b >> 48) & 15];
2798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   hi = (hi << 8) | (lo >> 56);
2799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   lo = (lo << 8) ^ (A[(b >> 44) & 15] << 4) ^ A[(b >> 40) & 15];
2800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   hi = (hi << 8) | (lo >> 56);
2801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   lo = (lo << 8) ^ (A[(b >> 36) & 15] << 4) ^ A[(b >> 32) & 15];
2802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   hi = (hi << 8) | (lo >> 56);
2803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   lo = (lo << 8) ^ (A[(b >> 28) & 15] << 4) ^ A[(b >> 24) & 15];
2804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   hi = (hi << 8) | (lo >> 56);
2805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   lo = (lo << 8) ^ (A[(b >> 20) & 15] << 4) ^ A[(b >> 16) & 15];
2806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   hi = (hi << 8) | (lo >> 56);
2807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   lo = (lo << 8) ^ (A[(b >> 12) & 15] << 4) ^ A[(b >> 8) & 15];
2808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   hi = (hi << 8) | (lo >> 56);
2809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   lo = (lo << 8) ^ (A[(b >> 4) & 15] << 4) ^ A[b & 15];
2810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong m0 = -1;
2812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   m0 /= 255;
2813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tmp = -((a >> 63) & 1); tmp &= ((b & (m0 * 0xfe)) >> 1); hi = hi ^ tmp;
2814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tmp = -((a >> 62) & 1); tmp &= ((b & (m0 * 0xfc)) >> 2); hi = hi ^ tmp;
2815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tmp = -((a >> 61) & 1); tmp &= ((b & (m0 * 0xf8)) >> 3); hi = hi ^ tmp;
2816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tmp = -((a >> 60) & 1); tmp &= ((b & (m0 * 0xf0)) >> 4); hi = hi ^ tmp;
2817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tmp = -((a >> 59) & 1); tmp &= ((b & (m0 * 0xe0)) >> 5); hi = hi ^ tmp;
2818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tmp = -((a >> 58) & 1); tmp &= ((b & (m0 * 0xc0)) >> 6); hi = hi ^ tmp;
2819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tmp = -((a >> 57) & 1); tmp &= ((b & (m0 * 0x80)) >> 7); hi = hi ^ tmp;
2820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return which ? hi : lo;
2822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CALLED FROM GENERATED CODE */
2826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DIRTY HELPER (non-referentially-transparent) */
2827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Horrible hack.  On non-amd64 platforms, return 1. */
2828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong amd64g_dirtyhelper_RDTSC ( void )
2829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if defined(__x86_64__)
2831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  eax, edx;
2832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   __asm__ __volatile__("rdtsc" : "=a" (eax), "=d" (edx));
2833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (((ULong)edx) << 32) | ((ULong)eax);
2834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  else
2835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return 1ULL;
2836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
2837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CALLED FROM GENERATED CODE */
2841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DIRTY HELPER (non-referentially-transparent) */
2842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Horrible hack.  On non-amd64 platforms, return 0. */
2843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong amd64g_dirtyhelper_IN ( ULong portno, ULong sz/*1,2 or 4*/ )
2844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if defined(__x86_64__)
2846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong r = 0;
2847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   portno &= 0xFFFF;
2848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (sz) {
2849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 4:
2850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         __asm__ __volatile__("movq $0,%%rax; inl %w1,%%eax; movq %%rax,%0"
2851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              : "=a" (r) : "Nd" (portno));
2852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 break;
2853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2:
2854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         __asm__ __volatile__("movq $0,%%rax; inw %w1,%w0"
2855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              : "=a" (r) : "Nd" (portno));
2856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 break;
2857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 1:
2858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         __asm__ __volatile__("movq $0,%%rax; inb %w1,%b0"
2859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              : "=a" (r) : "Nd" (portno));
2860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 break;
2861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
2862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break; /* note: no 64-bit version of insn exists */
2863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return r;
2865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  else
2866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return 0;
2867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
2868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CALLED FROM GENERATED CODE */
2872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DIRTY HELPER (non-referentially-transparent) */
2873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Horrible hack.  On non-amd64 platforms, do nothing. */
2874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid amd64g_dirtyhelper_OUT ( ULong portno, ULong data, ULong sz/*1,2 or 4*/ )
2875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if defined(__x86_64__)
2877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   portno &= 0xFFFF;
2878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (sz) {
2879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 4:
2880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         __asm__ __volatile__("movq %0,%%rax; outl %%eax, %w1"
2881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              : : "a" (data), "Nd" (portno));
2882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 break;
2883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2:
2884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         __asm__ __volatile__("outw %w0, %w1"
2885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              : : "a" (data), "Nd" (portno));
2886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 break;
2887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 1:
2888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         __asm__ __volatile__("outb %b0, %w1"
2889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              : : "a" (data), "Nd" (portno));
2890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 break;
2891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
2892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break; /* note: no 64-bit version of insn exists */
2893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  else
2895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* do nothing */
2896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
2897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CALLED FROM GENERATED CODE */
2900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DIRTY HELPER (non-referentially-transparent) */
2901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Horrible hack.  On non-amd64 platforms, do nothing. */
2902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* op = 0: call the native SGDT instruction.
2903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   op = 1: call the native SIDT instruction.
2904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
2905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid amd64g_dirtyhelper_SxDT ( void *address, ULong op ) {
2906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if defined(__x86_64__)
2907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op) {
2908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0:
2909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         __asm__ __volatile__("sgdt (%0)" : : "r" (address) : "memory");
2910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 1:
2912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         __asm__ __volatile__("sidt (%0)" : : "r" (address) : "memory");
2913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
2915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("amd64g_dirtyhelper_SxDT");
2916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  else
2918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* do nothing */
2919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar* p = (UChar*)address;
2920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   p[0] = p[1] = p[2] = p[3] = p[4] = p[5] = 0;
2921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   p[6] = p[7] = p[8] = p[9] = 0;
2922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
2923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
2926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Helpers for MMX/SSE/SSE2.                               ---*/
2927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
2928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline UChar abdU8 ( UChar xx, UChar yy ) {
2930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toUChar(xx>yy ? xx-yy : yy-xx);
2931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline ULong mk32x2 ( UInt w1, UInt w0 ) {
2934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (((ULong)w1) << 32) | ((ULong)w0);
2935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline UShort sel16x4_3 ( ULong w64 ) {
2938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt hi32 = toUInt(w64 >> 32);
2939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toUShort(hi32 >> 16);
2940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline UShort sel16x4_2 ( ULong w64 ) {
2942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt hi32 = toUInt(w64 >> 32);
2943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toUShort(hi32);
2944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline UShort sel16x4_1 ( ULong w64 ) {
2946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt lo32 = toUInt(w64);
2947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toUShort(lo32 >> 16);
2948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline UShort sel16x4_0 ( ULong w64 ) {
2950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt lo32 = toUInt(w64);
2951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toUShort(lo32);
2952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline UChar sel8x8_7 ( ULong w64 ) {
2955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt hi32 = toUInt(w64 >> 32);
2956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toUChar(hi32 >> 24);
2957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline UChar sel8x8_6 ( ULong w64 ) {
2959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt hi32 = toUInt(w64 >> 32);
2960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toUChar(hi32 >> 16);
2961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline UChar sel8x8_5 ( ULong w64 ) {
2963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt hi32 = toUInt(w64 >> 32);
2964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toUChar(hi32 >> 8);
2965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline UChar sel8x8_4 ( ULong w64 ) {
2967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt hi32 = toUInt(w64 >> 32);
2968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toUChar(hi32 >> 0);
2969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline UChar sel8x8_3 ( ULong w64 ) {
2971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt lo32 = toUInt(w64);
2972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toUChar(lo32 >> 24);
2973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline UChar sel8x8_2 ( ULong w64 ) {
2975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt lo32 = toUInt(w64);
2976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toUChar(lo32 >> 16);
2977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline UChar sel8x8_1 ( ULong w64 ) {
2979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt lo32 = toUInt(w64);
2980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toUChar(lo32 >> 8);
2981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline UChar sel8x8_0 ( ULong w64 ) {
2983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt lo32 = toUInt(w64);
2984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toUChar(lo32 >> 0);
2985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CALLED FROM GENERATED CODE: CLEAN HELPER */
2988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong amd64g_calculate_mmx_pmaddwd ( ULong xx, ULong yy )
2989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return
2991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      mk32x2(
2992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         (((Int)(Short)sel16x4_3(xx)) * ((Int)(Short)sel16x4_3(yy)))
2993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            + (((Int)(Short)sel16x4_2(xx)) * ((Int)(Short)sel16x4_2(yy))),
2994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         (((Int)(Short)sel16x4_1(xx)) * ((Int)(Short)sel16x4_1(yy)))
2995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            + (((Int)(Short)sel16x4_0(xx)) * ((Int)(Short)sel16x4_0(yy)))
2996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      );
2997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CALLED FROM GENERATED CODE: CLEAN HELPER */
3000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong amd64g_calculate_mmx_pmovmskb ( ULong xx )
3001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong r = 0;
3003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (xx & (1ULL << (64-1))) r |= (1<<7);
3004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (xx & (1ULL << (56-1))) r |= (1<<6);
3005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (xx & (1ULL << (48-1))) r |= (1<<5);
3006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (xx & (1ULL << (40-1))) r |= (1<<4);
3007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (xx & (1ULL << (32-1))) r |= (1<<3);
3008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (xx & (1ULL << (24-1))) r |= (1<<2);
3009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (xx & (1ULL << (16-1))) r |= (1<<1);
3010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (xx & (1ULL << ( 8-1))) r |= (1<<0);
3011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return r;
3012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CALLED FROM GENERATED CODE: CLEAN HELPER */
3015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong amd64g_calculate_mmx_psadbw ( ULong xx, ULong yy )
3016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt t = 0;
3018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   t += (UInt)abdU8( sel8x8_7(xx), sel8x8_7(yy) );
3019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   t += (UInt)abdU8( sel8x8_6(xx), sel8x8_6(yy) );
3020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   t += (UInt)abdU8( sel8x8_5(xx), sel8x8_5(yy) );
3021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   t += (UInt)abdU8( sel8x8_4(xx), sel8x8_4(yy) );
3022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   t += (UInt)abdU8( sel8x8_3(xx), sel8x8_3(yy) );
3023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   t += (UInt)abdU8( sel8x8_2(xx), sel8x8_2(yy) );
3024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   t += (UInt)abdU8( sel8x8_1(xx), sel8x8_1(yy) );
3025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   t += (UInt)abdU8( sel8x8_0(xx), sel8x8_0(yy) );
3026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   t &= 0xFFFF;
3027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (ULong)t;
3028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CALLED FROM GENERATED CODE: CLEAN HELPER */
3031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong amd64g_calculate_sse_pmovmskb ( ULong w64hi, ULong w64lo )
3032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong rHi8 = amd64g_calculate_mmx_pmovmskb ( w64hi );
3034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong rLo8 = amd64g_calculate_mmx_pmovmskb ( w64lo );
3035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ((rHi8 & 0xFF) << 8) | (rLo8 & 0xFF);
3036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3038f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root/* CALLED FROM GENERATED CODE: CLEAN HELPER */
3039663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengULong amd64g_calculate_sse_phminposuw ( ULong sLo, ULong sHi )
3040663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
3041663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UShort t, min;
3042663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   idx;
3043663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t = sel16x4_0(sLo); if (True)    { min = t; idx = 0; }
3044663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t = sel16x4_1(sLo); if (t < min) { min = t; idx = 1; }
3045663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t = sel16x4_2(sLo); if (t < min) { min = t; idx = 2; }
3046663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t = sel16x4_3(sLo); if (t < min) { min = t; idx = 3; }
3047663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t = sel16x4_0(sHi); if (t < min) { min = t; idx = 4; }
3048663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t = sel16x4_1(sHi); if (t < min) { min = t; idx = 5; }
3049663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t = sel16x4_2(sHi); if (t < min) { min = t; idx = 6; }
3050663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t = sel16x4_3(sHi); if (t < min) { min = t; idx = 7; }
3051663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return ((ULong)(idx << 16)) | ((ULong)min);
3052663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
3053663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3054663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* CALLED FROM GENERATED CODE: CLEAN HELPER */
3055f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny RootULong amd64g_calc_crc32b ( ULong crcIn, ULong b )
3056f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root{
3057f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   UInt  i;
3058f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   ULong crc = (b & 0xFFULL) ^ crcIn;
3059f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   for (i = 0; i < 8; i++)
3060f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      crc = (crc >> 1) ^ ((crc & 1) ? 0x82f63b78ULL : 0);
3061f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   return crc;
3062f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root}
3063f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
3064f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root/* CALLED FROM GENERATED CODE: CLEAN HELPER */
3065f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny RootULong amd64g_calc_crc32w ( ULong crcIn, ULong w )
3066f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root{
3067f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   UInt  i;
3068f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   ULong crc = (w & 0xFFFFULL) ^ crcIn;
3069f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   for (i = 0; i < 16; i++)
3070f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      crc = (crc >> 1) ^ ((crc & 1) ? 0x82f63b78ULL : 0);
3071f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   return crc;
3072f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root}
3073f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
3074f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root/* CALLED FROM GENERATED CODE: CLEAN HELPER */
3075f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny RootULong amd64g_calc_crc32l ( ULong crcIn, ULong l )
3076f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root{
3077f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   UInt i;
3078f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   ULong crc = (l & 0xFFFFFFFFULL) ^ crcIn;
3079f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   for (i = 0; i < 32; i++)
3080f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      crc = (crc >> 1) ^ ((crc & 1) ? 0x82f63b78ULL : 0);
3081f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   return crc;
3082f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root}
3083f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
3084f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root/* CALLED FROM GENERATED CODE: CLEAN HELPER */
3085f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny RootULong amd64g_calc_crc32q ( ULong crcIn, ULong q )
3086f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root{
3087f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   ULong crc = amd64g_calc_crc32l(crcIn, q);
3088f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   return amd64g_calc_crc32l(crc, q >> 32);
3089f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root}
3090f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
3091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3092663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* .. helper for next fn .. */
3093663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic inline ULong sad_8x4 ( ULong xx, ULong yy )
3094663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
3095663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt t = 0;
3096663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t += (UInt)abdU8( sel8x8_3(xx), sel8x8_3(yy) );
3097663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t += (UInt)abdU8( sel8x8_2(xx), sel8x8_2(yy) );
3098663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t += (UInt)abdU8( sel8x8_1(xx), sel8x8_1(yy) );
3099663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t += (UInt)abdU8( sel8x8_0(xx), sel8x8_0(yy) );
3100663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return (ULong)t;
3101663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
3102663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3103663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* CALLED FROM GENERATED CODE: CLEAN HELPER */
3104663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengULong amd64g_calc_mpsadbw ( ULong sHi, ULong sLo,
3105663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            ULong dHi, ULong dLo,
3106663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            ULong imm_and_return_control_bit )
3107663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
3108663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt imm8     = imm_and_return_control_bit & 7;
3109663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Bool calcHi   = (imm_and_return_control_bit >> 7) & 1;
3110663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt srcOffsL = imm8 & 3; /* src offs in 32-bit (L) chunks */
3111663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt dstOffsL = (imm8 >> 2) & 1; /* dst offs in ditto chunks */
3112663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* For src we only need 32 bits, so get them into the
3113663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      lower half of a 64 bit word. */
3114663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   ULong src = ((srcOffsL & 2) ? sHi : sLo) >> (32 * (srcOffsL & 1));
3115663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* For dst we need to get hold of 56 bits (7 bytes) from a total of
3116663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      11 bytes.  If calculating the low part of the result, need bytes
3117663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      dstOffsL * 4 + (0 .. 6); if calculating the high part,
3118663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      dstOffsL * 4 + (4 .. 10). */
3119663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   ULong dst;
3120663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* dstOffL = 0, Lo  ->  0 .. 6
3121663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      dstOffL = 1, Lo  ->  4 .. 10
3122663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      dstOffL = 0, Hi  ->  4 .. 10
3123663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      dstOffL = 1, Hi  ->  8 .. 14
3124663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   */
3125663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (calcHi && dstOffsL) {
3126663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 8 .. 14 */
3127663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      dst = dHi & 0x00FFFFFFFFFFFFFFULL;
3128663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
3129663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   else if (!calcHi && !dstOffsL) {
3130663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0 .. 6 */
3131663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      dst = dLo & 0x00FFFFFFFFFFFFFFULL;
3132663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
3133663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   else {
3134663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 4 .. 10 */
3135663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      dst = (dLo >> 32) | ((dHi & 0x00FFFFFFULL) << 32);
3136663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
3137663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   ULong r0  = sad_8x4( dst >>  0, src );
3138663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   ULong r1  = sad_8x4( dst >>  8, src );
3139663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   ULong r2  = sad_8x4( dst >> 16, src );
3140663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   ULong r3  = sad_8x4( dst >> 24, src );
3141663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   ULong res = (r3 << 48) | (r2 << 32) | (r1 << 16) | r0;
3142663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return res;
3143663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
3144663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
3146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Helpers for SSE4.2 PCMP{E,I}STR{I,M}                    ---*/
3147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
3148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt zmask_from_V128 ( V128* arg )
3150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt i, res = 0;
3152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < 16; i++) {
3153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      res |=  ((arg->w8[i] == 0) ? 1 : 0) << i;
3154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return res;
3156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3158663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic UInt zmask_from_V128_wide ( V128* arg )
3159663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
3160663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt i, res = 0;
3161663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   for (i = 0; i < 8; i++) {
3162663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      res |=  ((arg->w16[i] == 0) ? 1 : 0) << i;
3163663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
3164663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return res;
3165663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
3166663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Helps with PCMP{I,E}STR{I,M}.
3168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CALLED FROM GENERATED CODE: DIRTY HELPER(s).  (But not really,
3170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   actually it could be a clean helper, but for the fact that we can't
3171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   pass by value 2 x V128 to a clean helper, nor have one returned.)
3172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Reads guest state, writes to guest state for the xSTRM cases, no
3173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   accesses of memory, is a pure function.
3174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   opc_and_imm contains (4th byte of opcode << 8) | the-imm8-byte so
3176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the callee knows which I/E and I/M variant it is dealing with and
3177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   what the specific operation is.  4th byte of opcode is in the range
3178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   0x60 to 0x63:
3179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       istri  66 0F 3A 63
3180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       istrm  66 0F 3A 62
3181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       estri  66 0F 3A 61
3182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       estrm  66 0F 3A 60
3183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   gstOffL and gstOffR are the guest state offsets for the two XMM
3185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   register inputs.  We never have to deal with the memory case since
3186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   that is handled by pre-loading the relevant value into the fake
3187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   XMM16 register.
3188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   For ESTRx variants, edxIN and eaxIN hold the values of those two
3190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   registers.
3191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   In all cases, the bottom 16 bits of the result contain the new
3193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OSZACP %rflags values.  For xSTRI variants, bits[31:16] of the
3194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   result hold the new %ecx value.  For xSTRM variants, the helper
3195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   writes the result directly to the guest XMM0.
3196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Declarable side effects: in all cases, reads guest state at
3198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   [gstOffL, +16) and [gstOffR, +16).  For xSTRM variants, also writes
3199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   guest_XMM0.
3200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Is expected to be called with opc_and_imm combinations which have
3202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   actually been validated, and will assert if otherwise.  The front
3203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   end should ensure we're only called with verified values.
3204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
3205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong amd64g_dirtyhelper_PCMPxSTRx (
3206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          VexGuestAMD64State* gst,
3207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          HWord opc4_and_imm,
3208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          HWord gstOffL, HWord gstOffR,
3209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          HWord edxIN, HWord eaxIN
3210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       )
3211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HWord opc4 = (opc4_and_imm >> 8) & 0xFF;
3213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HWord imm8 = opc4_and_imm & 0xFF;
3214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HWord isISTRx = opc4 & 2;
3215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HWord isxSTRM = (opc4 & 1) ^ 1;
3216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert((opc4 & 0xFC) == 0x60); /* 0x60 .. 0x63 */
3217663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HWord wide = (imm8 & 1);
3218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // where the args are
3220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   V128* argL = (V128*)( ((UChar*)gst) + gstOffL );
3221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   V128* argR = (V128*)( ((UChar*)gst) + gstOffR );
3222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Create the arg validity masks, either from the vectors
3224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      themselves or from the supplied edx/eax values. */
3225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // FIXME: this is only right for the 8-bit data cases.
3226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // At least that is asserted above.
3227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt zmaskL, zmaskR;
3228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // temp spot for the resulting flags and vector.
3230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   V128 resV;
3231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt resOSZACP;
3232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3233663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // for checking whether case was handled
3234663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Bool ok = False;
3235663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3236663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (wide) {
3237663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (isISTRx) {
3238663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         zmaskL = zmask_from_V128_wide(argL);
3239663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         zmaskR = zmask_from_V128_wide(argR);
3240663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      } else {
3241663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int tmp;
3242663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         tmp = edxIN & 0xFFFFFFFF;
3243663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (tmp < -8) tmp = -8;
3244663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (tmp > 8)  tmp = 8;
3245663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (tmp < 0)  tmp = -tmp;
3246663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(tmp >= 0 && tmp <= 8);
3247663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         zmaskL = (1 << tmp) & 0xFF;
3248663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         tmp = eaxIN & 0xFFFFFFFF;
3249663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (tmp < -8) tmp = -8;
3250663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (tmp > 8)  tmp = 8;
3251663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (tmp < 0)  tmp = -tmp;
3252663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(tmp >= 0 && tmp <= 8);
3253663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         zmaskR = (1 << tmp) & 0xFF;
3254663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3255663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      // do the meyaath
3256663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ok = compute_PCMPxSTRx_wide (
3257663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              &resV, &resOSZACP, argL, argR,
3258663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              zmaskL, zmaskR, imm8, (Bool)isxSTRM
3259663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           );
3260663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
3261663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (isISTRx) {
3262663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         zmaskL = zmask_from_V128(argL);
3263663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         zmaskR = zmask_from_V128(argR);
3264663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      } else {
3265663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int tmp;
3266663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         tmp = edxIN & 0xFFFFFFFF;
3267663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (tmp < -16) tmp = -16;
3268663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (tmp > 16)  tmp = 16;
3269663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (tmp < 0)   tmp = -tmp;
3270663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(tmp >= 0 && tmp <= 16);
3271663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         zmaskL = (1 << tmp) & 0xFFFF;
3272663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         tmp = eaxIN & 0xFFFFFFFF;
3273663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (tmp < -16) tmp = -16;
3274663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (tmp > 16)  tmp = 16;
3275663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (tmp < 0)   tmp = -tmp;
3276663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(tmp >= 0 && tmp <= 16);
3277663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         zmaskR = (1 << tmp) & 0xFFFF;
3278663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3279663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      // do the meyaath
3280663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ok = compute_PCMPxSTRx (
3281663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              &resV, &resOSZACP, argL, argR,
3282663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              zmaskL, zmaskR, imm8, (Bool)isxSTRM
3283663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           );
3284663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
3285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // front end shouldn't pass us any imm8 variants we can't
3287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // handle.  Hence:
3288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(ok);
3289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // So, finally we need to get the results back to the caller.
3291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // In all cases, the new OSZACP value is the lowest 16 of
3292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // the return value.
3293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (isxSTRM) {
3294663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      gst->guest_YMM0[0] = resV.w32[0];
3295663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      gst->guest_YMM0[1] = resV.w32[1];
3296663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      gst->guest_YMM0[2] = resV.w32[2];
3297663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      gst->guest_YMM0[3] = resV.w32[3];
3298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return resOSZACP & 0x8D5;
3299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
3300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt newECX = resV.w32[0] & 0xFFFF;
3301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return (newECX << 16) | (resOSZACP & 0x8D5);
3302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3305663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---------------------------------------------------------------*/
3306663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*--- AES primitives and helpers                              ---*/
3307663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---------------------------------------------------------------*/
3308663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* a 16 x 16 matrix */
3309663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic const UChar sbox[256] = {                   // row nr
3310663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, // 1
3311663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
3312663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, // 2
3313663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
3314663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, // 3
3315663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
3316663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, // 4
3317663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
3318663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, // 5
3319663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
3320663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, // 6
3321663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
3322663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, // 7
3323663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
3324663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, // 8
3325663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
3326663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, // 9
3327663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
3328663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, //10
3329663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
3330663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, //11
3331663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
3332663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, //12
3333663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
3334663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, //13
3335663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
3336663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, //14
3337663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
3338663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, //15
3339663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
3340663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, //16
3341663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
3342663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng};
3343663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void SubBytes (V128* v)
3344663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
3345663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   V128 r;
3346663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt i;
3347663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   for (i = 0; i < 16; i++)
3348663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      r.w8[i] = sbox[v->w8[i]];
3349663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *v = r;
3350663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
3351663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3352663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* a 16 x 16 matrix */
3353663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic const UChar invsbox[256] = {                // row nr
3354663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, // 1
3355663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
3356663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, // 2
3357663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
3358663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, // 3
3359663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
3360663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, // 4
3361663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
3362663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, // 5
3363663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
3364663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, // 6
3365663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
3366663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, // 7
3367663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
3368663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, // 8
3369663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
3370663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, // 9
3371663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
3372663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, //10
3373663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
3374663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, //11
3375663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
3376663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, //12
3377663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
3378663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, //13
3379663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
3380663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, //14
3381663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
3382663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, //15
3383663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
3384663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, //16
3385663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
3386663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng};
3387663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void InvSubBytes (V128* v)
3388663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
3389663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   V128 r;
3390663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt i;
3391663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   for (i = 0; i < 16; i++)
3392663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      r.w8[i] = invsbox[v->w8[i]];
3393663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *v = r;
3394663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
3395663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3396663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic const UChar ShiftRows_op[16] =
3397663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   {11, 6, 1, 12, 7, 2, 13, 8, 3, 14, 9, 4, 15, 10, 5, 0};
3398663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void ShiftRows (V128* v)
3399663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
3400663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   V128 r;
3401663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt i;
3402663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   for (i = 0; i < 16; i++)
3403663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      r.w8[i] = v->w8[ShiftRows_op[15-i]];
3404663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *v = r;
3405663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
3406663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3407663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic const UChar InvShiftRows_op[16] =
3408663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   {3, 6, 9, 12, 15, 2, 5, 8, 11, 14, 1, 4, 7, 10, 13, 0};
3409663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void InvShiftRows (V128* v)
3410663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
3411663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   V128 r;
3412663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt i;
3413663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   for (i = 0; i < 16; i++)
3414663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      r.w8[i] = v->w8[InvShiftRows_op[15-i]];
3415663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *v = r;
3416663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
3417663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3418663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Multiplication of the finite fields elements of AES.
3419663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   See "A Specification for The AES Algorithm Rijndael
3420663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        (by Joan Daemen & Vincent Rijmen)"
3421663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        Dr. Brian Gladman, v3.1, 3rd March 2001. */
3422663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* N values so that (hex) xy = 0x03^N.
3423663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x00 cannot be used. We put 0xff for this value.*/
3424663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* a 16 x 16 matrix */
3425663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic const UChar Nxy[256] = {                    // row nr
3426663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xff, 0x00, 0x19, 0x01, 0x32, 0x02, 0x1a, 0xc6, // 1
3427663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x4b, 0xc7, 0x1b, 0x68, 0x33, 0xee, 0xdf, 0x03,
3428663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x64, 0x04, 0xe0, 0x0e, 0x34, 0x8d, 0x81, 0xef, // 2
3429663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x4c, 0x71, 0x08, 0xc8, 0xf8, 0x69, 0x1c, 0xc1,
3430663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x7d, 0xc2, 0x1d, 0xb5, 0xf9, 0xb9, 0x27, 0x6a, // 3
3431663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x4d, 0xe4, 0xa6, 0x72, 0x9a, 0xc9, 0x09, 0x78,
3432663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x65, 0x2f, 0x8a, 0x05, 0x21, 0x0f, 0xe1, 0x24, // 4
3433663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x12, 0xf0, 0x82, 0x45, 0x35, 0x93, 0xda, 0x8e,
3434663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x96, 0x8f, 0xdb, 0xbd, 0x36, 0xd0, 0xce, 0x94, // 5
3435663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x13, 0x5c, 0xd2, 0xf1, 0x40, 0x46, 0x83, 0x38,
3436663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x66, 0xdd, 0xfd, 0x30, 0xbf, 0x06, 0x8b, 0x62, // 6
3437663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xb3, 0x25, 0xe2, 0x98, 0x22, 0x88, 0x91, 0x10,
3438663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x7e, 0x6e, 0x48, 0xc3, 0xa3, 0xb6, 0x1e, 0x42, // 7
3439663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x3a, 0x6b, 0x28, 0x54, 0xfa, 0x85, 0x3d, 0xba,
3440663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x2b, 0x79, 0x0a, 0x15, 0x9b, 0x9f, 0x5e, 0xca, // 8
3441663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x4e, 0xd4, 0xac, 0xe5, 0xf3, 0x73, 0xa7, 0x57,
3442663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xaf, 0x58, 0xa8, 0x50, 0xf4, 0xea, 0xd6, 0x74, // 9
3443663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x4f, 0xae, 0xe9, 0xd5, 0xe7, 0xe6, 0xad, 0xe8,
3444663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x2c, 0xd7, 0x75, 0x7a, 0xeb, 0x16, 0x0b, 0xf5, //10
3445663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x59, 0xcb, 0x5f, 0xb0, 0x9c, 0xa9, 0x51, 0xa0,
3446663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x7f, 0x0c, 0xf6, 0x6f, 0x17, 0xc4, 0x49, 0xec, //11
3447663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xd8, 0x43, 0x1f, 0x2d, 0xa4, 0x76, 0x7b, 0xb7,
3448663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xcc, 0xbb, 0x3e, 0x5a, 0xfb, 0x60, 0xb1, 0x86, //12
3449663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x3b, 0x52, 0xa1, 0x6c, 0xaa, 0x55, 0x29, 0x9d,
3450663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x97, 0xb2, 0x87, 0x90, 0x61, 0xbe, 0xdc, 0xfc, //13
3451663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xbc, 0x95, 0xcf, 0xcd, 0x37, 0x3f, 0x5b, 0xd1,
3452663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x53, 0x39, 0x84, 0x3c, 0x41, 0xa2, 0x6d, 0x47, //14
3453663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x14, 0x2a, 0x9e, 0x5d, 0x56, 0xf2, 0xd3, 0xab,
3454663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x44, 0x11, 0x92, 0xd9, 0x23, 0x20, 0x2e, 0x89, //15
3455663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xb4, 0x7c, 0xb8, 0x26, 0x77, 0x99, 0xe3, 0xa5,
3456663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x67, 0x4a, 0xed, 0xde, 0xc5, 0x31, 0xfe, 0x18, //16
3457663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x0d, 0x63, 0x8c, 0x80, 0xc0, 0xf7, 0x70, 0x07
3458663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng};
3459663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3460663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* E values so that E = 0x03^xy. */
3461663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic const UChar Exy[256] = {                    // row nr
3462663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x01, 0x03, 0x05, 0x0f, 0x11, 0x33, 0x55, 0xff, // 1
3463663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x1a, 0x2e, 0x72, 0x96, 0xa1, 0xf8, 0x13, 0x35,
3464663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x5f, 0xe1, 0x38, 0x48, 0xd8, 0x73, 0x95, 0xa4, // 2
3465663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xf7, 0x02, 0x06, 0x0a, 0x1e, 0x22, 0x66, 0xaa,
3466663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xe5, 0x34, 0x5c, 0xe4, 0x37, 0x59, 0xeb, 0x26, // 3
3467663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x6a, 0xbe, 0xd9, 0x70, 0x90, 0xab, 0xe6, 0x31,
3468663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x53, 0xf5, 0x04, 0x0c, 0x14, 0x3c, 0x44, 0xcc, // 4
3469663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x4f, 0xd1, 0x68, 0xb8, 0xd3, 0x6e, 0xb2, 0xcd,
3470663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x4c, 0xd4, 0x67, 0xa9, 0xe0, 0x3b, 0x4d, 0xd7, // 5
3471663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x62, 0xa6, 0xf1, 0x08, 0x18, 0x28, 0x78, 0x88,
3472663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x83, 0x9e, 0xb9, 0xd0, 0x6b, 0xbd, 0xdc, 0x7f, // 6
3473663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x81, 0x98, 0xb3, 0xce, 0x49, 0xdb, 0x76, 0x9a,
3474663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xb5, 0xc4, 0x57, 0xf9, 0x10, 0x30, 0x50, 0xf0, // 7
3475663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x0b, 0x1d, 0x27, 0x69, 0xbb, 0xd6, 0x61, 0xa3,
3476663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xfe, 0x19, 0x2b, 0x7d, 0x87, 0x92, 0xad, 0xec, // 8
3477663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x2f, 0x71, 0x93, 0xae, 0xe9, 0x20, 0x60, 0xa0,
3478663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xfb, 0x16, 0x3a, 0x4e, 0xd2, 0x6d, 0xb7, 0xc2, // 9
3479663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x5d, 0xe7, 0x32, 0x56, 0xfa, 0x15, 0x3f, 0x41,
3480663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xc3, 0x5e, 0xe2, 0x3d, 0x47, 0xc9, 0x40, 0xc0, //10
3481663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x5b, 0xed, 0x2c, 0x74, 0x9c, 0xbf, 0xda, 0x75,
3482663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x9f, 0xba, 0xd5, 0x64, 0xac, 0xef, 0x2a, 0x7e, //11
3483663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x82, 0x9d, 0xbc, 0xdf, 0x7a, 0x8e, 0x89, 0x80,
3484663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x9b, 0xb6, 0xc1, 0x58, 0xe8, 0x23, 0x65, 0xaf, //12
3485663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xea, 0x25, 0x6f, 0xb1, 0xc8, 0x43, 0xc5, 0x54,
3486663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xfc, 0x1f, 0x21, 0x63, 0xa5, 0xf4, 0x07, 0x09, //13
3487663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x1b, 0x2d, 0x77, 0x99, 0xb0, 0xcb, 0x46, 0xca,
3488663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x45, 0xcf, 0x4a, 0xde, 0x79, 0x8b, 0x86, 0x91, //14
3489663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xa8, 0xe3, 0x3e, 0x42, 0xc6, 0x51, 0xf3, 0x0e,
3490663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x12, 0x36, 0x5a, 0xee, 0x29, 0x7b, 0x8d, 0x8c, //15
3491663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x8f, 0x8a, 0x85, 0x94, 0xa7, 0xf2, 0x0d, 0x17,
3492663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x39, 0x4b, 0xdd, 0x7c, 0x84, 0x97, 0xa2, 0xfd, //16
3493663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x1c, 0x24, 0x6c, 0xb4, 0xc7, 0x52, 0xf6, 0x01};
3494663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3495663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic inline UChar ff_mul(UChar u1, UChar u2)
3496663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
3497663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if ((u1 > 0) && (u2 > 0)) {
3498663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt ui = Nxy[u1] + Nxy[u2];
3499663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (ui >= 255)
3500663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         ui = ui - 255;
3501663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return Exy[ui];
3502663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
3503663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return 0;
3504663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   };
3505663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
3506663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3507663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void MixColumns (V128* v)
3508663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
3509663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   V128 r;
3510663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int j;
3511663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define P(x,row,col) (x)->w8[((row)*4+(col))]
3512663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   for (j = 0; j < 4; j++) {
3513663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      P(&r,j,0) = ff_mul(0x02, P(v,j,0)) ^ ff_mul(0x03, P(v,j,1))
3514663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         ^ P(v,j,2) ^ P(v,j,3);
3515663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      P(&r,j,1) = P(v,j,0) ^ ff_mul( 0x02, P(v,j,1) )
3516663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         ^ ff_mul(0x03, P(v,j,2) ) ^ P(v,j,3);
3517663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      P(&r,j,2) = P(v,j,0) ^ P(v,j,1) ^ ff_mul( 0x02, P(v,j,2) )
3518663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         ^ ff_mul(0x03, P(v,j,3) );
3519663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      P(&r,j,3) = ff_mul(0x03, P(v,j,0) ) ^ P(v,j,1) ^ P(v,j,2)
3520663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         ^ ff_mul( 0x02, P(v,j,3) );
3521663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
3522663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *v = r;
3523663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#undef P
3524663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
3525663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3526663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void InvMixColumns (V128* v)
3527663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
3528663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   V128 r;
3529663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int j;
3530663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define P(x,row,col) (x)->w8[((row)*4+(col))]
3531663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   for (j = 0; j < 4; j++) {
3532663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      P(&r,j,0) = ff_mul(0x0e, P(v,j,0) ) ^ ff_mul(0x0b, P(v,j,1) )
3533663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         ^ ff_mul(0x0d,P(v,j,2) ) ^ ff_mul(0x09, P(v,j,3) );
3534663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      P(&r,j,1) = ff_mul(0x09, P(v,j,0) ) ^ ff_mul(0x0e, P(v,j,1) )
3535663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         ^ ff_mul(0x0b,P(v,j,2) ) ^ ff_mul(0x0d, P(v,j,3) );
3536663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      P(&r,j,2) = ff_mul(0x0d, P(v,j,0) ) ^ ff_mul(0x09, P(v,j,1) )
3537663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         ^ ff_mul(0x0e,P(v,j,2) ) ^ ff_mul(0x0b, P(v,j,3) );
3538663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      P(&r,j,3) = ff_mul(0x0b, P(v,j,0) ) ^ ff_mul(0x0d, P(v,j,1) )
3539663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         ^ ff_mul(0x09,P(v,j,2) ) ^ ff_mul(0x0e, P(v,j,3) );
3540663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
3541663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *v = r;
3542663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#undef P
3543663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3544663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
3545663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3546663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* For description, see definition in guest_amd64_defs.h */
3547663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengvoid amd64g_dirtyhelper_AES (
3548663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          VexGuestAMD64State* gst,
3549663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          HWord opc4, HWord gstOffD,
3550663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          HWord gstOffL, HWord gstOffR
3551663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       )
3552663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
3553663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // where the args are
3554663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   V128* argD = (V128*)( ((UChar*)gst) + gstOffD );
3555663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   V128* argL = (V128*)( ((UChar*)gst) + gstOffL );
3556663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   V128* argR = (V128*)( ((UChar*)gst) + gstOffR );
3557663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   V128  r;
3558663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3559663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (opc4) {
3560663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0xDC: /* AESENC */
3561663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0xDD: /* AESENCLAST */
3562663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         r = *argR;
3563663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         ShiftRows (&r);
3564663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         SubBytes  (&r);
3565663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (opc4 == 0xDC)
3566663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            MixColumns (&r);
3567663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         argD->w64[0] = r.w64[0] ^ argL->w64[0];
3568663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         argD->w64[1] = r.w64[1] ^ argL->w64[1];
3569663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
3570663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3571663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0xDE: /* AESDEC */
3572663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0xDF: /* AESDECLAST */
3573663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         r = *argR;
3574663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         InvShiftRows (&r);
3575663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         InvSubBytes (&r);
3576663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (opc4 == 0xDE)
3577663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            InvMixColumns (&r);
3578663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         argD->w64[0] = r.w64[0] ^ argL->w64[0];
3579663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         argD->w64[1] = r.w64[1] ^ argL->w64[1];
3580663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
3581663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3582663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0xDB: /* AESIMC */
3583663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *argD = *argL;
3584663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         InvMixColumns (argD);
3585663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
3586663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default: vassert(0);
3587663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
3588663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
3589663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3590663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic inline UInt RotWord (UInt   w32)
3591663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
3592663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return ((w32 >> 8) | (w32 << 24));
3593663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
3594663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3595663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic inline UInt SubWord (UInt   w32)
3596663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
3597663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar *w8;
3598663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar *r8;
3599663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt res;
3600663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   w8 = (UChar*) &w32;
3601663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   r8 = (UChar*) &res;
3602663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   r8[0] = sbox[w8[0]];
3603663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   r8[1] = sbox[w8[1]];
3604663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   r8[2] = sbox[w8[2]];
3605663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   r8[3] = sbox[w8[3]];
3606663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return res;
3607663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
3608663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3609663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* For description, see definition in guest_amd64_defs.h */
3610663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengextern void amd64g_dirtyhelper_AESKEYGENASSIST (
3611663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          VexGuestAMD64State* gst,
3612663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          HWord imm8,
3613663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          HWord gstOffL, HWord gstOffR
3614663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       )
3615663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
3616663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // where the args are
3617663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   V128* argL = (V128*)( ((UChar*)gst) + gstOffL );
3618663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   V128* argR = (V128*)( ((UChar*)gst) + gstOffR );
3619663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3620663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   argR->w32[3] = RotWord (SubWord (argL->w32[3])) ^ imm8;
3621663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   argR->w32[2] = SubWord (argL->w32[3]);
3622663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   argR->w32[1] = RotWord (SubWord (argL->w32[1])) ^ imm8;
3623663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   argR->w32[0] = SubWord (argL->w32[1]);
3624663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
3625663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3626663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
3629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Helpers for dealing with, and describing,               ---*/
3630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- guest state as a whole.                                 ---*/
3631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
3632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Initialise the entire amd64 guest state. */
3634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* VISIBLE TO LIBVEX CLIENT */
3635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid LibVEX_GuestAMD64_initialise ( /*OUT*/VexGuestAMD64State* vex_state )
3636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3637663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vex_state->host_EvC_FAILADDR = 0;
3638663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vex_state->host_EvC_COUNTER = 0;
3639663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vex_state->pad0 = 0;
3640663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_state->guest_RAX = 0;
3642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_state->guest_RCX = 0;
3643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_state->guest_RDX = 0;
3644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_state->guest_RBX = 0;
3645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_state->guest_RSP = 0;
3646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_state->guest_RBP = 0;
3647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_state->guest_RSI = 0;
3648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_state->guest_RDI = 0;
3649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_state->guest_R8  = 0;
3650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_state->guest_R9  = 0;
3651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_state->guest_R10 = 0;
3652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_state->guest_R11 = 0;
3653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_state->guest_R12 = 0;
3654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_state->guest_R13 = 0;
3655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_state->guest_R14 = 0;
3656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_state->guest_R15 = 0;
3657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_state->guest_CC_OP   = AMD64G_CC_OP_COPY;
3659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_state->guest_CC_DEP1 = 0;
3660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_state->guest_CC_DEP2 = 0;
3661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_state->guest_CC_NDEP = 0;
3662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_state->guest_DFLAG   = 1; /* forwards */
3664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_state->guest_IDFLAG  = 0;
3665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* HACK: represent the offset associated with %fs==0. This
3667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assumes that %fs is only ever zero. */
3668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_state->guest_FS_ZERO = 0;
3669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_state->guest_RIP = 0;
3671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Initialise the simulated FPU */
3673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   amd64g_dirtyhelper_FINIT( vex_state );
3674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3675663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Initialise the AVX state. */
3676663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  define AVXZERO(_ymm) \
3677663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      do { _ymm[0]=_ymm[1]=_ymm[2]=_ymm[3] = 0; \
3678663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           _ymm[4]=_ymm[5]=_ymm[6]=_ymm[7] = 0; \
3679663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      } while (0)
3680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_state->guest_SSEROUND = (ULong)Irrm_NEAREST;
3681663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   AVXZERO(vex_state->guest_YMM0);
3682663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   AVXZERO(vex_state->guest_YMM1);
3683663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   AVXZERO(vex_state->guest_YMM2);
3684663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   AVXZERO(vex_state->guest_YMM3);
3685663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   AVXZERO(vex_state->guest_YMM4);
3686663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   AVXZERO(vex_state->guest_YMM5);
3687663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   AVXZERO(vex_state->guest_YMM6);
3688663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   AVXZERO(vex_state->guest_YMM7);
3689663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   AVXZERO(vex_state->guest_YMM8);
3690663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   AVXZERO(vex_state->guest_YMM9);
3691663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   AVXZERO(vex_state->guest_YMM10);
3692663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   AVXZERO(vex_state->guest_YMM11);
3693663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   AVXZERO(vex_state->guest_YMM12);
3694663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   AVXZERO(vex_state->guest_YMM13);
3695663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   AVXZERO(vex_state->guest_YMM14);
3696663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   AVXZERO(vex_state->guest_YMM15);
3697663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   AVXZERO(vex_state->guest_YMM16);
3698663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3699663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  undef AVXZERO
3700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_state->guest_EMWARN = EmWarn_NONE;
3702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* These should not ever be either read or written, but we
3704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      initialise them anyway. */
3705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_state->guest_TISTART = 0;
3706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_state->guest_TILEN   = 0;
3707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_state->guest_NRADDR   = 0;
3709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_state->guest_SC_CLASS = 0;
3710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_state->guest_GS_0x60  = 0;
3711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_state->guest_IP_AT_SYSCALL = 0;
3713663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vex_state->pad1 = 0;
3714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Figure out if any part of the guest state contained in minoff
3718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   .. maxoff requires precise memory exceptions.  If in doubt return
3719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   True (but this is generates significantly slower code).
3720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   By default we enforce precise exns for guest %RSP, %RBP and %RIP
3722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   only.  These are the minimum needed to extract correct stack
3723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   backtraces from amd64 code.
3724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
3725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool guest_amd64_state_requires_precise_mem_exns ( Int minoff,
3726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                   Int maxoff)
3727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int rbp_min = offsetof(VexGuestAMD64State, guest_RBP);
3729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int rbp_max = rbp_min + 8 - 1;
3730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int rsp_min = offsetof(VexGuestAMD64State, guest_RSP);
3731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int rsp_max = rsp_min + 8 - 1;
3732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int rip_min = offsetof(VexGuestAMD64State, guest_RIP);
3733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int rip_max = rip_min + 8 - 1;
3734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (maxoff < rbp_min || minoff > rbp_max) {
3736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* no overlap with rbp */
3737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
3738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
3739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (maxoff < rsp_min || minoff > rsp_max) {
3742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* no overlap with rsp */
3743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
3744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
3745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (maxoff < rip_min || minoff > rip_max) {
3748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* no overlap with eip */
3749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
3750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
3751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return False;
3754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ALWAYSDEFD(field)                             \
3758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    { offsetof(VexGuestAMD64State, field),            \
3759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (sizeof ((VexGuestAMD64State*)0)->field) }
3760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownVexGuestLayout
3762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   amd64guest_layout
3763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = {
3764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          /* Total size of the guest state, in bytes. */
3765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          .total_sizeB = sizeof(VexGuestAMD64State),
3766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          /* Describe the stack pointer. */
3768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          .offset_SP = offsetof(VexGuestAMD64State,guest_RSP),
3769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          .sizeof_SP = 8,
3770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          /* Describe the frame pointer. */
3772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          .offset_FP = offsetof(VexGuestAMD64State,guest_RBP),
3773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          .sizeof_FP = 8,
3774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          /* Describe the instruction pointer. */
3776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          .offset_IP = offsetof(VexGuestAMD64State,guest_RIP),
3777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          .sizeof_IP = 8,
3778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          /* Describe any sections to be regarded by Memcheck as
3780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             'always-defined'. */
3781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          .n_alwaysDefd = 16,
3782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          /* flags thunk: OP and NDEP are always defd, whereas DEP1
3784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             and DEP2 have to be tracked.  See detailed comment in
3785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             gdefs.h on meaning of thunk fields. */
3786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          .alwaysDefd
3787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             = { /*  0 */ ALWAYSDEFD(guest_CC_OP),
3788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 /*  1 */ ALWAYSDEFD(guest_CC_NDEP),
3789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		 /*  2 */ ALWAYSDEFD(guest_DFLAG),
3790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 /*  3 */ ALWAYSDEFD(guest_IDFLAG),
3791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 /*  4 */ ALWAYSDEFD(guest_RIP),
3792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 /*  5 */ ALWAYSDEFD(guest_FS_ZERO),
3793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 /*  6 */ ALWAYSDEFD(guest_FTOP),
3794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 /*  7 */ ALWAYSDEFD(guest_FPTAG),
3795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 /*  8 */ ALWAYSDEFD(guest_FPROUND),
3796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 /*  9 */ ALWAYSDEFD(guest_FC3210),
3797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 // /* */ ALWAYSDEFD(guest_CS),
3798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 // /* */ ALWAYSDEFD(guest_DS),
3799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 // /* */ ALWAYSDEFD(guest_ES),
3800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 // /* */ ALWAYSDEFD(guest_FS),
3801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 // /* */ ALWAYSDEFD(guest_GS),
3802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 // /* */ ALWAYSDEFD(guest_SS),
3803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 // /* */ ALWAYSDEFD(guest_LDT),
3804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 // /* */ ALWAYSDEFD(guest_GDT),
3805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 /* 10 */ ALWAYSDEFD(guest_EMWARN),
3806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 /* 11 */ ALWAYSDEFD(guest_SSEROUND),
3807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 /* 12 */ ALWAYSDEFD(guest_TISTART),
3808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 /* 13 */ ALWAYSDEFD(guest_TILEN),
3809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 /* 14 */ ALWAYSDEFD(guest_SC_CLASS),
3810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 /* 15 */ ALWAYSDEFD(guest_IP_AT_SYSCALL)
3811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
3812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        };
3813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
3816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end                               guest_amd64_helpers.c ---*/
3817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
3818