19c6acb0c7f7b5ff5c4a8d5a22259d8151edff499njn
29c6acb0c7f7b5ff5c4a8d5a22259d8151edff499njn/*---------------------------------------------------------------*/
3752f90673ebbb6b2f55fc5e46606dea371313713sewardj/*--- begin                             guest_amd64_helpers.c ---*/
49c6acb0c7f7b5ff5c4a8d5a22259d8151edff499njn/*---------------------------------------------------------------*/
59c6acb0c7f7b5ff5c4a8d5a22259d8151edff499njn
69c6acb0c7f7b5ff5c4a8d5a22259d8151edff499njn/*
7752f90673ebbb6b2f55fc5e46606dea371313713sewardj   This file is part of Valgrind, a dynamic binary instrumentation
8752f90673ebbb6b2f55fc5e46606dea371313713sewardj   framework.
99c6acb0c7f7b5ff5c4a8d5a22259d8151edff499njn
10ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes   Copyright (C) 2004-2017 OpenWorks LLP
11752f90673ebbb6b2f55fc5e46606dea371313713sewardj      info@open-works.net
129c6acb0c7f7b5ff5c4a8d5a22259d8151edff499njn
13752f90673ebbb6b2f55fc5e46606dea371313713sewardj   This program is free software; you can redistribute it and/or
14752f90673ebbb6b2f55fc5e46606dea371313713sewardj   modify it under the terms of the GNU General Public License as
15752f90673ebbb6b2f55fc5e46606dea371313713sewardj   published by the Free Software Foundation; either version 2 of the
16752f90673ebbb6b2f55fc5e46606dea371313713sewardj   License, or (at your option) any later version.
179c6acb0c7f7b5ff5c4a8d5a22259d8151edff499njn
18752f90673ebbb6b2f55fc5e46606dea371313713sewardj   This program is distributed in the hope that it will be useful, but
19752f90673ebbb6b2f55fc5e46606dea371313713sewardj   WITHOUT ANY WARRANTY; without even the implied warranty of
20752f90673ebbb6b2f55fc5e46606dea371313713sewardj   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21752f90673ebbb6b2f55fc5e46606dea371313713sewardj   General Public License for more details.
22752f90673ebbb6b2f55fc5e46606dea371313713sewardj
23752f90673ebbb6b2f55fc5e46606dea371313713sewardj   You should have received a copy of the GNU General Public License
24752f90673ebbb6b2f55fc5e46606dea371313713sewardj   along with this program; if not, write to the Free Software
25752f90673ebbb6b2f55fc5e46606dea371313713sewardj   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
267bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj   02110-1301, USA.
277bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj
28752f90673ebbb6b2f55fc5e46606dea371313713sewardj   The GNU General Public License is contained in the file COPYING.
299c6acb0c7f7b5ff5c4a8d5a22259d8151edff499njn
309c6acb0c7f7b5ff5c4a8d5a22259d8151edff499njn   Neither the names of the U.S. Department of Energy nor the
319c6acb0c7f7b5ff5c4a8d5a22259d8151edff499njn   University of California nor the names of its contributors may be
329c6acb0c7f7b5ff5c4a8d5a22259d8151edff499njn   used to endorse or promote products derived from this software
339c6acb0c7f7b5ff5c4a8d5a22259d8151edff499njn   without prior written permission.
349c6acb0c7f7b5ff5c4a8d5a22259d8151edff499njn*/
359c6acb0c7f7b5ff5c4a8d5a22259d8151edff499njn
369c6acb0c7f7b5ff5c4a8d5a22259d8151edff499njn#include "libvex_basictypes.h"
3733b024301d2311965cc68dc4cc900f3d0fdd8085florian#include "libvex_emnote.h"
389c6acb0c7f7b5ff5c4a8d5a22259d8151edff499njn#include "libvex_guest_amd64.h"
399c6acb0c7f7b5ff5c4a8d5a22259d8151edff499njn#include "libvex_ir.h"
409c6acb0c7f7b5ff5c4a8d5a22259d8151edff499njn#include "libvex.h"
419c6acb0c7f7b5ff5c4a8d5a22259d8151edff499njn
42cef7d3e3df4796e35b4521158d9dc058f034aa87sewardj#include "main_util.h"
436c46befd9eb90c1b6e739926c1fa335cba75bf46philippe#include "main_globals.h"
44cef7d3e3df4796e35b4521158d9dc058f034aa87sewardj#include "guest_generic_bb_to_IR.h"
45cef7d3e3df4796e35b4521158d9dc058f034aa87sewardj#include "guest_amd64_defs.h"
46cef7d3e3df4796e35b4521158d9dc058f034aa87sewardj#include "guest_generic_x87.h"
4744d494dfad0c12f96f61cf9edfc889dfa69e3b30sewardj
48f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
49f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj/* This file contains helper functions for amd64 guest code.
50f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   Calls to these functions are generated by the back end.
51f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   These calls are of course in the host machine code and
52f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   this file will be compiled to host machine code, so that
53f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   all makes sense.
54f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
55f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   Only change the signatures of these helper functions very
56f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   carefully.  If you change the signature here, you'll have to change
57f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   the parameters passed to it in the IR calls constructed by
58f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   guest-amd64/toIR.c.
59f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
60f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   The convention used is that all functions called from generated
61f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   code are named amd64g_<something>, and any function whose name lacks
62f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   that prefix is not called from generated code.  Note that some
63f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   LibVEX_* functions can however be called by VEX's client, but that
64f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   is not the same as calling them from VEX-generated code.
65f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj*/
66f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
67f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
68f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj/* Set to 1 to get detailed profiling info about use of the flag
69f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   machinery. */
70f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj#define PROFILE_RFLAGS 0
71f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
72f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
73f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj/*---------------------------------------------------------------*/
74f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj/*--- %rflags run-time helpers.                               ---*/
75f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj/*---------------------------------------------------------------*/
76f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
771a01e65f9993d97095c2af463e98674a091834casewardj/* Do 64x64 -> 128 signed/unsigned multiplies, for computing flags
781a01e65f9993d97095c2af463e98674a091834casewardj   after imulq/mulq. */
791a01e65f9993d97095c2af463e98674a091834casewardj
801a01e65f9993d97095c2af463e98674a091834casewardjstatic void mullS64 ( Long u, Long v, Long* rHi, Long* rLo )
811a01e65f9993d97095c2af463e98674a091834casewardj{
82095b4cbfbf9c7c88a66da949cc4cfc8888caae8dsewardj   const Long halfMask = 0xFFFFFFFFLL;
831a01e65f9993d97095c2af463e98674a091834casewardj   ULong u0, v0, w0;
841a01e65f9993d97095c2af463e98674a091834casewardj    Long u1, v1, w1, w2, t;
85095b4cbfbf9c7c88a66da949cc4cfc8888caae8dsewardj   u0   = u & halfMask;
861a01e65f9993d97095c2af463e98674a091834casewardj   u1   = u >> 32;
87095b4cbfbf9c7c88a66da949cc4cfc8888caae8dsewardj   v0   = v & halfMask;
881a01e65f9993d97095c2af463e98674a091834casewardj   v1   = v >> 32;
891a01e65f9993d97095c2af463e98674a091834casewardj   w0   = u0 * v0;
901a01e65f9993d97095c2af463e98674a091834casewardj   t    = u1 * v0 + (w0 >> 32);
91095b4cbfbf9c7c88a66da949cc4cfc8888caae8dsewardj   w1   = t & halfMask;
921a01e65f9993d97095c2af463e98674a091834casewardj   w2   = t >> 32;
931a01e65f9993d97095c2af463e98674a091834casewardj   w1   = u0 * v1 + w1;
941a01e65f9993d97095c2af463e98674a091834casewardj   *rHi = u1 * v1 + w2 + (w1 >> 32);
95095b4cbfbf9c7c88a66da949cc4cfc8888caae8dsewardj   *rLo = (Long)((ULong)u * (ULong)v);
961a01e65f9993d97095c2af463e98674a091834casewardj}
971a01e65f9993d97095c2af463e98674a091834casewardj
981a01e65f9993d97095c2af463e98674a091834casewardjstatic void mullU64 ( ULong u, ULong v, ULong* rHi, ULong* rLo )
991a01e65f9993d97095c2af463e98674a091834casewardj{
100095b4cbfbf9c7c88a66da949cc4cfc8888caae8dsewardj   const ULong halfMask = 0xFFFFFFFFULL;
1011a01e65f9993d97095c2af463e98674a091834casewardj   ULong u0, v0, w0;
1021a01e65f9993d97095c2af463e98674a091834casewardj   ULong u1, v1, w1,w2,t;
103095b4cbfbf9c7c88a66da949cc4cfc8888caae8dsewardj   u0   = u & halfMask;
1041a01e65f9993d97095c2af463e98674a091834casewardj   u1   = u >> 32;
105095b4cbfbf9c7c88a66da949cc4cfc8888caae8dsewardj   v0   = v & halfMask;
1061a01e65f9993d97095c2af463e98674a091834casewardj   v1   = v >> 32;
1071a01e65f9993d97095c2af463e98674a091834casewardj   w0   = u0 * v0;
1081a01e65f9993d97095c2af463e98674a091834casewardj   t    = u1 * v0 + (w0 >> 32);
109095b4cbfbf9c7c88a66da949cc4cfc8888caae8dsewardj   w1   = t & halfMask;
1101a01e65f9993d97095c2af463e98674a091834casewardj   w2   = t >> 32;
1111a01e65f9993d97095c2af463e98674a091834casewardj   w1   = u0 * v1 + w1;
1121a01e65f9993d97095c2af463e98674a091834casewardj   *rHi = u1 * v1 + w2 + (w1 >> 32);
1131a01e65f9993d97095c2af463e98674a091834casewardj   *rLo = u * v;
1141a01e65f9993d97095c2af463e98674a091834casewardj}
1151a01e65f9993d97095c2af463e98674a091834casewardj
1161a01e65f9993d97095c2af463e98674a091834casewardj
117f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardjstatic const UChar parity_table[256] = {
118f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
119f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
120f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
121f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
122f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
123f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
124f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
125f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
126f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
127f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
128f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
129f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
130f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
131f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
132f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
133f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
134f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
135f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
136f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
137f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
138f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
139f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
140f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
141f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
142f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
143f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
144f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
145f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
146f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
147f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
148f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
149f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
150f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj};
151f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
1524a6f3844a29aebc9774ab0d71418421c14ba9c41sewardj/* generalised left-shifter */
1531fa7b8031dea649db2f3b99b407d5a9a036dacdasewardjstatic inline Long lshift ( Long x, Int n )
154f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj{
155f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   if (n >= 0)
156108e03fcb0a4ef42164235b1988aa540aa1e5298florian      return (ULong)x << n;
157f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   else
158f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      return x >> (-n);
159f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj}
160f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
1611fa7b8031dea649db2f3b99b407d5a9a036dacdasewardj/* identity on ULong */
1621fa7b8031dea649db2f3b99b407d5a9a036dacdasewardjstatic inline ULong idULong ( ULong x )
1631fa7b8031dea649db2f3b99b407d5a9a036dacdasewardj{
1641fa7b8031dea649db2f3b99b407d5a9a036dacdasewardj   return x;
1651fa7b8031dea649db2f3b99b407d5a9a036dacdasewardj}
1661fa7b8031dea649db2f3b99b407d5a9a036dacdasewardj
167f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
168f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj#define PREAMBLE(__data_bits)					\
169f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   /* const */ ULong DATA_MASK 					\
170f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      = __data_bits==8                                          \
171f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj           ? 0xFFULL 					        \
172f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj           : (__data_bits==16                                   \
173f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj                ? 0xFFFFULL 		                        \
174f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj                : (__data_bits==32                              \
175f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj                     ? 0xFFFFFFFFULL                            \
176f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj                     : 0xFFFFFFFFFFFFFFFFULL));                 \
177f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   /* const */ ULong SIGN_MASK = 1ULL << (__data_bits - 1);     \
178f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   /* const */ ULong CC_DEP1 = cc_dep1_formal;			\
179f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   /* const */ ULong CC_DEP2 = cc_dep2_formal;			\
180f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   /* const */ ULong CC_NDEP = cc_ndep_formal;			\
181f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   /* Four bogus assignments, which hopefully gcc can     */	\
182f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   /* optimise away, and which stop it complaining about  */	\
183f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   /* unused variables.                                   */	\
184f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   SIGN_MASK = SIGN_MASK;					\
185f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   DATA_MASK = DATA_MASK;					\
186f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   CC_DEP2 = CC_DEP2;						\
187f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   CC_NDEP = CC_NDEP;
188f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
189f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
190f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj/*-------------------------------------------------------------*/
191f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
192f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj#define ACTIONS_ADD(DATA_BITS,DATA_UTYPE)			\
193f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj{								\
194f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   PREAMBLE(DATA_BITS);						\
195108e03fcb0a4ef42164235b1988aa540aa1e5298florian   { ULong cf, pf, af, zf, sf, of;				\
196108e03fcb0a4ef42164235b1988aa540aa1e5298florian     ULong argL, argR, res;					\
197f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     argL = CC_DEP1;						\
198f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     argR = CC_DEP2;						\
199f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     res  = argL + argR;					\
200f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     cf = (DATA_UTYPE)res < (DATA_UTYPE)argL;			\
201f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     pf = parity_table[(UChar)res];				\
202f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     af = (res ^ argL ^ argR) & 0x10;				\
203f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     zf = ((DATA_UTYPE)res == 0) << 6;				\
204f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     sf = lshift(res, 8 - DATA_BITS) & 0x80;			\
205f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     of = lshift((argL ^ argR ^ -1) & (argL ^ res), 		\
206f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj                 12 - DATA_BITS) & AMD64G_CC_MASK_O;		\
207f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     return cf | pf | af | zf | sf | of;			\
208f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   }								\
209f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj}
210f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
211f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj/*-------------------------------------------------------------*/
212f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
213f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj#define ACTIONS_SUB(DATA_BITS,DATA_UTYPE)			\
214f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj{								\
215f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   PREAMBLE(DATA_BITS);						\
216108e03fcb0a4ef42164235b1988aa540aa1e5298florian   { ULong cf, pf, af, zf, sf, of;				\
217108e03fcb0a4ef42164235b1988aa540aa1e5298florian     ULong argL, argR, res;					\
218f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     argL = CC_DEP1;						\
219f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     argR = CC_DEP2;						\
220f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     res  = argL - argR;					\
221f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     cf = (DATA_UTYPE)argL < (DATA_UTYPE)argR;			\
222f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     pf = parity_table[(UChar)res];				\
223f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     af = (res ^ argL ^ argR) & 0x10;				\
224f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     zf = ((DATA_UTYPE)res == 0) << 6;				\
225f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     sf = lshift(res, 8 - DATA_BITS) & 0x80;			\
226f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     of = lshift((argL ^ argR) & (argL ^ res),	 		\
227f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj                 12 - DATA_BITS) & AMD64G_CC_MASK_O; 		\
228f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     return cf | pf | af | zf | sf | of;			\
229f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   }								\
230f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj}
231f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
232f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj/*-------------------------------------------------------------*/
233f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
234f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj#define ACTIONS_ADC(DATA_BITS,DATA_UTYPE)			\
235f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj{								\
236f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   PREAMBLE(DATA_BITS);						\
237108e03fcb0a4ef42164235b1988aa540aa1e5298florian   { ULong cf, pf, af, zf, sf, of;				\
238108e03fcb0a4ef42164235b1988aa540aa1e5298florian     ULong argL, argR, oldC, res;		 		\
239f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     oldC = CC_NDEP & AMD64G_CC_MASK_C;				\
240f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     argL = CC_DEP1;						\
241f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     argR = CC_DEP2 ^ oldC;	       				\
242f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     res  = (argL + argR) + oldC;				\
243f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     if (oldC)							\
244f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj        cf = (DATA_UTYPE)res <= (DATA_UTYPE)argL;		\
245f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     else							\
246f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj        cf = (DATA_UTYPE)res < (DATA_UTYPE)argL;		\
247f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     pf = parity_table[(UChar)res];				\
248f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     af = (res ^ argL ^ argR) & 0x10;				\
249f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     zf = ((DATA_UTYPE)res == 0) << 6;				\
250f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     sf = lshift(res, 8 - DATA_BITS) & 0x80;			\
251f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     of = lshift((argL ^ argR ^ -1) & (argL ^ res), 		\
252f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj                  12 - DATA_BITS) & AMD64G_CC_MASK_O;		\
253f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     return cf | pf | af | zf | sf | of;			\
254f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   }								\
255f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj}
256f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
257f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj/*-------------------------------------------------------------*/
258f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
259f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj#define ACTIONS_SBB(DATA_BITS,DATA_UTYPE)			\
260f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj{								\
261f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   PREAMBLE(DATA_BITS);						\
262108e03fcb0a4ef42164235b1988aa540aa1e5298florian   { ULong cf, pf, af, zf, sf, of;				\
263108e03fcb0a4ef42164235b1988aa540aa1e5298florian     ULong argL, argR, oldC, res;	       			\
264f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     oldC = CC_NDEP & AMD64G_CC_MASK_C;				\
265f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     argL = CC_DEP1;						\
266f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     argR = CC_DEP2 ^ oldC;	       				\
267f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     res  = (argL - argR) - oldC;				\
268f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     if (oldC)							\
269f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj        cf = (DATA_UTYPE)argL <= (DATA_UTYPE)argR;		\
270f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     else							\
271f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj        cf = (DATA_UTYPE)argL < (DATA_UTYPE)argR;		\
272f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     pf = parity_table[(UChar)res];				\
273f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     af = (res ^ argL ^ argR) & 0x10;				\
274f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     zf = ((DATA_UTYPE)res == 0) << 6;				\
275f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     sf = lshift(res, 8 - DATA_BITS) & 0x80;			\
276f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     of = lshift((argL ^ argR) & (argL ^ res), 			\
277f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj                 12 - DATA_BITS) & AMD64G_CC_MASK_O;		\
278f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     return cf | pf | af | zf | sf | of;			\
279f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   }								\
280f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj}
281f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
282f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj/*-------------------------------------------------------------*/
283f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
284f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj#define ACTIONS_LOGIC(DATA_BITS,DATA_UTYPE)			\
285f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj{								\
286f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   PREAMBLE(DATA_BITS);						\
287108e03fcb0a4ef42164235b1988aa540aa1e5298florian   { ULong cf, pf, af, zf, sf, of;				\
288f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     cf = 0;							\
289f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     pf = parity_table[(UChar)CC_DEP1];				\
290f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     af = 0;							\
291f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     zf = ((DATA_UTYPE)CC_DEP1 == 0) << 6;			\
292f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     sf = lshift(CC_DEP1, 8 - DATA_BITS) & 0x80;		\
293f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     of = 0;							\
294f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     return cf | pf | af | zf | sf | of;			\
295f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   }								\
296f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj}
297f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
298f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj/*-------------------------------------------------------------*/
299f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
300f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj#define ACTIONS_INC(DATA_BITS,DATA_UTYPE)			\
301f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj{								\
302f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   PREAMBLE(DATA_BITS);						\
303108e03fcb0a4ef42164235b1988aa540aa1e5298florian   { ULong cf, pf, af, zf, sf, of;				\
304108e03fcb0a4ef42164235b1988aa540aa1e5298florian     ULong argL, argR, res;					\
305f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     res  = CC_DEP1;						\
306f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     argL = res - 1;						\
307f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     argR = 1;							\
308f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     cf = CC_NDEP & AMD64G_CC_MASK_C;				\
309f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     pf = parity_table[(UChar)res];				\
310f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     af = (res ^ argL ^ argR) & 0x10;				\
311f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     zf = ((DATA_UTYPE)res == 0) << 6;				\
312f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     sf = lshift(res, 8 - DATA_BITS) & 0x80;			\
313f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     of = ((res & DATA_MASK) == SIGN_MASK) << 11;		\
314f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     return cf | pf | af | zf | sf | of;			\
315f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   }								\
316f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj}
317f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
318f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj/*-------------------------------------------------------------*/
319f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
320f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj#define ACTIONS_DEC(DATA_BITS,DATA_UTYPE)			\
321f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj{								\
322f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   PREAMBLE(DATA_BITS);						\
323108e03fcb0a4ef42164235b1988aa540aa1e5298florian   { ULong cf, pf, af, zf, sf, of;				\
324108e03fcb0a4ef42164235b1988aa540aa1e5298florian     ULong argL, argR, res;					\
325f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     res  = CC_DEP1;						\
326f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     argL = res + 1;						\
327f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     argR = 1;							\
328f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     cf = CC_NDEP & AMD64G_CC_MASK_C;				\
329f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     pf = parity_table[(UChar)res];				\
330f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     af = (res ^ argL ^ argR) & 0x10;				\
331f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     zf = ((DATA_UTYPE)res == 0) << 6;				\
332f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     sf = lshift(res, 8 - DATA_BITS) & 0x80;			\
333f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     of = ((res & DATA_MASK) 					\
334f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj          == ((ULong)SIGN_MASK - 1)) << 11;			\
335f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     return cf | pf | af | zf | sf | of;			\
336f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   }								\
337f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj}
338f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
339f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj/*-------------------------------------------------------------*/
340f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
341f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj#define ACTIONS_SHL(DATA_BITS,DATA_UTYPE)			\
342f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj{								\
343f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   PREAMBLE(DATA_BITS);						\
344108e03fcb0a4ef42164235b1988aa540aa1e5298florian   { ULong cf, pf, af, zf, sf, of;				\
345f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     cf = (CC_DEP2 >> (DATA_BITS - 1)) & AMD64G_CC_MASK_C;	\
346f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     pf = parity_table[(UChar)CC_DEP1];				\
347f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     af = 0; /* undefined */					\
348f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     zf = ((DATA_UTYPE)CC_DEP1 == 0) << 6;			\
349f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     sf = lshift(CC_DEP1, 8 - DATA_BITS) & 0x80;		\
350f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     /* of is defined if shift count == 1 */			\
351f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     of = lshift(CC_DEP2 ^ CC_DEP1, 12 - DATA_BITS) 		\
352f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj          & AMD64G_CC_MASK_O;					\
353f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     return cf | pf | af | zf | sf | of;			\
354f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   }								\
355f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj}
356f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
357f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj/*-------------------------------------------------------------*/
358f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
359f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj#define ACTIONS_SHR(DATA_BITS,DATA_UTYPE)			\
360f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj{								\
361f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   PREAMBLE(DATA_BITS);  					\
362108e03fcb0a4ef42164235b1988aa540aa1e5298florian   { ULong cf, pf, af, zf, sf, of;				\
363f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     cf = CC_DEP2 & 1;						\
364f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     pf = parity_table[(UChar)CC_DEP1];				\
365f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     af = 0; /* undefined */					\
366f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     zf = ((DATA_UTYPE)CC_DEP1 == 0) << 6;			\
367f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     sf = lshift(CC_DEP1, 8 - DATA_BITS) & 0x80;		\
368f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     /* of is defined if shift count == 1 */			\
369f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     of = lshift(CC_DEP2 ^ CC_DEP1, 12 - DATA_BITS)		\
370f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj          & AMD64G_CC_MASK_O;					\
371f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     return cf | pf | af | zf | sf | of;			\
372f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   }								\
373f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj}
374f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
375f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj/*-------------------------------------------------------------*/
376f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
377f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj/* ROL: cf' = lsb(result).  of' = msb(result) ^ lsb(result). */
378f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj/* DEP1 = result, NDEP = old flags */
379f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj#define ACTIONS_ROL(DATA_BITS,DATA_UTYPE)			\
380f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj{								\
381f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   PREAMBLE(DATA_BITS);						\
382108e03fcb0a4ef42164235b1988aa540aa1e5298florian   { ULong fl 							\
383f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj        = (CC_NDEP & ~(AMD64G_CC_MASK_O | AMD64G_CC_MASK_C))	\
3847de0d3c800437fbd82c59d57d156f4823d67609fsewardj          | (AMD64G_CC_MASK_C & CC_DEP1)			\
385f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj          | (AMD64G_CC_MASK_O & (lshift(CC_DEP1,  		\
386f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj                                      11-(DATA_BITS-1)) 	\
387f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj                     ^ lshift(CC_DEP1, 11)));			\
388f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     return fl;							\
389f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   }								\
390f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj}
391f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
392f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj/*-------------------------------------------------------------*/
393f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
394f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj/* ROR: cf' = msb(result).  of' = msb(result) ^ msb-1(result). */
395f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj/* DEP1 = result, NDEP = old flags */
396f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj#define ACTIONS_ROR(DATA_BITS,DATA_UTYPE)			\
397f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj{								\
398f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   PREAMBLE(DATA_BITS);						\
399108e03fcb0a4ef42164235b1988aa540aa1e5298florian   { ULong fl 							\
400f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj        = (CC_NDEP & ~(AMD64G_CC_MASK_O | AMD64G_CC_MASK_C))	\
401f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj          | (AMD64G_CC_MASK_C & (CC_DEP1 >> (DATA_BITS-1)))	\
402f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj          | (AMD64G_CC_MASK_O & (lshift(CC_DEP1, 		\
403f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj                                      11-(DATA_BITS-1)) 	\
404f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj                     ^ lshift(CC_DEP1, 11-(DATA_BITS-1)+1)));	\
405f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     return fl;							\
406f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   }								\
407f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj}
408f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
409f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj/*-------------------------------------------------------------*/
410f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
4111fa7b8031dea649db2f3b99b407d5a9a036dacdasewardj#define ACTIONS_UMUL(DATA_BITS, DATA_UTYPE,  NARROWtoU,         \
4121fa7b8031dea649db2f3b99b407d5a9a036dacdasewardj                                DATA_U2TYPE, NARROWto2U)        \
413f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj{                                                               \
414f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   PREAMBLE(DATA_BITS);                                         \
415108e03fcb0a4ef42164235b1988aa540aa1e5298florian   { ULong cf, pf, af, zf, sf, of;                              \
416f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     DATA_UTYPE  hi;                                            \
4171fa7b8031dea649db2f3b99b407d5a9a036dacdasewardj     DATA_UTYPE  lo                                             \
4181fa7b8031dea649db2f3b99b407d5a9a036dacdasewardj        = NARROWtoU( ((DATA_UTYPE)CC_DEP1)                      \
4191fa7b8031dea649db2f3b99b407d5a9a036dacdasewardj                     * ((DATA_UTYPE)CC_DEP2) );                 \
4201fa7b8031dea649db2f3b99b407d5a9a036dacdasewardj     DATA_U2TYPE rr                                             \
4211fa7b8031dea649db2f3b99b407d5a9a036dacdasewardj        = NARROWto2U(                                           \
4221fa7b8031dea649db2f3b99b407d5a9a036dacdasewardj             ((DATA_U2TYPE)((DATA_UTYPE)CC_DEP1))               \
4231fa7b8031dea649db2f3b99b407d5a9a036dacdasewardj             * ((DATA_U2TYPE)((DATA_UTYPE)CC_DEP2)) );          \
4241fa7b8031dea649db2f3b99b407d5a9a036dacdasewardj     hi = NARROWtoU(rr >>/*u*/ DATA_BITS);                      \
425f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     cf = (hi != 0);                                            \
426f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     pf = parity_table[(UChar)lo];                              \
427f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     af = 0; /* undefined */                                    \
428f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     zf = (lo == 0) << 6;                                       \
429f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     sf = lshift(lo, 8 - DATA_BITS) & 0x80;                     \
430f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     of = cf << 11;                                             \
431f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     return cf | pf | af | zf | sf | of;                        \
432f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   }								\
433f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj}
434f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
435f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj/*-------------------------------------------------------------*/
436f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
4371fa7b8031dea649db2f3b99b407d5a9a036dacdasewardj#define ACTIONS_SMUL(DATA_BITS, DATA_STYPE,  NARROWtoS,         \
4381fa7b8031dea649db2f3b99b407d5a9a036dacdasewardj                                DATA_S2TYPE, NARROWto2S)        \
439f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj{                                                               \
440f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   PREAMBLE(DATA_BITS);                                         \
441108e03fcb0a4ef42164235b1988aa540aa1e5298florian   { ULong cf, pf, af, zf, sf, of;                              \
442f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     DATA_STYPE  hi;                                            \
4431fa7b8031dea649db2f3b99b407d5a9a036dacdasewardj     DATA_STYPE  lo                                             \
44445f8de626643cea67d0741f2b8a0b33dc69cbf84florian        = NARROWtoS( ((DATA_S2TYPE)(DATA_STYPE)CC_DEP1)         \
44545f8de626643cea67d0741f2b8a0b33dc69cbf84florian                     * ((DATA_S2TYPE)(DATA_STYPE)CC_DEP2) );    \
4461fa7b8031dea649db2f3b99b407d5a9a036dacdasewardj     DATA_S2TYPE rr                                             \
4471fa7b8031dea649db2f3b99b407d5a9a036dacdasewardj        = NARROWto2S(                                           \
4481fa7b8031dea649db2f3b99b407d5a9a036dacdasewardj             ((DATA_S2TYPE)((DATA_STYPE)CC_DEP1))               \
4491fa7b8031dea649db2f3b99b407d5a9a036dacdasewardj             * ((DATA_S2TYPE)((DATA_STYPE)CC_DEP2)) );          \
4501fa7b8031dea649db2f3b99b407d5a9a036dacdasewardj     hi = NARROWtoS(rr >>/*s*/ DATA_BITS);                      \
451f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     cf = (hi != (lo >>/*s*/ (DATA_BITS-1)));                   \
452f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     pf = parity_table[(UChar)lo];                              \
453f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     af = 0; /* undefined */                                    \
454f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     zf = (lo == 0) << 6;                                       \
455f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     sf = lshift(lo, 8 - DATA_BITS) & 0x80;                     \
456f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     of = cf << 11;                                             \
457f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj     return cf | pf | af | zf | sf | of;                        \
458f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   }								\
459f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj}
460f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
4611a01e65f9993d97095c2af463e98674a091834casewardj/*-------------------------------------------------------------*/
4621a01e65f9993d97095c2af463e98674a091834casewardj
4631a01e65f9993d97095c2af463e98674a091834casewardj#define ACTIONS_UMULQ                                           \
4641a01e65f9993d97095c2af463e98674a091834casewardj{                                                               \
4651a01e65f9993d97095c2af463e98674a091834casewardj   PREAMBLE(64);                                                \
466108e03fcb0a4ef42164235b1988aa540aa1e5298florian   { ULong cf, pf, af, zf, sf, of;                              \
4671a01e65f9993d97095c2af463e98674a091834casewardj     ULong lo, hi;                                              \
4681a01e65f9993d97095c2af463e98674a091834casewardj     mullU64( (ULong)CC_DEP1, (ULong)CC_DEP2, &hi, &lo );       \
4691a01e65f9993d97095c2af463e98674a091834casewardj     cf = (hi != 0);                                            \
4701a01e65f9993d97095c2af463e98674a091834casewardj     pf = parity_table[(UChar)lo];                              \
4711a01e65f9993d97095c2af463e98674a091834casewardj     af = 0; /* undefined */                                    \
4721a01e65f9993d97095c2af463e98674a091834casewardj     zf = (lo == 0) << 6;                                       \
4731a01e65f9993d97095c2af463e98674a091834casewardj     sf = lshift(lo, 8 - 64) & 0x80;                            \
4741a01e65f9993d97095c2af463e98674a091834casewardj     of = cf << 11;                                             \
4751a01e65f9993d97095c2af463e98674a091834casewardj     return cf | pf | af | zf | sf | of;                        \
4761a01e65f9993d97095c2af463e98674a091834casewardj   }								\
4771a01e65f9993d97095c2af463e98674a091834casewardj}
4781a01e65f9993d97095c2af463e98674a091834casewardj
4791a01e65f9993d97095c2af463e98674a091834casewardj/*-------------------------------------------------------------*/
4801a01e65f9993d97095c2af463e98674a091834casewardj
4811a01e65f9993d97095c2af463e98674a091834casewardj#define ACTIONS_SMULQ                                           \
4821a01e65f9993d97095c2af463e98674a091834casewardj{                                                               \
4831a01e65f9993d97095c2af463e98674a091834casewardj   PREAMBLE(64);                                                \
484108e03fcb0a4ef42164235b1988aa540aa1e5298florian   { ULong cf, pf, af, zf, sf, of;                              \
4851a01e65f9993d97095c2af463e98674a091834casewardj     Long lo, hi;                                               \
4861a01e65f9993d97095c2af463e98674a091834casewardj     mullS64( (Long)CC_DEP1, (Long)CC_DEP2, &hi, &lo );         \
4871a01e65f9993d97095c2af463e98674a091834casewardj     cf = (hi != (lo >>/*s*/ (64-1)));                          \
4881a01e65f9993d97095c2af463e98674a091834casewardj     pf = parity_table[(UChar)lo];                              \
4891a01e65f9993d97095c2af463e98674a091834casewardj     af = 0; /* undefined */                                    \
4901a01e65f9993d97095c2af463e98674a091834casewardj     zf = (lo == 0) << 6;                                       \
4911a01e65f9993d97095c2af463e98674a091834casewardj     sf = lshift(lo, 8 - 64) & 0x80;                            \
4921a01e65f9993d97095c2af463e98674a091834casewardj     of = cf << 11;                                             \
4931a01e65f9993d97095c2af463e98674a091834casewardj     return cf | pf | af | zf | sf | of;                        \
4941a01e65f9993d97095c2af463e98674a091834casewardj   }								\
4951a01e65f9993d97095c2af463e98674a091834casewardj}
4961a01e65f9993d97095c2af463e98674a091834casewardj
497cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj/*-------------------------------------------------------------*/
498cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj
499cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj#define ACTIONS_ANDN(DATA_BITS,DATA_UTYPE)			\
500cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj{								\
501cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj   PREAMBLE(DATA_BITS);						\
502108e03fcb0a4ef42164235b1988aa540aa1e5298florian   { ULong cf, pf, af, zf, sf, of;				\
503cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj     cf = 0;							\
504cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj     pf = 0;							\
505cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj     af = 0;							\
506cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj     zf = ((DATA_UTYPE)CC_DEP1 == 0) << 6;			\
507cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj     sf = lshift(CC_DEP1, 8 - DATA_BITS) & 0x80;		\
508cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj     of = 0;							\
509cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj     return cf | pf | af | zf | sf | of;			\
510cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj   }								\
511cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj}
512cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj
513cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj/*-------------------------------------------------------------*/
514cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj
515cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj#define ACTIONS_BLSI(DATA_BITS,DATA_UTYPE)			\
516cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj{								\
517cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj   PREAMBLE(DATA_BITS);						\
518108e03fcb0a4ef42164235b1988aa540aa1e5298florian   { ULong cf, pf, af, zf, sf, of;				\
519cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj     cf = ((DATA_UTYPE)CC_DEP2 != 0);				\
520cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj     pf = 0;							\
521cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj     af = 0;							\
522cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj     zf = ((DATA_UTYPE)CC_DEP1 == 0) << 6;			\
523cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj     sf = lshift(CC_DEP1, 8 - DATA_BITS) & 0x80;		\
524cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj     of = 0;							\
525cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj     return cf | pf | af | zf | sf | of;			\
526cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj   }								\
527cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj}
528cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj
529cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj/*-------------------------------------------------------------*/
530cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj
531cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj#define ACTIONS_BLSMSK(DATA_BITS,DATA_UTYPE)			\
532cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj{								\
533cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj   PREAMBLE(DATA_BITS);						\
534cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj   { Long cf, pf, af, zf, sf, of;				\
535cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj     cf = ((DATA_UTYPE)CC_DEP2 == 0);				\
536cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj     pf = 0;							\
537cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj     af = 0;							\
538cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj     zf = 0;							\
539cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj     sf = lshift(CC_DEP1, 8 - DATA_BITS) & 0x80;		\
540cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj     of = 0;							\
541cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj     return cf | pf | af | zf | sf | of;			\
542cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj   }								\
543cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj}
544cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj
545cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj/*-------------------------------------------------------------*/
546cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj
547cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj#define ACTIONS_BLSR(DATA_BITS,DATA_UTYPE)			\
548cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj{								\
549cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj   PREAMBLE(DATA_BITS);						\
550108e03fcb0a4ef42164235b1988aa540aa1e5298florian   { ULong cf, pf, af, zf, sf, of;				\
551cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj     cf = ((DATA_UTYPE)CC_DEP2 == 0);				\
552cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj     pf = 0;							\
553cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj     af = 0;							\
554cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj     zf = ((DATA_UTYPE)CC_DEP1 == 0) << 6;			\
555cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj     sf = lshift(CC_DEP1, 8 - DATA_BITS) & 0x80;		\
556cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj     of = 0;							\
557cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj     return cf | pf | af | zf | sf | of;			\
558cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj   }								\
559cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj}
560cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj
561cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj/*-------------------------------------------------------------*/
562cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj
563ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes#define ACTIONS_ADX(DATA_BITS,DATA_UTYPE,FLAGNAME)		\
564ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes{								\
565ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes   PREAMBLE(DATA_BITS);						\
566ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes   { ULong ocf;	/* o or c */					\
567ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes     ULong argL, argR, oldOC, res;				\
568ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes     oldOC = (CC_NDEP >> AMD64G_CC_SHIFT_##FLAGNAME) & 1;	\
569ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes     argL  = CC_DEP1;						\
570ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes     argR  = CC_DEP2 ^ oldOC;					\
571ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes     res   = (argL + argR) + oldOC;				\
572ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes     if (oldOC)							\
573ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes        ocf = (DATA_UTYPE)res <= (DATA_UTYPE)argL;		\
574ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes     else							\
575ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes        ocf = (DATA_UTYPE)res < (DATA_UTYPE)argL;		\
576ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes     return (CC_NDEP & ~AMD64G_CC_MASK_##FLAGNAME)		\
577ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes            | (ocf << AMD64G_CC_SHIFT_##FLAGNAME);		\
578ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes   }								\
579ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes}
580ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes
581ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes/*-------------------------------------------------------------*/
582ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes
583f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
5841fa7b8031dea649db2f3b99b407d5a9a036dacdasewardj#if PROFILE_RFLAGS
585f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
586f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardjstatic Bool initted     = False;
587f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
588f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj/* C flag, fast route */
589f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardjstatic UInt tabc_fast[AMD64G_CC_OP_NUMBER];
590f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj/* C flag, slow route */
591f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardjstatic UInt tabc_slow[AMD64G_CC_OP_NUMBER];
592f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj/* table for calculate_cond */
593f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardjstatic UInt tab_cond[AMD64G_CC_OP_NUMBER][16];
594f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj/* total entry counts for calc_all, calc_c, calc_cond. */
595f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardjstatic UInt n_calc_all  = 0;
596f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardjstatic UInt n_calc_c    = 0;
597f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardjstatic UInt n_calc_cond = 0;
598f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
599f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj#define SHOW_COUNTS_NOW (0 == (0x3FFFFF & (n_calc_all+n_calc_c+n_calc_cond)))
600f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
601f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
602f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardjstatic void showCounts ( void )
603f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj{
604f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   Int op, co;
6055df8ab0739ec95e8de9d9f43fa0e68b3e7125554florian   HChar ch;
6061fa7b8031dea649db2f3b99b407d5a9a036dacdasewardj   vex_printf("\nTotal calls: calc_all=%u   calc_cond=%u   calc_c=%u\n",
607f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj              n_calc_all, n_calc_cond, n_calc_c);
608f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
609f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   vex_printf("      cSLOW  cFAST    O   NO    B   NB    Z   NZ   BE  NBE"
610f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj              "    S   NS    P   NP    L   NL   LE  NLE\n");
611f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   vex_printf("     -----------------------------------------------------"
612f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj              "----------------------------------------\n");
613f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   for (op = 0; op < AMD64G_CC_OP_NUMBER; op++) {
614f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
615f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      ch = ' ';
6160354035b9222b1d6e37172ac2a70b19c816df025sewardj      if (op > 0 && (op-1) % 4 == 0)
617f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj         ch = 'B';
6180354035b9222b1d6e37172ac2a70b19c816df025sewardj      if (op > 0 && (op-1) % 4 == 1)
619f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj         ch = 'W';
6200354035b9222b1d6e37172ac2a70b19c816df025sewardj      if (op > 0 && (op-1) % 4 == 2)
621f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj         ch = 'L';
6220354035b9222b1d6e37172ac2a70b19c816df025sewardj      if (op > 0 && (op-1) % 4 == 3)
6230354035b9222b1d6e37172ac2a70b19c816df025sewardj         ch = 'Q';
624f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
625f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      vex_printf("%2d%c: ", op, ch);
6261fa7b8031dea649db2f3b99b407d5a9a036dacdasewardj      vex_printf("%6u ", tabc_slow[op]);
6271fa7b8031dea649db2f3b99b407d5a9a036dacdasewardj      vex_printf("%6u ", tabc_fast[op]);
628f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      for (co = 0; co < 16; co++) {
629f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj         Int n = tab_cond[op][co];
630f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj         if (n >= 1000) {
631f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj            vex_printf(" %3dK", n / 1000);
632f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj         } else
633f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj         if (n >= 0) {
634f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj            vex_printf(" %3d ", n );
635f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj         } else {
636f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj            vex_printf("     ");
637f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj         }
638f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      }
639f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      vex_printf("\n");
640f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   }
641f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   vex_printf("\n");
642f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj}
643f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
644f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardjstatic void initCounts ( void )
645f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj{
646f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   Int op, co;
647f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   initted = True;
648f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   for (op = 0; op < AMD64G_CC_OP_NUMBER; op++) {
649f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      tabc_fast[op] = tabc_slow[op] = 0;
650f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      for (co = 0; co < 16; co++)
651f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj         tab_cond[op][co] = 0;
652f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   }
653f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj}
654f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
6551fa7b8031dea649db2f3b99b407d5a9a036dacdasewardj#endif /* PROFILE_RFLAGS */
656f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
657f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
658f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
659f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj/* Calculate all the 6 flags from the supplied thunk parameters.
660f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   Worker function, not directly called from generated code. */
661f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardjstatic
662f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardjULong amd64g_calculate_rflags_all_WRK ( ULong cc_op,
663f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj                                        ULong cc_dep1_formal,
664f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj                                        ULong cc_dep2_formal,
665f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj                                        ULong cc_ndep_formal )
666118b23eb9e0d86e8d0f7e1a347134ec00ae5f821sewardj{
667f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   switch (cc_op) {
668f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64G_CC_OP_COPY:
669f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj         return cc_dep1_formal
670f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj                & (AMD64G_CC_MASK_O | AMD64G_CC_MASK_S | AMD64G_CC_MASK_Z
671f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj                   | AMD64G_CC_MASK_A | AMD64G_CC_MASK_C | AMD64G_CC_MASK_P);
672f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
673f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64G_CC_OP_ADDB:   ACTIONS_ADD( 8,  UChar  );
674f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64G_CC_OP_ADDW:   ACTIONS_ADD( 16, UShort );
675f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64G_CC_OP_ADDL:   ACTIONS_ADD( 32, UInt   );
676d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj      case AMD64G_CC_OP_ADDQ:   ACTIONS_ADD( 64, ULong  );
677f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
678f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64G_CC_OP_ADCB:   ACTIONS_ADC( 8,  UChar  );
679f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64G_CC_OP_ADCW:   ACTIONS_ADC( 16, UShort );
680f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64G_CC_OP_ADCL:   ACTIONS_ADC( 32, UInt   );
68185520e44c14bebadea604ba9ba32113b55988227sewardj      case AMD64G_CC_OP_ADCQ:   ACTIONS_ADC( 64, ULong  );
682f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
683f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64G_CC_OP_SUBB:   ACTIONS_SUB(  8, UChar  );
684f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64G_CC_OP_SUBW:   ACTIONS_SUB( 16, UShort );
685f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64G_CC_OP_SUBL:   ACTIONS_SUB( 32, UInt   );
686f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64G_CC_OP_SUBQ:   ACTIONS_SUB( 64, ULong  );
687f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
688f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64G_CC_OP_SBBB:   ACTIONS_SBB(  8, UChar  );
689f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64G_CC_OP_SBBW:   ACTIONS_SBB( 16, UShort );
690f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64G_CC_OP_SBBL:   ACTIONS_SBB( 32, UInt   );
69185520e44c14bebadea604ba9ba32113b55988227sewardj      case AMD64G_CC_OP_SBBQ:   ACTIONS_SBB( 64, ULong  );
692f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
693f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64G_CC_OP_LOGICB: ACTIONS_LOGIC(  8, UChar  );
694f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64G_CC_OP_LOGICW: ACTIONS_LOGIC( 16, UShort );
695f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64G_CC_OP_LOGICL: ACTIONS_LOGIC( 32, UInt   );
696f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64G_CC_OP_LOGICQ: ACTIONS_LOGIC( 64, ULong  );
697f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
698f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64G_CC_OP_INCB:   ACTIONS_INC(  8, UChar  );
699f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64G_CC_OP_INCW:   ACTIONS_INC( 16, UShort );
700f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64G_CC_OP_INCL:   ACTIONS_INC( 32, UInt   );
7017de0d3c800437fbd82c59d57d156f4823d67609fsewardj      case AMD64G_CC_OP_INCQ:   ACTIONS_INC( 64, ULong  );
702f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
703f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64G_CC_OP_DECB:   ACTIONS_DEC(  8, UChar  );
704f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64G_CC_OP_DECW:   ACTIONS_DEC( 16, UShort );
705f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64G_CC_OP_DECL:   ACTIONS_DEC( 32, UInt   );
7067de0d3c800437fbd82c59d57d156f4823d67609fsewardj      case AMD64G_CC_OP_DECQ:   ACTIONS_DEC( 64, ULong  );
707f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
708f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64G_CC_OP_SHLB:   ACTIONS_SHL(  8, UChar  );
709f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64G_CC_OP_SHLW:   ACTIONS_SHL( 16, UShort );
710f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64G_CC_OP_SHLL:   ACTIONS_SHL( 32, UInt   );
7117de0d3c800437fbd82c59d57d156f4823d67609fsewardj      case AMD64G_CC_OP_SHLQ:   ACTIONS_SHL( 64, ULong  );
712f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
713f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64G_CC_OP_SHRB:   ACTIONS_SHR(  8, UChar  );
714f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64G_CC_OP_SHRW:   ACTIONS_SHR( 16, UShort );
715f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64G_CC_OP_SHRL:   ACTIONS_SHR( 32, UInt   );
716a6b93d109a1d3b18e1ffaf3c1721216e79aaadc7sewardj      case AMD64G_CC_OP_SHRQ:   ACTIONS_SHR( 64, ULong  );
717f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
718f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64G_CC_OP_ROLB:   ACTIONS_ROL(  8, UChar  );
719f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64G_CC_OP_ROLW:   ACTIONS_ROL( 16, UShort );
720f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64G_CC_OP_ROLL:   ACTIONS_ROL( 32, UInt   );
72185520e44c14bebadea604ba9ba32113b55988227sewardj      case AMD64G_CC_OP_ROLQ:   ACTIONS_ROL( 64, ULong  );
722f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
723f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64G_CC_OP_RORB:   ACTIONS_ROR(  8, UChar  );
724f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64G_CC_OP_RORW:   ACTIONS_ROR( 16, UShort );
725f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64G_CC_OP_RORL:   ACTIONS_ROR( 32, UInt   );
72685520e44c14bebadea604ba9ba32113b55988227sewardj      case AMD64G_CC_OP_RORQ:   ACTIONS_ROR( 64, ULong  );
727f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
7281fa7b8031dea649db2f3b99b407d5a9a036dacdasewardj      case AMD64G_CC_OP_UMULB:  ACTIONS_UMUL(  8, UChar,  toUChar,
7291fa7b8031dea649db2f3b99b407d5a9a036dacdasewardj                                                  UShort, toUShort );
7301fa7b8031dea649db2f3b99b407d5a9a036dacdasewardj      case AMD64G_CC_OP_UMULW:  ACTIONS_UMUL( 16, UShort, toUShort,
7311fa7b8031dea649db2f3b99b407d5a9a036dacdasewardj                                                  UInt,   toUInt );
7321fa7b8031dea649db2f3b99b407d5a9a036dacdasewardj      case AMD64G_CC_OP_UMULL:  ACTIONS_UMUL( 32, UInt,   toUInt,
7331fa7b8031dea649db2f3b99b407d5a9a036dacdasewardj                                                  ULong,  idULong );
7341fa7b8031dea649db2f3b99b407d5a9a036dacdasewardj
7358bdb89a30baf14230e483916deaf1eaaf92d3d34sewardj      case AMD64G_CC_OP_UMULQ:  ACTIONS_UMULQ;
7368bdb89a30baf14230e483916deaf1eaaf92d3d34sewardj
7371fa7b8031dea649db2f3b99b407d5a9a036dacdasewardj      case AMD64G_CC_OP_SMULB:  ACTIONS_SMUL(  8, Char,   toUChar,
7381fa7b8031dea649db2f3b99b407d5a9a036dacdasewardj                                                  Short,  toUShort );
7391fa7b8031dea649db2f3b99b407d5a9a036dacdasewardj      case AMD64G_CC_OP_SMULW:  ACTIONS_SMUL( 16, Short,  toUShort,
7401fa7b8031dea649db2f3b99b407d5a9a036dacdasewardj                                                  Int,    toUInt   );
7411fa7b8031dea649db2f3b99b407d5a9a036dacdasewardj      case AMD64G_CC_OP_SMULL:  ACTIONS_SMUL( 32, Int,    toUInt,
7421fa7b8031dea649db2f3b99b407d5a9a036dacdasewardj                                                  Long,   idULong );
743f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
7441a01e65f9993d97095c2af463e98674a091834casewardj      case AMD64G_CC_OP_SMULQ:  ACTIONS_SMULQ;
745f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
746cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj      case AMD64G_CC_OP_ANDN32: ACTIONS_ANDN( 32, UInt   );
747cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj      case AMD64G_CC_OP_ANDN64: ACTIONS_ANDN( 64, ULong  );
748cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj
749cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj      case AMD64G_CC_OP_BLSI32: ACTIONS_BLSI( 32, UInt   );
750cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj      case AMD64G_CC_OP_BLSI64: ACTIONS_BLSI( 64, ULong  );
751cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj
752cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj      case AMD64G_CC_OP_BLSMSK32: ACTIONS_BLSMSK( 32, UInt   );
753cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj      case AMD64G_CC_OP_BLSMSK64: ACTIONS_BLSMSK( 64, ULong  );
754cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj
755cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj      case AMD64G_CC_OP_BLSR32: ACTIONS_BLSR( 32, UInt   );
756cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj      case AMD64G_CC_OP_BLSR64: ACTIONS_BLSR( 64, ULong  );
757cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj
758ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes      case AMD64G_CC_OP_ADCX32: ACTIONS_ADX( 32, UInt,  C );
759ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes      case AMD64G_CC_OP_ADCX64: ACTIONS_ADX( 64, ULong, C );
760ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes
761ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes      case AMD64G_CC_OP_ADOX32: ACTIONS_ADX( 32, UInt,  O );
762ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes      case AMD64G_CC_OP_ADOX64: ACTIONS_ADX( 64, ULong, O );
763ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes
764f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      default:
765f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj         /* shouldn't really make these calls from generated code */
766f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj         vex_printf("amd64g_calculate_rflags_all_WRK(AMD64)"
7671fa7b8031dea649db2f3b99b407d5a9a036dacdasewardj                    "( %llu, 0x%llx, 0x%llx, 0x%llx )\n",
768f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj                    cc_op, cc_dep1_formal, cc_dep2_formal, cc_ndep_formal );
769f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj         vpanic("amd64g_calculate_rflags_all_WRK(AMD64)");
770f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   }
771f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj}
772f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
773f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
774f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
775f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj/* Calculate all the 6 flags from the supplied thunk parameters. */
776f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardjULong amd64g_calculate_rflags_all ( ULong cc_op,
777f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj                                    ULong cc_dep1,
778f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj                                    ULong cc_dep2,
779f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj                                    ULong cc_ndep )
780f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj{
7811fa7b8031dea649db2f3b99b407d5a9a036dacdasewardj#  if PROFILE_RFLAGS
782f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   if (!initted) initCounts();
783f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   n_calc_all++;
784f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   if (SHOW_COUNTS_NOW) showCounts();
785f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj#  endif
786f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   return
787f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      amd64g_calculate_rflags_all_WRK ( cc_op, cc_dep1, cc_dep2, cc_ndep );
788f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj}
789f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
790f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
791f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
792f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj/* Calculate just the carry flag from the supplied thunk parameters. */
793f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardjULong amd64g_calculate_rflags_c ( ULong cc_op,
794f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj                                  ULong cc_dep1,
795f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj                                  ULong cc_dep2,
796f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj                                  ULong cc_ndep )
797f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj{
7981fa7b8031dea649db2f3b99b407d5a9a036dacdasewardj#  if PROFILE_RFLAGS
799f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   if (!initted) initCounts();
800f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   n_calc_c++;
801f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   tabc_fast[cc_op]++;
802f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   if (SHOW_COUNTS_NOW) showCounts();
803f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj#  endif
804f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
805f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   /* Fast-case some common ones. */
806f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   switch (cc_op) {
8077fc494b1b2abc210ee4b7a82d43f6a084a869022sewardj      case AMD64G_CC_OP_COPY:
8087fc494b1b2abc210ee4b7a82d43f6a084a869022sewardj         return (cc_dep1 >> AMD64G_CC_SHIFT_C) & 1;
8090354035b9222b1d6e37172ac2a70b19c816df025sewardj      case AMD64G_CC_OP_LOGICQ:
810f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64G_CC_OP_LOGICL:
811f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64G_CC_OP_LOGICW:
812f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64G_CC_OP_LOGICB:
813f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj         return 0;
8140354035b9222b1d6e37172ac2a70b19c816df025sewardj	 //      case AMD64G_CC_OP_SUBL:
8150354035b9222b1d6e37172ac2a70b19c816df025sewardj	 //         return ((UInt)cc_dep1) < ((UInt)cc_dep2)
8160354035b9222b1d6e37172ac2a70b19c816df025sewardj	 //                   ? AMD64G_CC_MASK_C : 0;
8170354035b9222b1d6e37172ac2a70b19c816df025sewardj	 //      case AMD64G_CC_OP_SUBW:
8180354035b9222b1d6e37172ac2a70b19c816df025sewardj	 //         return ((UInt)(cc_dep1 & 0xFFFF)) < ((UInt)(cc_dep2 & 0xFFFF))
8190354035b9222b1d6e37172ac2a70b19c816df025sewardj	 //                   ? AMD64G_CC_MASK_C : 0;
8200354035b9222b1d6e37172ac2a70b19c816df025sewardj	 //      case AMD64G_CC_OP_SUBB:
8210354035b9222b1d6e37172ac2a70b19c816df025sewardj	 //         return ((UInt)(cc_dep1 & 0xFF)) < ((UInt)(cc_dep2 & 0xFF))
8220354035b9222b1d6e37172ac2a70b19c816df025sewardj	 //                   ? AMD64G_CC_MASK_C : 0;
8230354035b9222b1d6e37172ac2a70b19c816df025sewardj	 //      case AMD64G_CC_OP_INCL:
8240354035b9222b1d6e37172ac2a70b19c816df025sewardj	 //      case AMD64G_CC_OP_DECL:
8250354035b9222b1d6e37172ac2a70b19c816df025sewardj	 //         return cc_ndep & AMD64G_CC_MASK_C;
826f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      default:
827f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj         break;
828f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   }
829f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
8301fa7b8031dea649db2f3b99b407d5a9a036dacdasewardj#  if PROFILE_RFLAGS
831f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   tabc_fast[cc_op]--;
832f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   tabc_slow[cc_op]++;
833f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj#  endif
834f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
835f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   return amd64g_calculate_rflags_all_WRK(cc_op,cc_dep1,cc_dep2,cc_ndep)
836f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj          & AMD64G_CC_MASK_C;
837118b23eb9e0d86e8d0f7e1a347134ec00ae5f821sewardj}
838118b23eb9e0d86e8d0f7e1a347134ec00ae5f821sewardj
839118b23eb9e0d86e8d0f7e1a347134ec00ae5f821sewardj
840f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
841f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj/* returns 1 or 0 */
842f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardjULong amd64g_calculate_condition ( ULong/*AMD64Condcode*/ cond,
843f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj                                   ULong cc_op,
844f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj                                   ULong cc_dep1,
845f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj                                   ULong cc_dep2,
846f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj                                   ULong cc_ndep )
847df0e002ac9be60d99aef2e2cfc1801d5d734ae9bsewardj{
848f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   ULong rflags = amd64g_calculate_rflags_all_WRK(cc_op, cc_dep1,
849f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj                                                  cc_dep2, cc_ndep);
850f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   ULong of,sf,zf,cf,pf;
851f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   ULong inv = cond & 1;
852f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
8531fa7b8031dea649db2f3b99b407d5a9a036dacdasewardj#  if PROFILE_RFLAGS
854f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   if (!initted) initCounts();
855f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   tab_cond[cc_op][cond]++;
856f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   n_calc_cond++;
857f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   if (SHOW_COUNTS_NOW) showCounts();
858f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj#  endif
859f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
860f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   switch (cond) {
861f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64CondNO:
862f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64CondO: /* OF == 1 */
863f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj         of = rflags >> AMD64G_CC_SHIFT_O;
864f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj         return 1 & (inv ^ of);
865f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
866f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64CondNZ:
867f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64CondZ: /* ZF == 1 */
868f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj         zf = rflags >> AMD64G_CC_SHIFT_Z;
869f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj         return 1 & (inv ^ zf);
870f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
871f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64CondNB:
872f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64CondB: /* CF == 1 */
873f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj         cf = rflags >> AMD64G_CC_SHIFT_C;
874f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj         return 1 & (inv ^ cf);
875f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj         break;
876f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
877f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64CondNBE:
878f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64CondBE: /* (CF or ZF) == 1 */
879f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj         cf = rflags >> AMD64G_CC_SHIFT_C;
880f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj         zf = rflags >> AMD64G_CC_SHIFT_Z;
881f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj         return 1 & (inv ^ (cf | zf));
882f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj         break;
883f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
884f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64CondNS:
885f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64CondS: /* SF == 1 */
886f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj         sf = rflags >> AMD64G_CC_SHIFT_S;
887f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj         return 1 & (inv ^ sf);
888f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
889f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64CondNP:
890f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64CondP: /* PF == 1 */
891f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj         pf = rflags >> AMD64G_CC_SHIFT_P;
892f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj         return 1 & (inv ^ pf);
893f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
894f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64CondNL:
895f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64CondL: /* (SF xor OF) == 1 */
896f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj         sf = rflags >> AMD64G_CC_SHIFT_S;
897f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj         of = rflags >> AMD64G_CC_SHIFT_O;
898f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj         return 1 & (inv ^ (sf ^ of));
899f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj         break;
900f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
901f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64CondNLE:
902f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      case AMD64CondLE: /* ((SF xor OF) or ZF)  == 1 */
903f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj         sf = rflags >> AMD64G_CC_SHIFT_S;
904f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj         of = rflags >> AMD64G_CC_SHIFT_O;
905f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj         zf = rflags >> AMD64G_CC_SHIFT_Z;
906f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj         return 1 & (inv ^ ((sf ^ of) | zf));
907f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj         break;
908f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
909f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      default:
910f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj         /* shouldn't really make these calls from generated code */
911f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj         vex_printf("amd64g_calculate_condition"
9121fa7b8031dea649db2f3b99b407d5a9a036dacdasewardj                    "( %llu, %llu, 0x%llx, 0x%llx, 0x%llx )\n",
913f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj                    cond, cc_op, cc_dep1, cc_dep2, cc_ndep );
914f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj         vpanic("amd64g_calculate_condition");
915f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   }
916df0e002ac9be60d99aef2e2cfc1801d5d734ae9bsewardj}
91744d494dfad0c12f96f61cf9edfc889dfa69e3b30sewardj
918f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
919f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj/* VISIBLE TO LIBVEX CLIENT */
920efa834abaded25c8aff2f3923e476ef7cc1d0396florianULong LibVEX_GuestAMD64_get_rflags ( /*IN*/const VexGuestAMD64State* vex_state )
921354e5c6a228cbd811c1267adda79509500da158esewardj{
922f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   ULong rflags = amd64g_calculate_rflags_all_WRK(
923f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj                     vex_state->guest_CC_OP,
924f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj                     vex_state->guest_CC_DEP1,
925f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj                     vex_state->guest_CC_DEP2,
926f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj                     vex_state->guest_CC_NDEP
927f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj                  );
9287de0d3c800437fbd82c59d57d156f4823d67609fsewardj   Long dflag = vex_state->guest_DFLAG;
9297de0d3c800437fbd82c59d57d156f4823d67609fsewardj   vassert(dflag == 1 || dflag == -1);
9307de0d3c800437fbd82c59d57d156f4823d67609fsewardj   if (dflag == -1)
931f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj      rflags |= (1<<10);
93285520e44c14bebadea604ba9ba32113b55988227sewardj   if (vex_state->guest_IDFLAG == 1)
93385520e44c14bebadea604ba9ba32113b55988227sewardj      rflags |= (1<<21);
9345e120aaf7b9e659ecbc641dc1e20e40b2219618esewardj   if (vex_state->guest_ACFLAG == 1)
9355e120aaf7b9e659ecbc641dc1e20e40b2219618esewardj      rflags |= (1<<18);
9365e120aaf7b9e659ecbc641dc1e20e40b2219618esewardj
937f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   return rflags;
938354e5c6a228cbd811c1267adda79509500da158esewardj}
939f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
940d660d41d4174e44f284bad3264601662ed68d4a1sewardj/* VISIBLE TO LIBVEX CLIENT */
941d660d41d4174e44f284bad3264601662ed68d4a1sewardjvoid
9423e5d82d003f0746010e22c7cfc4a25b34c9641f1sewardjLibVEX_GuestAMD64_put_rflags ( ULong rflags,
9433e5d82d003f0746010e22c7cfc4a25b34c9641f1sewardj                               /*MOD*/VexGuestAMD64State* vex_state )
9443e5d82d003f0746010e22c7cfc4a25b34c9641f1sewardj{
9453e5d82d003f0746010e22c7cfc4a25b34c9641f1sewardj   /* D flag */
9463e5d82d003f0746010e22c7cfc4a25b34c9641f1sewardj   if (rflags & AMD64G_CC_MASK_D) {
9473e5d82d003f0746010e22c7cfc4a25b34c9641f1sewardj      vex_state->guest_DFLAG = -1;
9483e5d82d003f0746010e22c7cfc4a25b34c9641f1sewardj      rflags &= ~AMD64G_CC_MASK_D;
9493e5d82d003f0746010e22c7cfc4a25b34c9641f1sewardj   }
9503e5d82d003f0746010e22c7cfc4a25b34c9641f1sewardj   else
9513e5d82d003f0746010e22c7cfc4a25b34c9641f1sewardj      vex_state->guest_DFLAG = 1;
9523e5d82d003f0746010e22c7cfc4a25b34c9641f1sewardj
9533e5d82d003f0746010e22c7cfc4a25b34c9641f1sewardj   /* ID flag */
9543e5d82d003f0746010e22c7cfc4a25b34c9641f1sewardj   if (rflags & AMD64G_CC_MASK_ID) {
9553e5d82d003f0746010e22c7cfc4a25b34c9641f1sewardj      vex_state->guest_IDFLAG = 1;
9563e5d82d003f0746010e22c7cfc4a25b34c9641f1sewardj      rflags &= ~AMD64G_CC_MASK_ID;
9573e5d82d003f0746010e22c7cfc4a25b34c9641f1sewardj   }
9583e5d82d003f0746010e22c7cfc4a25b34c9641f1sewardj   else
9593e5d82d003f0746010e22c7cfc4a25b34c9641f1sewardj      vex_state->guest_IDFLAG = 0;
9603e5d82d003f0746010e22c7cfc4a25b34c9641f1sewardj
9613e5d82d003f0746010e22c7cfc4a25b34c9641f1sewardj   /* AC flag */
9623e5d82d003f0746010e22c7cfc4a25b34c9641f1sewardj   if (rflags & AMD64G_CC_MASK_AC) {
9633e5d82d003f0746010e22c7cfc4a25b34c9641f1sewardj      vex_state->guest_ACFLAG = 1;
9643e5d82d003f0746010e22c7cfc4a25b34c9641f1sewardj      rflags &= ~AMD64G_CC_MASK_AC;
9653e5d82d003f0746010e22c7cfc4a25b34c9641f1sewardj   }
9663e5d82d003f0746010e22c7cfc4a25b34c9641f1sewardj   else
9673e5d82d003f0746010e22c7cfc4a25b34c9641f1sewardj      vex_state->guest_ACFLAG = 0;
9683e5d82d003f0746010e22c7cfc4a25b34c9641f1sewardj
9693e5d82d003f0746010e22c7cfc4a25b34c9641f1sewardj   UInt cc_mask = AMD64G_CC_MASK_O | AMD64G_CC_MASK_S | AMD64G_CC_MASK_Z |
9703e5d82d003f0746010e22c7cfc4a25b34c9641f1sewardj                  AMD64G_CC_MASK_A | AMD64G_CC_MASK_C | AMD64G_CC_MASK_P;
9713e5d82d003f0746010e22c7cfc4a25b34c9641f1sewardj   vex_state->guest_CC_OP   = AMD64G_CC_OP_COPY;
9723e5d82d003f0746010e22c7cfc4a25b34c9641f1sewardj   vex_state->guest_CC_DEP1 = rflags & cc_mask;
9733e5d82d003f0746010e22c7cfc4a25b34c9641f1sewardj   vex_state->guest_CC_DEP2 = 0;
9743e5d82d003f0746010e22c7cfc4a25b34c9641f1sewardj   vex_state->guest_CC_NDEP = 0;
9753e5d82d003f0746010e22c7cfc4a25b34c9641f1sewardj}
9763e5d82d003f0746010e22c7cfc4a25b34c9641f1sewardj
9773e5d82d003f0746010e22c7cfc4a25b34c9641f1sewardj/* VISIBLE TO LIBVEX CLIENT */
9783e5d82d003f0746010e22c7cfc4a25b34c9641f1sewardjvoid
979d660d41d4174e44f284bad3264601662ed68d4a1sewardjLibVEX_GuestAMD64_put_rflag_c ( ULong new_carry_flag,
980d660d41d4174e44f284bad3264601662ed68d4a1sewardj                               /*MOD*/VexGuestAMD64State* vex_state )
981d660d41d4174e44f284bad3264601662ed68d4a1sewardj{
982d660d41d4174e44f284bad3264601662ed68d4a1sewardj   ULong oszacp = amd64g_calculate_rflags_all_WRK(
983d660d41d4174e44f284bad3264601662ed68d4a1sewardj                     vex_state->guest_CC_OP,
984d660d41d4174e44f284bad3264601662ed68d4a1sewardj                     vex_state->guest_CC_DEP1,
985d660d41d4174e44f284bad3264601662ed68d4a1sewardj                     vex_state->guest_CC_DEP2,
986d660d41d4174e44f284bad3264601662ed68d4a1sewardj                     vex_state->guest_CC_NDEP
987d660d41d4174e44f284bad3264601662ed68d4a1sewardj                  );
988d660d41d4174e44f284bad3264601662ed68d4a1sewardj   if (new_carry_flag & 1) {
989d660d41d4174e44f284bad3264601662ed68d4a1sewardj      oszacp |= AMD64G_CC_MASK_C;
990d660d41d4174e44f284bad3264601662ed68d4a1sewardj   } else {
991d660d41d4174e44f284bad3264601662ed68d4a1sewardj      oszacp &= ~AMD64G_CC_MASK_C;
992d660d41d4174e44f284bad3264601662ed68d4a1sewardj   }
993d660d41d4174e44f284bad3264601662ed68d4a1sewardj   vex_state->guest_CC_OP   = AMD64G_CC_OP_COPY;
994d660d41d4174e44f284bad3264601662ed68d4a1sewardj   vex_state->guest_CC_DEP1 = oszacp;
995d660d41d4174e44f284bad3264601662ed68d4a1sewardj   vex_state->guest_CC_DEP2 = 0;
996d660d41d4174e44f284bad3264601662ed68d4a1sewardj   vex_state->guest_CC_NDEP = 0;
997d660d41d4174e44f284bad3264601662ed68d4a1sewardj}
998d660d41d4174e44f284bad3264601662ed68d4a1sewardj
999f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
1000f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj/*---------------------------------------------------------------*/
1001f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj/*--- %rflags translation-time function specialisers.         ---*/
1002f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj/*--- These help iropt specialise calls the above run-time    ---*/
1003f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj/*--- %rflags functions.                                      ---*/
1004f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj/*---------------------------------------------------------------*/
1005354e5c6a228cbd811c1267adda79509500da158esewardj
10060354035b9222b1d6e37172ac2a70b19c816df025sewardj/* Used by the optimiser to try specialisations.  Returns an
10070354035b9222b1d6e37172ac2a70b19c816df025sewardj   equivalent expression, or NULL if none. */
10080354035b9222b1d6e37172ac2a70b19c816df025sewardj
10090354035b9222b1d6e37172ac2a70b19c816df025sewardjstatic Bool isU64 ( IRExpr* e, ULong n )
10100354035b9222b1d6e37172ac2a70b19c816df025sewardj{
101165b17c682ad74b2b0d1d6011a0ec847d25fc96a8sewardj   return toBool( e->tag == Iex_Const
101265b17c682ad74b2b0d1d6011a0ec847d25fc96a8sewardj                  && e->Iex.Const.con->tag == Ico_U64
101365b17c682ad74b2b0d1d6011a0ec847d25fc96a8sewardj                  && e->Iex.Const.con->Ico.U64 == n );
10140354035b9222b1d6e37172ac2a70b19c816df025sewardj}
1015354e5c6a228cbd811c1267adda79509500da158esewardj
10161ff4756e1731485e6bf3cd96717cd8398daec1f2florianIRExpr* guest_amd64_spechelper ( const HChar* function_name,
1017be9179130bdfb61d0e03ecb32eced8dd5c7bfc74sewardj                                 IRExpr** args,
1018be9179130bdfb61d0e03ecb32eced8dd5c7bfc74sewardj                                 IRStmt** precedingStmts,
1019be9179130bdfb61d0e03ecb32eced8dd5c7bfc74sewardj                                 Int      n_precedingStmts )
102044d494dfad0c12f96f61cf9edfc889dfa69e3b30sewardj{
10210354035b9222b1d6e37172ac2a70b19c816df025sewardj#  define unop(_op,_a1) IRExpr_Unop((_op),(_a1))
10220354035b9222b1d6e37172ac2a70b19c816df025sewardj#  define binop(_op,_a1,_a2) IRExpr_Binop((_op),(_a1),(_a2))
10230354035b9222b1d6e37172ac2a70b19c816df025sewardj#  define mkU64(_n) IRExpr_Const(IRConst_U64(_n))
10249cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj#  define mkU32(_n) IRExpr_Const(IRConst_U32(_n))
10250354035b9222b1d6e37172ac2a70b19c816df025sewardj#  define mkU8(_n)  IRExpr_Const(IRConst_U8(_n))
10260354035b9222b1d6e37172ac2a70b19c816df025sewardj
10270354035b9222b1d6e37172ac2a70b19c816df025sewardj   Int i, arity = 0;
10280354035b9222b1d6e37172ac2a70b19c816df025sewardj   for (i = 0; args[i]; i++)
10290354035b9222b1d6e37172ac2a70b19c816df025sewardj      arity++;
10300354035b9222b1d6e37172ac2a70b19c816df025sewardj#  if 0
10310354035b9222b1d6e37172ac2a70b19c816df025sewardj   vex_printf("spec request:\n");
10320354035b9222b1d6e37172ac2a70b19c816df025sewardj   vex_printf("   %s  ", function_name);
10330354035b9222b1d6e37172ac2a70b19c816df025sewardj   for (i = 0; i < arity; i++) {
10340354035b9222b1d6e37172ac2a70b19c816df025sewardj      vex_printf("  ");
10350354035b9222b1d6e37172ac2a70b19c816df025sewardj      ppIRExpr(args[i]);
10360354035b9222b1d6e37172ac2a70b19c816df025sewardj   }
10370354035b9222b1d6e37172ac2a70b19c816df025sewardj   vex_printf("\n");
10380354035b9222b1d6e37172ac2a70b19c816df025sewardj#  endif
10390354035b9222b1d6e37172ac2a70b19c816df025sewardj
10400354035b9222b1d6e37172ac2a70b19c816df025sewardj   /* --------- specialising "amd64g_calculate_condition" --------- */
10410354035b9222b1d6e37172ac2a70b19c816df025sewardj
10420354035b9222b1d6e37172ac2a70b19c816df025sewardj   if (vex_streq(function_name, "amd64g_calculate_condition")) {
10430354035b9222b1d6e37172ac2a70b19c816df025sewardj      /* specialise calls to above "calculate condition" function */
10440354035b9222b1d6e37172ac2a70b19c816df025sewardj      IRExpr *cond, *cc_op, *cc_dep1, *cc_dep2;
10450354035b9222b1d6e37172ac2a70b19c816df025sewardj      vassert(arity == 5);
10460354035b9222b1d6e37172ac2a70b19c816df025sewardj      cond    = args[0];
10470354035b9222b1d6e37172ac2a70b19c816df025sewardj      cc_op   = args[1];
10480354035b9222b1d6e37172ac2a70b19c816df025sewardj      cc_dep1 = args[2];
10490354035b9222b1d6e37172ac2a70b19c816df025sewardj      cc_dep2 = args[3];
10500354035b9222b1d6e37172ac2a70b19c816df025sewardj
1051db261e489a4302789faccbfc17b96182051c8c3asewardj      /*---------------- ADDQ ----------------*/
1052db261e489a4302789faccbfc17b96182051c8c3asewardj
1053db261e489a4302789faccbfc17b96182051c8c3asewardj      if (isU64(cc_op, AMD64G_CC_OP_ADDQ) && isU64(cond, AMD64CondZ)) {
1054db261e489a4302789faccbfc17b96182051c8c3asewardj         /* long long add, then Z --> test (dst+src == 0) */
1055db261e489a4302789faccbfc17b96182051c8c3asewardj         return unop(Iop_1Uto64,
1056db261e489a4302789faccbfc17b96182051c8c3asewardj                     binop(Iop_CmpEQ64,
1057db261e489a4302789faccbfc17b96182051c8c3asewardj                           binop(Iop_Add64, cc_dep1, cc_dep2),
1058db261e489a4302789faccbfc17b96182051c8c3asewardj                           mkU64(0)));
1059db261e489a4302789faccbfc17b96182051c8c3asewardj      }
10600354035b9222b1d6e37172ac2a70b19c816df025sewardj
1061aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj      /*---------------- ADDL ----------------*/
1062aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj
1063aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj      if (isU64(cc_op, AMD64G_CC_OP_ADDL) && isU64(cond, AMD64CondO)) {
1064aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj         /* This is very commonly generated by Javascript JITs, for
1065aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj            the idiom "do a 32-bit add and jump to out-of-line code if
1066aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj            an overflow occurs". */
1067aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj         /* long add, then O (overflow)
1068aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj            --> ((dep1 ^ dep2 ^ -1) & (dep1 ^ (dep1 + dep2)))[31]
1069aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj            --> (((dep1 ^ dep2 ^ -1) & (dep1 ^ (dep1 +64 dep2))) >>u 31) & 1
1070aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj            --> (((not(dep1 ^ dep2)) & (dep1 ^ (dep1 +64 dep2))) >>u 31) & 1
1071aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj         */
1072aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj         vassert(isIRAtom(cc_dep1));
1073aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj         vassert(isIRAtom(cc_dep2));
1074aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj         return
1075aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj            binop(Iop_And64,
1076aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj                  binop(Iop_Shr64,
1077aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj                        binop(Iop_And64,
1078aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj                              unop(Iop_Not64,
1079aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj                                   binop(Iop_Xor64, cc_dep1, cc_dep2)),
1080aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj                              binop(Iop_Xor64,
1081aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj                                    cc_dep1,
1082aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj                                    binop(Iop_Add64, cc_dep1, cc_dep2))),
1083aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj                        mkU8(31)),
1084aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj                  mkU64(1));
1085aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj
1086aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj      }
1087aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj
10884b06a0b4ad062b86e43431d82ab514d6dc68407fsewardj      /*---------------- SUBQ ----------------*/
10894b06a0b4ad062b86e43431d82ab514d6dc68407fsewardj
1090aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj      /* 0, */
1091aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj      if (isU64(cc_op, AMD64G_CC_OP_SUBQ) && isU64(cond, AMD64CondO)) {
1092aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj         /* long long sub/cmp, then O (overflow)
1093aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj            --> ((dep1 ^ dep2) & (dep1 ^ (dep1 - dep2)))[63]
1094aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj            --> ((dep1 ^ dep2) & (dep1 ^ (dep1 - dep2))) >>u 63
1095aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj         */
1096aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj         vassert(isIRAtom(cc_dep1));
1097aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj         vassert(isIRAtom(cc_dep2));
1098aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj         return binop(Iop_Shr64,
1099aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj                      binop(Iop_And64,
1100aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj                            binop(Iop_Xor64, cc_dep1, cc_dep2),
1101aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj                            binop(Iop_Xor64,
1102aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj                                  cc_dep1,
1103aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj                                  binop(Iop_Sub64, cc_dep1, cc_dep2))),
1104d937bebf71808133be12831f57f47e8fd022ab91mjw                      mkU8(63));
1105aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj      }
1106aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj      if (isU64(cc_op, AMD64G_CC_OP_SUBQ) && isU64(cond, AMD64CondNO)) {
1107aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj         /* No action.  Never yet found a test case. */
1108aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj      }
1109aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj
1110edccb443be188091d51d7ecd984ce75e649adb16sewardj      /* 2, 3 */
11114b06a0b4ad062b86e43431d82ab514d6dc68407fsewardj      if (isU64(cc_op, AMD64G_CC_OP_SUBQ) && isU64(cond, AMD64CondB)) {
11124b06a0b4ad062b86e43431d82ab514d6dc68407fsewardj         /* long long sub/cmp, then B (unsigned less than)
11134b06a0b4ad062b86e43431d82ab514d6dc68407fsewardj            --> test dst <u src */
11144b06a0b4ad062b86e43431d82ab514d6dc68407fsewardj         return unop(Iop_1Uto64,
11154b06a0b4ad062b86e43431d82ab514d6dc68407fsewardj                     binop(Iop_CmpLT64U, cc_dep1, cc_dep2));
11164b06a0b4ad062b86e43431d82ab514d6dc68407fsewardj      }
1117a9e4a80f0533c83cebca31070135d9506d5ae4c7sewardj      if (isU64(cc_op, AMD64G_CC_OP_SUBQ) && isU64(cond, AMD64CondNB)) {
1118a9e4a80f0533c83cebca31070135d9506d5ae4c7sewardj         /* long long sub/cmp, then NB (unsigned greater than or equal)
1119a9e4a80f0533c83cebca31070135d9506d5ae4c7sewardj            --> test src <=u dst */
1120a9e4a80f0533c83cebca31070135d9506d5ae4c7sewardj         /* Note, args are opposite way round from the usual */
1121a9e4a80f0533c83cebca31070135d9506d5ae4c7sewardj         return unop(Iop_1Uto64,
1122a9e4a80f0533c83cebca31070135d9506d5ae4c7sewardj                     binop(Iop_CmpLE64U, cc_dep2, cc_dep1));
1123a9e4a80f0533c83cebca31070135d9506d5ae4c7sewardj      }
1124a9e4a80f0533c83cebca31070135d9506d5ae4c7sewardj
1125edccb443be188091d51d7ecd984ce75e649adb16sewardj      /* 4, 5 */
1126edccb443be188091d51d7ecd984ce75e649adb16sewardj      if (isU64(cc_op, AMD64G_CC_OP_SUBQ) && isU64(cond, AMD64CondZ)) {
1127edccb443be188091d51d7ecd984ce75e649adb16sewardj         /* long long sub/cmp, then Z --> test dst==src */
11283cfd1f038f2f8457f63f2731ed5a53d4544f52absewardj         return unop(Iop_1Uto64,
1129edccb443be188091d51d7ecd984ce75e649adb16sewardj                     binop(Iop_CmpEQ64,cc_dep1,cc_dep2));
1130edccb443be188091d51d7ecd984ce75e649adb16sewardj      }
1131edccb443be188091d51d7ecd984ce75e649adb16sewardj      if (isU64(cc_op, AMD64G_CC_OP_SUBQ) && isU64(cond, AMD64CondNZ)) {
1132edccb443be188091d51d7ecd984ce75e649adb16sewardj         /* long long sub/cmp, then NZ --> test dst!=src */
1133edccb443be188091d51d7ecd984ce75e649adb16sewardj         return unop(Iop_1Uto64,
1134edccb443be188091d51d7ecd984ce75e649adb16sewardj                     binop(Iop_CmpNE64,cc_dep1,cc_dep2));
11353cfd1f038f2f8457f63f2731ed5a53d4544f52absewardj      }
11363cfd1f038f2f8457f63f2731ed5a53d4544f52absewardj
1137edccb443be188091d51d7ecd984ce75e649adb16sewardj      /* 6, 7 */
1138a9e4a80f0533c83cebca31070135d9506d5ae4c7sewardj      if (isU64(cc_op, AMD64G_CC_OP_SUBQ) && isU64(cond, AMD64CondBE)) {
1139a9e4a80f0533c83cebca31070135d9506d5ae4c7sewardj         /* long long sub/cmp, then BE (unsigned less than or equal)
1140a9e4a80f0533c83cebca31070135d9506d5ae4c7sewardj            --> test dst <=u src */
1141a9e4a80f0533c83cebca31070135d9506d5ae4c7sewardj         return unop(Iop_1Uto64,
1142a9e4a80f0533c83cebca31070135d9506d5ae4c7sewardj                     binop(Iop_CmpLE64U, cc_dep1, cc_dep2));
1143a9e4a80f0533c83cebca31070135d9506d5ae4c7sewardj      }
11443a05a1543f99be21e75ed7136c45bf1a24594822sewardj      if (isU64(cc_op, AMD64G_CC_OP_SUBQ) && isU64(cond, AMD64CondNBE)) {
11453a05a1543f99be21e75ed7136c45bf1a24594822sewardj         /* long long sub/cmp, then NBE (unsigned greater than)
11463a05a1543f99be21e75ed7136c45bf1a24594822sewardj            --> test !(dst <=u src) */
11473a05a1543f99be21e75ed7136c45bf1a24594822sewardj         return binop(Iop_Xor64,
11483a05a1543f99be21e75ed7136c45bf1a24594822sewardj                      unop(Iop_1Uto64,
11493a05a1543f99be21e75ed7136c45bf1a24594822sewardj                           binop(Iop_CmpLE64U, cc_dep1, cc_dep2)),
11503a05a1543f99be21e75ed7136c45bf1a24594822sewardj                      mkU64(1));
11513a05a1543f99be21e75ed7136c45bf1a24594822sewardj      }
1152a9e4a80f0533c83cebca31070135d9506d5ae4c7sewardj
1153aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj      /* 8, 9 */
1154aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj      if (isU64(cc_op, AMD64G_CC_OP_SUBQ) && isU64(cond, AMD64CondS)) {
1155aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj         /* long long sub/cmp, then S (negative)
1156aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj            --> (dst-src)[63]
1157aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj            --> (dst-src) >>u 63 */
1158aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj         return binop(Iop_Shr64,
1159aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj                      binop(Iop_Sub64, cc_dep1, cc_dep2),
1160aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj                      mkU8(63));
1161aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj      }
1162aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj      if (isU64(cc_op, AMD64G_CC_OP_SUBQ) && isU64(cond, AMD64CondNS)) {
1163aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj         /* long long sub/cmp, then NS (not negative)
1164aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj            --> (dst-src)[63] ^ 1
1165aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj            --> ((dst-src) >>u 63) ^ 1 */
1166aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj         return binop(Iop_Xor64,
1167aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj                      binop(Iop_Shr64,
1168aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj                            binop(Iop_Sub64, cc_dep1, cc_dep2),
1169aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj                            mkU8(63)),
1170aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj                      mkU64(1));
1171aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj      }
1172aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj
1173aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj      /* 12, 13 */
1174edccb443be188091d51d7ecd984ce75e649adb16sewardj      if (isU64(cc_op, AMD64G_CC_OP_SUBQ) && isU64(cond, AMD64CondL)) {
1175edccb443be188091d51d7ecd984ce75e649adb16sewardj         /* long long sub/cmp, then L (signed less than)
1176edccb443be188091d51d7ecd984ce75e649adb16sewardj            --> test dst <s src */
1177db261e489a4302789faccbfc17b96182051c8c3asewardj         return unop(Iop_1Uto64,
1178edccb443be188091d51d7ecd984ce75e649adb16sewardj                     binop(Iop_CmpLT64S, cc_dep1, cc_dep2));
1179a9e4a80f0533c83cebca31070135d9506d5ae4c7sewardj      }
1180aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj      if (isU64(cc_op, AMD64G_CC_OP_SUBQ) && isU64(cond, AMD64CondNL)) {
1181aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj         /* long long sub/cmp, then NL (signed greater than or equal)
1182aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj            --> test dst >=s src
1183aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj            --> test src <=s dst */
1184aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj         return unop(Iop_1Uto64,
1185aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj                     binop(Iop_CmpLE64S, cc_dep2, cc_dep1));
1186aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj      }
1187edccb443be188091d51d7ecd984ce75e649adb16sewardj
1188aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj      /* 14, 15 */
1189aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj      if (isU64(cc_op, AMD64G_CC_OP_SUBQ) && isU64(cond, AMD64CondLE)) {
1190aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj         /* long long sub/cmp, then LE (signed less than or equal)
1191aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj            --> test dst <=s src */
1192aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj         return unop(Iop_1Uto64,
1193aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj                     binop(Iop_CmpLE64S, cc_dep1, cc_dep2));
1194aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj      }
1195edccb443be188091d51d7ecd984ce75e649adb16sewardj      if (isU64(cc_op, AMD64G_CC_OP_SUBQ) && isU64(cond, AMD64CondNLE)) {
1196edccb443be188091d51d7ecd984ce75e649adb16sewardj         /* long sub/cmp, then NLE (signed greater than)
1197edccb443be188091d51d7ecd984ce75e649adb16sewardj            --> test !(dst <=s src)
1198edccb443be188091d51d7ecd984ce75e649adb16sewardj            --> test (dst >s src)
1199edccb443be188091d51d7ecd984ce75e649adb16sewardj            --> test (src <s dst) */
1200a9e4a80f0533c83cebca31070135d9506d5ae4c7sewardj         return unop(Iop_1Uto64,
1201edccb443be188091d51d7ecd984ce75e649adb16sewardj                     binop(Iop_CmpLT64S, cc_dep2, cc_dep1));
1202edccb443be188091d51d7ecd984ce75e649adb16sewardj
1203db261e489a4302789faccbfc17b96182051c8c3asewardj      }
1204db261e489a4302789faccbfc17b96182051c8c3asewardj
1205edccb443be188091d51d7ecd984ce75e649adb16sewardj      /*---------------- SUBL ----------------*/
1206edccb443be188091d51d7ecd984ce75e649adb16sewardj
1207aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj      /* 0, */
1208aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj      if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondO)) {
1209aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj         /* This is very commonly generated by Javascript JITs, for
1210aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj            the idiom "do a 32-bit subtract and jump to out-of-line
1211aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj            code if an overflow occurs". */
1212aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj         /* long sub/cmp, then O (overflow)
1213aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj            --> ((dep1 ^ dep2) & (dep1 ^ (dep1 - dep2)))[31]
1214aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj            --> (((dep1 ^ dep2) & (dep1 ^ (dep1 -64 dep2))) >>u 31) & 1
1215aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj         */
1216aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj         vassert(isIRAtom(cc_dep1));
1217aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj         vassert(isIRAtom(cc_dep2));
1218aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj         return
1219aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj            binop(Iop_And64,
1220aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj                  binop(Iop_Shr64,
1221aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj                        binop(Iop_And64,
1222aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj                              binop(Iop_Xor64, cc_dep1, cc_dep2),
1223aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj                              binop(Iop_Xor64,
1224aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj                                    cc_dep1,
1225aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj                                    binop(Iop_Sub64, cc_dep1, cc_dep2))),
1226aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj                        mkU8(31)),
1227aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj                  mkU64(1));
1228aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj      }
1229aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj      if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondNO)) {
1230aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj         /* No action.  Never yet found a test case. */
1231aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj      }
1232aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj
1233aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj      /* 2, 3 */
1234edccb443be188091d51d7ecd984ce75e649adb16sewardj      if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondB)) {
1235edccb443be188091d51d7ecd984ce75e649adb16sewardj         /* long sub/cmp, then B (unsigned less than)
1236edccb443be188091d51d7ecd984ce75e649adb16sewardj            --> test dst <u src */
12376d709a9a67687e446d25838deccd1698bfb3d273sewardj         return unop(Iop_1Uto64,
1238edccb443be188091d51d7ecd984ce75e649adb16sewardj                     binop(Iop_CmpLT32U,
12399cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj                           unop(Iop_64to32, cc_dep1),
12409cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj                           unop(Iop_64to32, cc_dep2)));
12410354035b9222b1d6e37172ac2a70b19c816df025sewardj      }
1242aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj      if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondNB)) {
1243aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj         /* long sub/cmp, then NB (unsigned greater than or equal)
1244aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj            --> test src <=u dst */
1245aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj         /* Note, args are opposite way round from the usual */
1246aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj         return unop(Iop_1Uto64,
1247aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj                     binop(Iop_CmpLE32U,
1248aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj                           unop(Iop_64to32, cc_dep2),
1249aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj                           unop(Iop_64to32, cc_dep1)));
1250aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj      }
12510354035b9222b1d6e37172ac2a70b19c816df025sewardj
1252edccb443be188091d51d7ecd984ce75e649adb16sewardj      /* 4, 5 */
1253edccb443be188091d51d7ecd984ce75e649adb16sewardj      if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondZ)) {
1254edccb443be188091d51d7ecd984ce75e649adb16sewardj         /* long sub/cmp, then Z --> test dst==src */
12556d709a9a67687e446d25838deccd1698bfb3d273sewardj         return unop(Iop_1Uto64,
1256edccb443be188091d51d7ecd984ce75e649adb16sewardj                     binop(Iop_CmpEQ32,
12579cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj                           unop(Iop_64to32, cc_dep1),
12589cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj                           unop(Iop_64to32, cc_dep2)));
12590354035b9222b1d6e37172ac2a70b19c816df025sewardj      }
1260edccb443be188091d51d7ecd984ce75e649adb16sewardj      if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondNZ)) {
1261edccb443be188091d51d7ecd984ce75e649adb16sewardj         /* long sub/cmp, then NZ --> test dst!=src */
1262ff6b34ac26070c47e55803e61f8ae5554ddcac27sewardj         return unop(Iop_1Uto64,
1263edccb443be188091d51d7ecd984ce75e649adb16sewardj                     binop(Iop_CmpNE32,
1264edccb443be188091d51d7ecd984ce75e649adb16sewardj                           unop(Iop_64to32, cc_dep1),
1265edccb443be188091d51d7ecd984ce75e649adb16sewardj                           unop(Iop_64to32, cc_dep2)));
1266ff6b34ac26070c47e55803e61f8ae5554ddcac27sewardj      }
12670354035b9222b1d6e37172ac2a70b19c816df025sewardj
1268edccb443be188091d51d7ecd984ce75e649adb16sewardj      /* 6, 7 */
1269a9e4a80f0533c83cebca31070135d9506d5ae4c7sewardj      if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondBE)) {
1270a9e4a80f0533c83cebca31070135d9506d5ae4c7sewardj         /* long sub/cmp, then BE (unsigned less than or equal)
1271a9e4a80f0533c83cebca31070135d9506d5ae4c7sewardj            --> test dst <=u src */
1272a9e4a80f0533c83cebca31070135d9506d5ae4c7sewardj         return unop(Iop_1Uto64,
12739cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj                     binop(Iop_CmpLE32U,
12749cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj                           unop(Iop_64to32, cc_dep1),
12759cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj                           unop(Iop_64to32, cc_dep2)));
1276a9e4a80f0533c83cebca31070135d9506d5ae4c7sewardj      }
127732d615b76c65938d815fe529e690a7f79a24a4ecsewardj      if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondNBE)) {
127832d615b76c65938d815fe529e690a7f79a24a4ecsewardj         /* long sub/cmp, then NBE (unsigned greater than)
127932d615b76c65938d815fe529e690a7f79a24a4ecsewardj            --> test src <u dst */
128032d615b76c65938d815fe529e690a7f79a24a4ecsewardj         /* Note, args are opposite way round from the usual */
128132d615b76c65938d815fe529e690a7f79a24a4ecsewardj         return unop(Iop_1Uto64,
12829cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj                     binop(Iop_CmpLT32U,
12839cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj                           unop(Iop_64to32, cc_dep2),
12849cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj                           unop(Iop_64to32, cc_dep1)));
128532d615b76c65938d815fe529e690a7f79a24a4ecsewardj      }
12860354035b9222b1d6e37172ac2a70b19c816df025sewardj
1287aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj      /* 8, 9 */
12883b09235486a95b746c7aeca7fe7e21f3271fd489sewardj      if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondS)) {
1289aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj         /* long sub/cmp, then S (negative)
1290aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj            --> (dst-src)[31]
1291aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj            --> ((dst -64 src) >>u 31) & 1
1292aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj            Pointless to narrow the args to 32 bit before the subtract. */
1293aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj         return binop(Iop_And64,
1294aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj                      binop(Iop_Shr64,
1295aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj                            binop(Iop_Sub64, cc_dep1, cc_dep2),
1296aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj                            mkU8(31)),
1297aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj                      mkU64(1));
1298aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj      }
1299aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj      if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondNS)) {
1300aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj         /* long sub/cmp, then NS (not negative)
1301aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj            --> (dst-src)[31] ^ 1
1302aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj            --> (((dst -64 src) >>u 31) & 1) ^ 1
1303aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj            Pointless to narrow the args to 32 bit before the subtract. */
1304aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj         return binop(Iop_Xor64,
1305aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj                      binop(Iop_And64,
1306aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj                            binop(Iop_Shr64,
1307aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj                                  binop(Iop_Sub64, cc_dep1, cc_dep2),
1308aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj                                  mkU8(31)),
1309aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj                            mkU64(1)),
1310aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj                      mkU64(1));
13113b09235486a95b746c7aeca7fe7e21f3271fd489sewardj      }
13123b09235486a95b746c7aeca7fe7e21f3271fd489sewardj
1313aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj      /* 12, 13 */
1314edccb443be188091d51d7ecd984ce75e649adb16sewardj      if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondL)) {
1315edccb443be188091d51d7ecd984ce75e649adb16sewardj         /* long sub/cmp, then L (signed less than)
1316edccb443be188091d51d7ecd984ce75e649adb16sewardj            --> test dst <s src */
1317e430418063e237ff914c91ecb0d32ac0dd14587asewardj         return unop(Iop_1Uto64,
1318edccb443be188091d51d7ecd984ce75e649adb16sewardj                     binop(Iop_CmpLT32S,
1319e430418063e237ff914c91ecb0d32ac0dd14587asewardj                           unop(Iop_64to32, cc_dep1),
1320e430418063e237ff914c91ecb0d32ac0dd14587asewardj                           unop(Iop_64to32, cc_dep2)));
1321e430418063e237ff914c91ecb0d32ac0dd14587asewardj      }
1322aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj      if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondNL)) {
1323aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj         /* long sub/cmp, then NL (signed greater than or equal)
1324aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj            --> test dst >=s src
1325aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj            --> test src <=s dst */
1326aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj         return unop(Iop_1Uto64,
1327aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj                     binop(Iop_CmpLE32S,
1328aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj                           unop(Iop_64to32, cc_dep2),
1329aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj                           unop(Iop_64to32, cc_dep1)));
1330aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj      }
1331e430418063e237ff914c91ecb0d32ac0dd14587asewardj
1332edccb443be188091d51d7ecd984ce75e649adb16sewardj      /* 14, 15 */
1333edccb443be188091d51d7ecd984ce75e649adb16sewardj      if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondLE)) {
1334edccb443be188091d51d7ecd984ce75e649adb16sewardj         /* long sub/cmp, then LE (signed less than or equal)
1335edccb443be188091d51d7ecd984ce75e649adb16sewardj            --> test dst <=s src */
1336edccb443be188091d51d7ecd984ce75e649adb16sewardj         return unop(Iop_1Uto64,
1337edccb443be188091d51d7ecd984ce75e649adb16sewardj                     binop(Iop_CmpLE32S,
1338edccb443be188091d51d7ecd984ce75e649adb16sewardj                           unop(Iop_64to32, cc_dep1),
1339edccb443be188091d51d7ecd984ce75e649adb16sewardj                           unop(Iop_64to32, cc_dep2)));
1340edccb443be188091d51d7ecd984ce75e649adb16sewardj
1341edccb443be188091d51d7ecd984ce75e649adb16sewardj      }
1342edccb443be188091d51d7ecd984ce75e649adb16sewardj      if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondNLE)) {
1343edccb443be188091d51d7ecd984ce75e649adb16sewardj         /* long sub/cmp, then NLE (signed greater than)
1344edccb443be188091d51d7ecd984ce75e649adb16sewardj            --> test !(dst <=s src)
1345edccb443be188091d51d7ecd984ce75e649adb16sewardj            --> test (dst >s src)
1346edccb443be188091d51d7ecd984ce75e649adb16sewardj            --> test (src <s dst) */
1347edccb443be188091d51d7ecd984ce75e649adb16sewardj         return unop(Iop_1Uto64,
1348edccb443be188091d51d7ecd984ce75e649adb16sewardj                     binop(Iop_CmpLT32S,
1349edccb443be188091d51d7ecd984ce75e649adb16sewardj                           unop(Iop_64to32, cc_dep2),
1350edccb443be188091d51d7ecd984ce75e649adb16sewardj                           unop(Iop_64to32, cc_dep1)));
1351edccb443be188091d51d7ecd984ce75e649adb16sewardj
1352edccb443be188091d51d7ecd984ce75e649adb16sewardj      }
1353edccb443be188091d51d7ecd984ce75e649adb16sewardj
13540354035b9222b1d6e37172ac2a70b19c816df025sewardj      /*---------------- SUBW ----------------*/
13550354035b9222b1d6e37172ac2a70b19c816df025sewardj
135666a5e810b05fbe4473bf5babb5446c20091b4602sewardj      /* 4, 5 */
1357a82b476f778a599ece9d9001d51b6a024d4657dasewardj      if (isU64(cc_op, AMD64G_CC_OP_SUBW) && isU64(cond, AMD64CondZ)) {
1358a82b476f778a599ece9d9001d51b6a024d4657dasewardj         /* word sub/cmp, then Z --> test dst==src */
1359a82b476f778a599ece9d9001d51b6a024d4657dasewardj         return unop(Iop_1Uto64,
1360a82b476f778a599ece9d9001d51b6a024d4657dasewardj                     binop(Iop_CmpEQ16,
1361a82b476f778a599ece9d9001d51b6a024d4657dasewardj                           unop(Iop_64to16,cc_dep1),
1362a82b476f778a599ece9d9001d51b6a024d4657dasewardj                           unop(Iop_64to16,cc_dep2)));
1363a82b476f778a599ece9d9001d51b6a024d4657dasewardj      }
1364beb5291313fcd91543dd19c76a9e04d8b0e94af9sewardj      if (isU64(cc_op, AMD64G_CC_OP_SUBW) && isU64(cond, AMD64CondNZ)) {
1365beb5291313fcd91543dd19c76a9e04d8b0e94af9sewardj         /* word sub/cmp, then NZ --> test dst!=src */
1366beb5291313fcd91543dd19c76a9e04d8b0e94af9sewardj         return unop(Iop_1Uto64,
1367beb5291313fcd91543dd19c76a9e04d8b0e94af9sewardj                     binop(Iop_CmpNE16,
1368beb5291313fcd91543dd19c76a9e04d8b0e94af9sewardj                           unop(Iop_64to16,cc_dep1),
1369beb5291313fcd91543dd19c76a9e04d8b0e94af9sewardj                           unop(Iop_64to16,cc_dep2)));
1370beb5291313fcd91543dd19c76a9e04d8b0e94af9sewardj      }
13710354035b9222b1d6e37172ac2a70b19c816df025sewardj
137266a5e810b05fbe4473bf5babb5446c20091b4602sewardj      /* 6, */
1373aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj      if (isU64(cc_op, AMD64G_CC_OP_SUBW) && isU64(cond, AMD64CondBE)) {
1374aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj         /* word sub/cmp, then BE (unsigned less than or equal)
1375aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj            --> test dst <=u src */
1376aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj         return unop(Iop_1Uto64,
1377aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj                     binop(Iop_CmpLE64U,
1378aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj                           binop(Iop_Shl64, cc_dep1, mkU8(48)),
1379aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj                           binop(Iop_Shl64, cc_dep2, mkU8(48))));
1380aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj      }
1381aedb8595d3c44725ba4397263731e4a14f4d4b70sewardj
1382ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes      /* 8, 9 */
1383ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes      if (isU64(cc_op, AMD64G_CC_OP_SUBW) && isU64(cond, AMD64CondS)
1384ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes                                          && isU64(cc_dep2, 0)) {
1385ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes         /* word sub/cmp of zero, then S --> test (dst-0 <s 0)
1386ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes                                         --> test dst <s 0
1387ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes                                         --> (ULong)dst[15]
1388ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes            This is yet another scheme by which clang figures out if the
1389ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes            top bit of a word is 1 or 0.  See also LOGICB/CondS below. */
1390ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes         /* Note: isU64(cc_dep2, 0) is correct, even though this is
1391ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes            for an 16-bit comparison, since the args to the helper
1392ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes            function are always U64s. */
1393ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes         return binop(Iop_And64,
1394ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes                      binop(Iop_Shr64,cc_dep1,mkU8(15)),
1395ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes                      mkU64(1));
1396ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes      }
1397ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes      if (isU64(cc_op, AMD64G_CC_OP_SUBW) && isU64(cond, AMD64CondNS)
1398ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes                                          && isU64(cc_dep2, 0)) {
1399ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes         /* word sub/cmp of zero, then NS --> test !(dst-0 <s 0)
1400ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes                                          --> test !(dst <s 0)
1401ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes                                          --> (ULong) !dst[15]
1402ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes         */
1403ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes         return binop(Iop_Xor64,
1404ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes                      binop(Iop_And64,
1405ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes                            binop(Iop_Shr64,cc_dep1,mkU8(15)),
1406ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes                            mkU64(1)),
1407ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes                      mkU64(1));
1408ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes      }
1409ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes
141066a5e810b05fbe4473bf5babb5446c20091b4602sewardj      /* 14, */
14113f81c4e65a102d0c74857d221921d6d8882fdb33sewardj      if (isU64(cc_op, AMD64G_CC_OP_SUBW) && isU64(cond, AMD64CondLE)) {
14123be608db7407faffb476302dfd34d4b82e13c26csewardj         /* word sub/cmp, then LE (signed less than or equal)
14133f81c4e65a102d0c74857d221921d6d8882fdb33sewardj            --> test dst <=s src */
14143f81c4e65a102d0c74857d221921d6d8882fdb33sewardj         return unop(Iop_1Uto64,
14153f81c4e65a102d0c74857d221921d6d8882fdb33sewardj                     binop(Iop_CmpLE64S,
14163f81c4e65a102d0c74857d221921d6d8882fdb33sewardj                           binop(Iop_Shl64,cc_dep1,mkU8(48)),
14173f81c4e65a102d0c74857d221921d6d8882fdb33sewardj                           binop(Iop_Shl64,cc_dep2,mkU8(48))));
14183f81c4e65a102d0c74857d221921d6d8882fdb33sewardj
14193f81c4e65a102d0c74857d221921d6d8882fdb33sewardj      }
14203f81c4e65a102d0c74857d221921d6d8882fdb33sewardj
14210354035b9222b1d6e37172ac2a70b19c816df025sewardj      /*---------------- SUBB ----------------*/
14220354035b9222b1d6e37172ac2a70b19c816df025sewardj
142366a5e810b05fbe4473bf5babb5446c20091b4602sewardj      /* 2, 3 */
142466a5e810b05fbe4473bf5babb5446c20091b4602sewardj      if (isU64(cc_op, AMD64G_CC_OP_SUBB) && isU64(cond, AMD64CondB)) {
142566a5e810b05fbe4473bf5babb5446c20091b4602sewardj         /* byte sub/cmp, then B (unsigned less than)
142666a5e810b05fbe4473bf5babb5446c20091b4602sewardj            --> test dst <u src */
142766a5e810b05fbe4473bf5babb5446c20091b4602sewardj         return unop(Iop_1Uto64,
142866a5e810b05fbe4473bf5babb5446c20091b4602sewardj                     binop(Iop_CmpLT64U,
142966a5e810b05fbe4473bf5babb5446c20091b4602sewardj                           binop(Iop_And64, cc_dep1, mkU64(0xFF)),
143066a5e810b05fbe4473bf5babb5446c20091b4602sewardj                           binop(Iop_And64, cc_dep2, mkU64(0xFF))));
143166a5e810b05fbe4473bf5babb5446c20091b4602sewardj      }
143266a5e810b05fbe4473bf5babb5446c20091b4602sewardj      if (isU64(cc_op, AMD64G_CC_OP_SUBB) && isU64(cond, AMD64CondNB)) {
143366a5e810b05fbe4473bf5babb5446c20091b4602sewardj         /* byte sub/cmp, then NB (unsigned greater than or equal)
143466a5e810b05fbe4473bf5babb5446c20091b4602sewardj            --> test src <=u dst */
143566a5e810b05fbe4473bf5babb5446c20091b4602sewardj         /* Note, args are opposite way round from the usual */
143666a5e810b05fbe4473bf5babb5446c20091b4602sewardj         return unop(Iop_1Uto64,
143766a5e810b05fbe4473bf5babb5446c20091b4602sewardj                     binop(Iop_CmpLE64U,
143866a5e810b05fbe4473bf5babb5446c20091b4602sewardj                           binop(Iop_And64, cc_dep2, mkU64(0xFF)),
143966a5e810b05fbe4473bf5babb5446c20091b4602sewardj                           binop(Iop_And64, cc_dep1, mkU64(0xFF))));
144066a5e810b05fbe4473bf5babb5446c20091b4602sewardj      }
144166a5e810b05fbe4473bf5babb5446c20091b4602sewardj
144266a5e810b05fbe4473bf5babb5446c20091b4602sewardj      /* 4, 5 */
14430354035b9222b1d6e37172ac2a70b19c816df025sewardj      if (isU64(cc_op, AMD64G_CC_OP_SUBB) && isU64(cond, AMD64CondZ)) {
14440354035b9222b1d6e37172ac2a70b19c816df025sewardj         /* byte sub/cmp, then Z --> test dst==src */
14456d709a9a67687e446d25838deccd1698bfb3d273sewardj         return unop(Iop_1Uto64,
14460354035b9222b1d6e37172ac2a70b19c816df025sewardj                     binop(Iop_CmpEQ8,
14476d709a9a67687e446d25838deccd1698bfb3d273sewardj                           unop(Iop_64to8,cc_dep1),
14486d709a9a67687e446d25838deccd1698bfb3d273sewardj                           unop(Iop_64to8,cc_dep2)));
14490354035b9222b1d6e37172ac2a70b19c816df025sewardj      }
145032d615b76c65938d815fe529e690a7f79a24a4ecsewardj      if (isU64(cc_op, AMD64G_CC_OP_SUBB) && isU64(cond, AMD64CondNZ)) {
145132d615b76c65938d815fe529e690a7f79a24a4ecsewardj         /* byte sub/cmp, then NZ --> test dst!=src */
145232d615b76c65938d815fe529e690a7f79a24a4ecsewardj         return unop(Iop_1Uto64,
145332d615b76c65938d815fe529e690a7f79a24a4ecsewardj                     binop(Iop_CmpNE8,
145432d615b76c65938d815fe529e690a7f79a24a4ecsewardj                           unop(Iop_64to8,cc_dep1),
145532d615b76c65938d815fe529e690a7f79a24a4ecsewardj                           unop(Iop_64to8,cc_dep2)));
145632d615b76c65938d815fe529e690a7f79a24a4ecsewardj      }
145732d615b76c65938d815fe529e690a7f79a24a4ecsewardj
145866a5e810b05fbe4473bf5babb5446c20091b4602sewardj      /* 6, */
1459e430418063e237ff914c91ecb0d32ac0dd14587asewardj      if (isU64(cc_op, AMD64G_CC_OP_SUBB) && isU64(cond, AMD64CondBE)) {
1460e430418063e237ff914c91ecb0d32ac0dd14587asewardj         /* byte sub/cmp, then BE (unsigned less than or equal)
1461e430418063e237ff914c91ecb0d32ac0dd14587asewardj            --> test dst <=u src */
1462e430418063e237ff914c91ecb0d32ac0dd14587asewardj         return unop(Iop_1Uto64,
1463e430418063e237ff914c91ecb0d32ac0dd14587asewardj                     binop(Iop_CmpLE64U,
1464e430418063e237ff914c91ecb0d32ac0dd14587asewardj                           binop(Iop_And64, cc_dep1, mkU64(0xFF)),
1465e430418063e237ff914c91ecb0d32ac0dd14587asewardj                           binop(Iop_And64, cc_dep2, mkU64(0xFF))));
1466e430418063e237ff914c91ecb0d32ac0dd14587asewardj      }
1467e430418063e237ff914c91ecb0d32ac0dd14587asewardj
146866a5e810b05fbe4473bf5babb5446c20091b4602sewardj      /* 8, 9 */
14693be608db7407faffb476302dfd34d4b82e13c26csewardj      if (isU64(cc_op, AMD64G_CC_OP_SUBB) && isU64(cond, AMD64CondS)
14703be608db7407faffb476302dfd34d4b82e13c26csewardj                                          && isU64(cc_dep2, 0)) {
14713be608db7407faffb476302dfd34d4b82e13c26csewardj         /* byte sub/cmp of zero, then S --> test (dst-0 <s 0)
14723be608db7407faffb476302dfd34d4b82e13c26csewardj                                         --> test dst <s 0
14733be608db7407faffb476302dfd34d4b82e13c26csewardj                                         --> (ULong)dst[7]
14743be608db7407faffb476302dfd34d4b82e13c26csewardj            This is yet another scheme by which gcc figures out if the
14753be608db7407faffb476302dfd34d4b82e13c26csewardj            top bit of a byte is 1 or 0.  See also LOGICB/CondS below. */
14763be608db7407faffb476302dfd34d4b82e13c26csewardj         /* Note: isU64(cc_dep2, 0) is correct, even though this is
14773be608db7407faffb476302dfd34d4b82e13c26csewardj            for an 8-bit comparison, since the args to the helper
14783be608db7407faffb476302dfd34d4b82e13c26csewardj            function are always U64s. */
14793be608db7407faffb476302dfd34d4b82e13c26csewardj         return binop(Iop_And64,
14803be608db7407faffb476302dfd34d4b82e13c26csewardj                      binop(Iop_Shr64,cc_dep1,mkU8(7)),
14813be608db7407faffb476302dfd34d4b82e13c26csewardj                      mkU64(1));
14823be608db7407faffb476302dfd34d4b82e13c26csewardj      }
1483cd538b445c0489aae317dabf2425698435c9a1f3sewardj      if (isU64(cc_op, AMD64G_CC_OP_SUBB) && isU64(cond, AMD64CondNS)
1484cd538b445c0489aae317dabf2425698435c9a1f3sewardj                                          && isU64(cc_dep2, 0)) {
1485cd538b445c0489aae317dabf2425698435c9a1f3sewardj         /* byte sub/cmp of zero, then NS --> test !(dst-0 <s 0)
1486cd538b445c0489aae317dabf2425698435c9a1f3sewardj                                          --> test !(dst <s 0)
1487cd538b445c0489aae317dabf2425698435c9a1f3sewardj                                          --> (ULong) !dst[7]
1488cd538b445c0489aae317dabf2425698435c9a1f3sewardj         */
1489cd538b445c0489aae317dabf2425698435c9a1f3sewardj         return binop(Iop_Xor64,
1490cd538b445c0489aae317dabf2425698435c9a1f3sewardj                      binop(Iop_And64,
1491cd538b445c0489aae317dabf2425698435c9a1f3sewardj                            binop(Iop_Shr64,cc_dep1,mkU8(7)),
1492cd538b445c0489aae317dabf2425698435c9a1f3sewardj                            mkU64(1)),
1493cd538b445c0489aae317dabf2425698435c9a1f3sewardj                      mkU64(1));
1494cd538b445c0489aae317dabf2425698435c9a1f3sewardj      }
14953be608db7407faffb476302dfd34d4b82e13c26csewardj
14964b06a0b4ad062b86e43431d82ab514d6dc68407fsewardj      /*---------------- LOGICQ ----------------*/
14974b06a0b4ad062b86e43431d82ab514d6dc68407fsewardj
14984b06a0b4ad062b86e43431d82ab514d6dc68407fsewardj      if (isU64(cc_op, AMD64G_CC_OP_LOGICQ) && isU64(cond, AMD64CondZ)) {
14994b06a0b4ad062b86e43431d82ab514d6dc68407fsewardj         /* long long and/or/xor, then Z --> test dst==0 */
15004b06a0b4ad062b86e43431d82ab514d6dc68407fsewardj         return unop(Iop_1Uto64,
15014b06a0b4ad062b86e43431d82ab514d6dc68407fsewardj                     binop(Iop_CmpEQ64, cc_dep1, mkU64(0)));
15024b06a0b4ad062b86e43431d82ab514d6dc68407fsewardj      }
15030cd7473678993cbd9a3f8ba01089221af3becb74sewardj      if (isU64(cc_op, AMD64G_CC_OP_LOGICQ) && isU64(cond, AMD64CondNZ)) {
15040cd7473678993cbd9a3f8ba01089221af3becb74sewardj         /* long long and/or/xor, then NZ --> test dst!=0 */
15050cd7473678993cbd9a3f8ba01089221af3becb74sewardj         return unop(Iop_1Uto64,
15060cd7473678993cbd9a3f8ba01089221af3becb74sewardj                     binop(Iop_CmpNE64, cc_dep1, mkU64(0)));
15070cd7473678993cbd9a3f8ba01089221af3becb74sewardj      }
15084b06a0b4ad062b86e43431d82ab514d6dc68407fsewardj
150977fd8467f1c25c2873ece6e3328d8ebf3afebb12sewardj      if (isU64(cc_op, AMD64G_CC_OP_LOGICQ) && isU64(cond, AMD64CondL)) {
151077fd8467f1c25c2873ece6e3328d8ebf3afebb12sewardj         /* long long and/or/xor, then L
151177fd8467f1c25c2873ece6e3328d8ebf3afebb12sewardj            LOGIC sets SF and ZF according to the
151277fd8467f1c25c2873ece6e3328d8ebf3afebb12sewardj            result and makes OF be zero.  L computes SF ^ OF, but
151377fd8467f1c25c2873ece6e3328d8ebf3afebb12sewardj            OF is zero, so this reduces to SF -- which will be 1 iff
151477fd8467f1c25c2873ece6e3328d8ebf3afebb12sewardj            the result is < signed 0.  Hence ...
151577fd8467f1c25c2873ece6e3328d8ebf3afebb12sewardj         */
151677fd8467f1c25c2873ece6e3328d8ebf3afebb12sewardj         return unop(Iop_1Uto64,
151777fd8467f1c25c2873ece6e3328d8ebf3afebb12sewardj                     binop(Iop_CmpLT64S,
151877fd8467f1c25c2873ece6e3328d8ebf3afebb12sewardj                           cc_dep1,
151977fd8467f1c25c2873ece6e3328d8ebf3afebb12sewardj                           mkU64(0)));
152077fd8467f1c25c2873ece6e3328d8ebf3afebb12sewardj      }
152177fd8467f1c25c2873ece6e3328d8ebf3afebb12sewardj
15220354035b9222b1d6e37172ac2a70b19c816df025sewardj      /*---------------- LOGICL ----------------*/
15230354035b9222b1d6e37172ac2a70b19c816df025sewardj
15240354035b9222b1d6e37172ac2a70b19c816df025sewardj      if (isU64(cc_op, AMD64G_CC_OP_LOGICL) && isU64(cond, AMD64CondZ)) {
15250354035b9222b1d6e37172ac2a70b19c816df025sewardj         /* long and/or/xor, then Z --> test dst==0 */
15266d709a9a67687e446d25838deccd1698bfb3d273sewardj         return unop(Iop_1Uto64,
15279cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj                     binop(Iop_CmpEQ32,
15289cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj                           unop(Iop_64to32, cc_dep1),
15299cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj                           mkU32(0)));
1530005b4ef5a50535516154e60fa65b3420fe4eed35sewardj      }
1531005b4ef5a50535516154e60fa65b3420fe4eed35sewardj      if (isU64(cc_op, AMD64G_CC_OP_LOGICL) && isU64(cond, AMD64CondNZ)) {
1532005b4ef5a50535516154e60fa65b3420fe4eed35sewardj         /* long and/or/xor, then NZ --> test dst!=0 */
1533005b4ef5a50535516154e60fa65b3420fe4eed35sewardj         return unop(Iop_1Uto64,
15349cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj                     binop(Iop_CmpNE32,
15359cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj                           unop(Iop_64to32, cc_dep1),
15369cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj                           mkU32(0)));
15370354035b9222b1d6e37172ac2a70b19c816df025sewardj      }
15380354035b9222b1d6e37172ac2a70b19c816df025sewardj
15390354035b9222b1d6e37172ac2a70b19c816df025sewardj      if (isU64(cc_op, AMD64G_CC_OP_LOGICL) && isU64(cond, AMD64CondLE)) {
15400354035b9222b1d6e37172ac2a70b19c816df025sewardj         /* long and/or/xor, then LE
15410354035b9222b1d6e37172ac2a70b19c816df025sewardj            This is pretty subtle.  LOGIC sets SF and ZF according to the
154277fd8467f1c25c2873ece6e3328d8ebf3afebb12sewardj            result and makes OF be zero.  LE computes (SF ^ OF) | ZF, but
154377fd8467f1c25c2873ece6e3328d8ebf3afebb12sewardj            OF is zero, so this reduces to SF | ZF -- which will be 1 iff
15440354035b9222b1d6e37172ac2a70b19c816df025sewardj            the result is <=signed 0.  Hence ...
15450354035b9222b1d6e37172ac2a70b19c816df025sewardj         */
15466d709a9a67687e446d25838deccd1698bfb3d273sewardj         return unop(Iop_1Uto64,
15479cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj                     binop(Iop_CmpLE32S,
15489cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj                           unop(Iop_64to32, cc_dep1),
15499cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj                           mkU32(0)));
15500354035b9222b1d6e37172ac2a70b19c816df025sewardj      }
15510354035b9222b1d6e37172ac2a70b19c816df025sewardj
1552e430418063e237ff914c91ecb0d32ac0dd14587asewardj      if (isU64(cc_op, AMD64G_CC_OP_LOGICL) && isU64(cond, AMD64CondS)) {
1553e430418063e237ff914c91ecb0d32ac0dd14587asewardj         /* long and/or/xor, then S --> (ULong)result[31] */
1554e430418063e237ff914c91ecb0d32ac0dd14587asewardj         return binop(Iop_And64,
1555e430418063e237ff914c91ecb0d32ac0dd14587asewardj                      binop(Iop_Shr64, cc_dep1, mkU8(31)),
1556e430418063e237ff914c91ecb0d32ac0dd14587asewardj                      mkU64(1));
1557e430418063e237ff914c91ecb0d32ac0dd14587asewardj      }
1558e430418063e237ff914c91ecb0d32ac0dd14587asewardj      if (isU64(cc_op, AMD64G_CC_OP_LOGICL) && isU64(cond, AMD64CondNS)) {
1559e430418063e237ff914c91ecb0d32ac0dd14587asewardj         /* long and/or/xor, then S --> (ULong) ~ result[31] */
1560e430418063e237ff914c91ecb0d32ac0dd14587asewardj         return binop(Iop_Xor64,
1561e430418063e237ff914c91ecb0d32ac0dd14587asewardj                binop(Iop_And64,
1562e430418063e237ff914c91ecb0d32ac0dd14587asewardj                      binop(Iop_Shr64, cc_dep1, mkU8(31)),
1563e430418063e237ff914c91ecb0d32ac0dd14587asewardj                      mkU64(1)),
1564e430418063e237ff914c91ecb0d32ac0dd14587asewardj                mkU64(1));
1565e430418063e237ff914c91ecb0d32ac0dd14587asewardj      }
1566e430418063e237ff914c91ecb0d32ac0dd14587asewardj
156761acf4ca755d2d2b2632a4fb31b4fc21e681c5f6sewardj      /*---------------- LOGICW ----------------*/
156861acf4ca755d2d2b2632a4fb31b4fc21e681c5f6sewardj
156961acf4ca755d2d2b2632a4fb31b4fc21e681c5f6sewardj      if (isU64(cc_op, AMD64G_CC_OP_LOGICW) && isU64(cond, AMD64CondZ)) {
157061acf4ca755d2d2b2632a4fb31b4fc21e681c5f6sewardj         /* word and/or/xor, then Z --> test dst==0 */
157161acf4ca755d2d2b2632a4fb31b4fc21e681c5f6sewardj         return unop(Iop_1Uto64,
157261acf4ca755d2d2b2632a4fb31b4fc21e681c5f6sewardj                     binop(Iop_CmpEQ64,
157361acf4ca755d2d2b2632a4fb31b4fc21e681c5f6sewardj                           binop(Iop_And64, cc_dep1, mkU64(0xFFFF)),
157461acf4ca755d2d2b2632a4fb31b4fc21e681c5f6sewardj                           mkU64(0)));
157561acf4ca755d2d2b2632a4fb31b4fc21e681c5f6sewardj      }
157661acf4ca755d2d2b2632a4fb31b4fc21e681c5f6sewardj      if (isU64(cc_op, AMD64G_CC_OP_LOGICW) && isU64(cond, AMD64CondNZ)) {
157761acf4ca755d2d2b2632a4fb31b4fc21e681c5f6sewardj         /* word and/or/xor, then NZ --> test dst!=0 */
157861acf4ca755d2d2b2632a4fb31b4fc21e681c5f6sewardj         return unop(Iop_1Uto64,
157961acf4ca755d2d2b2632a4fb31b4fc21e681c5f6sewardj                     binop(Iop_CmpNE64,
158061acf4ca755d2d2b2632a4fb31b4fc21e681c5f6sewardj                           binop(Iop_And64, cc_dep1, mkU64(0xFFFF)),
158161acf4ca755d2d2b2632a4fb31b4fc21e681c5f6sewardj                           mkU64(0)));
158261acf4ca755d2d2b2632a4fb31b4fc21e681c5f6sewardj      }
158361acf4ca755d2d2b2632a4fb31b4fc21e681c5f6sewardj
15844b06a0b4ad062b86e43431d82ab514d6dc68407fsewardj      /*---------------- LOGICB ----------------*/
15854b06a0b4ad062b86e43431d82ab514d6dc68407fsewardj
15864b06a0b4ad062b86e43431d82ab514d6dc68407fsewardj      if (isU64(cc_op, AMD64G_CC_OP_LOGICB) && isU64(cond, AMD64CondZ)) {
15874b06a0b4ad062b86e43431d82ab514d6dc68407fsewardj         /* byte and/or/xor, then Z --> test dst==0 */
15884b06a0b4ad062b86e43431d82ab514d6dc68407fsewardj         return unop(Iop_1Uto64,
15894b06a0b4ad062b86e43431d82ab514d6dc68407fsewardj                     binop(Iop_CmpEQ64, binop(Iop_And64,cc_dep1,mkU64(255)),
15904b06a0b4ad062b86e43431d82ab514d6dc68407fsewardj                                        mkU64(0)));
1591ff6b34ac26070c47e55803e61f8ae5554ddcac27sewardj      }
1592ff6b34ac26070c47e55803e61f8ae5554ddcac27sewardj      if (isU64(cc_op, AMD64G_CC_OP_LOGICB) && isU64(cond, AMD64CondNZ)) {
1593ff6b34ac26070c47e55803e61f8ae5554ddcac27sewardj         /* byte and/or/xor, then NZ --> test dst!=0 */
1594ff6b34ac26070c47e55803e61f8ae5554ddcac27sewardj         return unop(Iop_1Uto64,
1595ff6b34ac26070c47e55803e61f8ae5554ddcac27sewardj                     binop(Iop_CmpNE64, binop(Iop_And64,cc_dep1,mkU64(255)),
1596ff6b34ac26070c47e55803e61f8ae5554ddcac27sewardj                                        mkU64(0)));
15974b06a0b4ad062b86e43431d82ab514d6dc68407fsewardj      }
15983f81c4e65a102d0c74857d221921d6d8882fdb33sewardj
1599346d9a198e8db67114d158e97e33072bf737bc25sewardj      if (isU64(cc_op, AMD64G_CC_OP_LOGICB) && isU64(cond, AMD64CondS)) {
1600346d9a198e8db67114d158e97e33072bf737bc25sewardj         /* this is an idiom gcc sometimes uses to find out if the top
1601346d9a198e8db67114d158e97e33072bf737bc25sewardj            bit of a byte register is set: eg testb %al,%al; js ..
1602346d9a198e8db67114d158e97e33072bf737bc25sewardj            Since it just depends on the top bit of the byte, extract
1603346d9a198e8db67114d158e97e33072bf737bc25sewardj            that bit and explicitly get rid of all the rest.  This
1604346d9a198e8db67114d158e97e33072bf737bc25sewardj            helps memcheck avoid false positives in the case where any
1605346d9a198e8db67114d158e97e33072bf737bc25sewardj            of the other bits in the byte are undefined. */
1606346d9a198e8db67114d158e97e33072bf737bc25sewardj         /* byte and/or/xor, then S --> (UInt)result[7] */
1607346d9a198e8db67114d158e97e33072bf737bc25sewardj         return binop(Iop_And64,
1608346d9a198e8db67114d158e97e33072bf737bc25sewardj                      binop(Iop_Shr64,cc_dep1,mkU8(7)),
1609346d9a198e8db67114d158e97e33072bf737bc25sewardj                      mkU64(1));
1610346d9a198e8db67114d158e97e33072bf737bc25sewardj      }
1611a6d08098f8291c52a2f08d70812805f9b47f6d7csewardj      if (isU64(cc_op, AMD64G_CC_OP_LOGICB) && isU64(cond, AMD64CondNS)) {
1612a6d08098f8291c52a2f08d70812805f9b47f6d7csewardj         /* byte and/or/xor, then NS --> (UInt)!result[7] */
1613a6d08098f8291c52a2f08d70812805f9b47f6d7csewardj         return binop(Iop_Xor64,
1614a6d08098f8291c52a2f08d70812805f9b47f6d7csewardj                      binop(Iop_And64,
1615a6d08098f8291c52a2f08d70812805f9b47f6d7csewardj                            binop(Iop_Shr64,cc_dep1,mkU8(7)),
1616a6d08098f8291c52a2f08d70812805f9b47f6d7csewardj                            mkU64(1)),
1617a6d08098f8291c52a2f08d70812805f9b47f6d7csewardj                      mkU64(1));
1618a6d08098f8291c52a2f08d70812805f9b47f6d7csewardj      }
1619346d9a198e8db67114d158e97e33072bf737bc25sewardj
16203f81c4e65a102d0c74857d221921d6d8882fdb33sewardj      /*---------------- INCB ----------------*/
16213f81c4e65a102d0c74857d221921d6d8882fdb33sewardj
16223f81c4e65a102d0c74857d221921d6d8882fdb33sewardj      if (isU64(cc_op, AMD64G_CC_OP_INCB) && isU64(cond, AMD64CondLE)) {
16234df975ffbe2c0aad9b64f547d84bde40c3c11171sewardj         /* 8-bit inc, then LE --> sign bit of the arg */
16244df975ffbe2c0aad9b64f547d84bde40c3c11171sewardj         return binop(Iop_And64,
16254df975ffbe2c0aad9b64f547d84bde40c3c11171sewardj                      binop(Iop_Shr64,
16264df975ffbe2c0aad9b64f547d84bde40c3c11171sewardj                            binop(Iop_Sub64, cc_dep1, mkU64(1)),
16274df975ffbe2c0aad9b64f547d84bde40c3c11171sewardj                            mkU8(7)),
16284df975ffbe2c0aad9b64f547d84bde40c3c11171sewardj                      mkU64(1));
16293f81c4e65a102d0c74857d221921d6d8882fdb33sewardj      }
16303f81c4e65a102d0c74857d221921d6d8882fdb33sewardj
16317784bd257254f55f4b5cebbcb70d5974fb12e808sewardj      /*---------------- INCW ----------------*/
16327784bd257254f55f4b5cebbcb70d5974fb12e808sewardj
16337784bd257254f55f4b5cebbcb70d5974fb12e808sewardj      if (isU64(cc_op, AMD64G_CC_OP_INCW) && isU64(cond, AMD64CondZ)) {
16347784bd257254f55f4b5cebbcb70d5974fb12e808sewardj         /* 16-bit inc, then Z --> test dst == 0 */
16357784bd257254f55f4b5cebbcb70d5974fb12e808sewardj         return unop(Iop_1Uto64,
16367784bd257254f55f4b5cebbcb70d5974fb12e808sewardj                     binop(Iop_CmpEQ64,
16377784bd257254f55f4b5cebbcb70d5974fb12e808sewardj                           binop(Iop_Shl64,cc_dep1,mkU8(48)),
16387784bd257254f55f4b5cebbcb70d5974fb12e808sewardj                           mkU64(0)));
16397784bd257254f55f4b5cebbcb70d5974fb12e808sewardj      }
16407784bd257254f55f4b5cebbcb70d5974fb12e808sewardj
164177fd8467f1c25c2873ece6e3328d8ebf3afebb12sewardj      /*---------------- DECL ----------------*/
164277fd8467f1c25c2873ece6e3328d8ebf3afebb12sewardj
164377fd8467f1c25c2873ece6e3328d8ebf3afebb12sewardj      if (isU64(cc_op, AMD64G_CC_OP_DECL) && isU64(cond, AMD64CondZ)) {
164477fd8467f1c25c2873ece6e3328d8ebf3afebb12sewardj         /* dec L, then Z --> test dst == 0 */
164577fd8467f1c25c2873ece6e3328d8ebf3afebb12sewardj         return unop(Iop_1Uto64,
16469cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj                     binop(Iop_CmpEQ32,
16479cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj                           unop(Iop_64to32, cc_dep1),
16489cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj                           mkU32(0)));
164977fd8467f1c25c2873ece6e3328d8ebf3afebb12sewardj      }
165077fd8467f1c25c2873ece6e3328d8ebf3afebb12sewardj
1651b6d02ea14a70600fda60851f1b12a81661bd5c24sewardj      /*---------------- DECW ----------------*/
1652b6d02ea14a70600fda60851f1b12a81661bd5c24sewardj
1653b6d02ea14a70600fda60851f1b12a81661bd5c24sewardj      if (isU64(cc_op, AMD64G_CC_OP_DECW) && isU64(cond, AMD64CondNZ)) {
1654b6d02ea14a70600fda60851f1b12a81661bd5c24sewardj         /* 16-bit dec, then NZ --> test dst != 0 */
1655b6d02ea14a70600fda60851f1b12a81661bd5c24sewardj         return unop(Iop_1Uto64,
1656b6d02ea14a70600fda60851f1b12a81661bd5c24sewardj                     binop(Iop_CmpNE64,
1657b6d02ea14a70600fda60851f1b12a81661bd5c24sewardj                           binop(Iop_Shl64,cc_dep1,mkU8(48)),
1658b6d02ea14a70600fda60851f1b12a81661bd5c24sewardj                           mkU64(0)));
1659b6d02ea14a70600fda60851f1b12a81661bd5c24sewardj      }
1660b6d02ea14a70600fda60851f1b12a81661bd5c24sewardj
1661ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes      /*---------------- SHRQ ----------------*/
1662ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes
1663ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes      if (isU64(cc_op, AMD64G_CC_OP_SHRQ) && isU64(cond, AMD64CondZ)) {
1664ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes         /* SHRQ, then Z --> test dep1 == 0 */
1665ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes         return unop(Iop_1Uto64,
1666ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes                     binop(Iop_CmpEQ64, cc_dep1, mkU64(0)));
1667ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes      }
1668ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes      if (isU64(cc_op, AMD64G_CC_OP_SHRQ) && isU64(cond, AMD64CondNZ)) {
1669ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes         /* SHRQ, then NZ --> test dep1 != 0 */
1670ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes         return unop(Iop_1Uto64,
1671ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes                     binop(Iop_CmpNE64, cc_dep1, mkU64(0)));
1672ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes      }
1673ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes
1674a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes      /*---------------- SHRL ----------------*/
1675a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes
1676a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes      if (isU64(cc_op, AMD64G_CC_OP_SHRL) && isU64(cond, AMD64CondZ)) {
1677a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes         /* SHRL, then Z --> test dep1 == 0 */
1678a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes         return unop(Iop_1Uto64,
1679a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes                     binop(Iop_CmpEQ32, unop(Iop_64to32, cc_dep1),
1680a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes                           mkU32(0)));
1681a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes      }
1682ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes      if (isU64(cc_op, AMD64G_CC_OP_SHRL) && isU64(cond, AMD64CondNZ)) {
1683ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes         /* SHRL, then NZ --> test dep1 != 0 */
1684ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes         return unop(Iop_1Uto64,
1685ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes                     binop(Iop_CmpNE32, unop(Iop_64to32, cc_dep1),
1686ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes                           mkU32(0)));
1687ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes      }
1688a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes
16897fc494b1b2abc210ee4b7a82d43f6a084a869022sewardj      /*---------------- COPY ----------------*/
16907fc494b1b2abc210ee4b7a82d43f6a084a869022sewardj      /* This can happen, as a result of amd64 FP compares: "comisd ... ;
16917fc494b1b2abc210ee4b7a82d43f6a084a869022sewardj         jbe" for example. */
16927fc494b1b2abc210ee4b7a82d43f6a084a869022sewardj
16937fc494b1b2abc210ee4b7a82d43f6a084a869022sewardj      if (isU64(cc_op, AMD64G_CC_OP_COPY) &&
16947fc494b1b2abc210ee4b7a82d43f6a084a869022sewardj          (isU64(cond, AMD64CondBE) || isU64(cond, AMD64CondNBE))) {
16957fc494b1b2abc210ee4b7a82d43f6a084a869022sewardj         /* COPY, then BE --> extract C and Z from dep1, and test (C
16967fc494b1b2abc210ee4b7a82d43f6a084a869022sewardj            or Z == 1). */
16977fc494b1b2abc210ee4b7a82d43f6a084a869022sewardj         /* COPY, then NBE --> extract C and Z from dep1, and test (C
16987fc494b1b2abc210ee4b7a82d43f6a084a869022sewardj            or Z == 0). */
16997fc494b1b2abc210ee4b7a82d43f6a084a869022sewardj         ULong nnn = isU64(cond, AMD64CondBE) ? 1 : 0;
17007fc494b1b2abc210ee4b7a82d43f6a084a869022sewardj         return
17017fc494b1b2abc210ee4b7a82d43f6a084a869022sewardj            unop(
17027fc494b1b2abc210ee4b7a82d43f6a084a869022sewardj               Iop_1Uto64,
17037fc494b1b2abc210ee4b7a82d43f6a084a869022sewardj               binop(
17047fc494b1b2abc210ee4b7a82d43f6a084a869022sewardj                  Iop_CmpEQ64,
17057fc494b1b2abc210ee4b7a82d43f6a084a869022sewardj                  binop(
17067fc494b1b2abc210ee4b7a82d43f6a084a869022sewardj                     Iop_And64,
17077fc494b1b2abc210ee4b7a82d43f6a084a869022sewardj                     binop(
17087fc494b1b2abc210ee4b7a82d43f6a084a869022sewardj                        Iop_Or64,
17097fc494b1b2abc210ee4b7a82d43f6a084a869022sewardj                        binop(Iop_Shr64, cc_dep1, mkU8(AMD64G_CC_SHIFT_C)),
17107fc494b1b2abc210ee4b7a82d43f6a084a869022sewardj                        binop(Iop_Shr64, cc_dep1, mkU8(AMD64G_CC_SHIFT_Z))
17117fc494b1b2abc210ee4b7a82d43f6a084a869022sewardj                     ),
17127fc494b1b2abc210ee4b7a82d43f6a084a869022sewardj                     mkU64(1)
17137fc494b1b2abc210ee4b7a82d43f6a084a869022sewardj                  ),
17147fc494b1b2abc210ee4b7a82d43f6a084a869022sewardj                  mkU64(nnn)
17157fc494b1b2abc210ee4b7a82d43f6a084a869022sewardj               )
17167fc494b1b2abc210ee4b7a82d43f6a084a869022sewardj            );
17177fc494b1b2abc210ee4b7a82d43f6a084a869022sewardj      }
17187fc494b1b2abc210ee4b7a82d43f6a084a869022sewardj
17199f05a64b6443485d0f9156ca75230c53381ce163sewardj      if (isU64(cc_op, AMD64G_CC_OP_COPY) && isU64(cond, AMD64CondB)) {
17209f05a64b6443485d0f9156ca75230c53381ce163sewardj         /* COPY, then B --> extract C dep1, and test (C == 1). */
17219f05a64b6443485d0f9156ca75230c53381ce163sewardj         return
17229f05a64b6443485d0f9156ca75230c53381ce163sewardj            unop(
17239f05a64b6443485d0f9156ca75230c53381ce163sewardj               Iop_1Uto64,
17249f05a64b6443485d0f9156ca75230c53381ce163sewardj               binop(
17259f05a64b6443485d0f9156ca75230c53381ce163sewardj                  Iop_CmpNE64,
17269f05a64b6443485d0f9156ca75230c53381ce163sewardj                  binop(
17279f05a64b6443485d0f9156ca75230c53381ce163sewardj                     Iop_And64,
17289f05a64b6443485d0f9156ca75230c53381ce163sewardj                     binop(Iop_Shr64, cc_dep1, mkU8(AMD64G_CC_SHIFT_C)),
17299f05a64b6443485d0f9156ca75230c53381ce163sewardj                     mkU64(1)
17309f05a64b6443485d0f9156ca75230c53381ce163sewardj                  ),
17319f05a64b6443485d0f9156ca75230c53381ce163sewardj                  mkU64(0)
17329f05a64b6443485d0f9156ca75230c53381ce163sewardj               )
17339f05a64b6443485d0f9156ca75230c53381ce163sewardj            );
17349f05a64b6443485d0f9156ca75230c53381ce163sewardj      }
17350354035b9222b1d6e37172ac2a70b19c816df025sewardj
1736b235e5b6613f6e4e00c0e50f2062d30cc99d9434sewardj      if (isU64(cc_op, AMD64G_CC_OP_COPY)
1737b235e5b6613f6e4e00c0e50f2062d30cc99d9434sewardj          && (isU64(cond, AMD64CondZ) || isU64(cond, AMD64CondNZ))) {
1738b235e5b6613f6e4e00c0e50f2062d30cc99d9434sewardj         /* COPY, then Z --> extract Z from dep1, and test (Z == 1). */
1739b235e5b6613f6e4e00c0e50f2062d30cc99d9434sewardj         /* COPY, then NZ --> extract Z from dep1, and test (Z == 0). */
1740b235e5b6613f6e4e00c0e50f2062d30cc99d9434sewardj         UInt nnn = isU64(cond, AMD64CondZ) ? 1 : 0;
1741b235e5b6613f6e4e00c0e50f2062d30cc99d9434sewardj         return
1742b235e5b6613f6e4e00c0e50f2062d30cc99d9434sewardj            unop(
1743b235e5b6613f6e4e00c0e50f2062d30cc99d9434sewardj               Iop_1Uto64,
1744b235e5b6613f6e4e00c0e50f2062d30cc99d9434sewardj               binop(
1745b235e5b6613f6e4e00c0e50f2062d30cc99d9434sewardj                  Iop_CmpEQ64,
1746b235e5b6613f6e4e00c0e50f2062d30cc99d9434sewardj                  binop(
1747b235e5b6613f6e4e00c0e50f2062d30cc99d9434sewardj                     Iop_And64,
1748b235e5b6613f6e4e00c0e50f2062d30cc99d9434sewardj                     binop(Iop_Shr64, cc_dep1, mkU8(AMD64G_CC_SHIFT_Z)),
1749b235e5b6613f6e4e00c0e50f2062d30cc99d9434sewardj                     mkU64(1)
1750b235e5b6613f6e4e00c0e50f2062d30cc99d9434sewardj                  ),
1751b235e5b6613f6e4e00c0e50f2062d30cc99d9434sewardj                  mkU64(nnn)
1752b235e5b6613f6e4e00c0e50f2062d30cc99d9434sewardj               )
1753b235e5b6613f6e4e00c0e50f2062d30cc99d9434sewardj            );
1754b235e5b6613f6e4e00c0e50f2062d30cc99d9434sewardj      }
1755b235e5b6613f6e4e00c0e50f2062d30cc99d9434sewardj
1756b235e5b6613f6e4e00c0e50f2062d30cc99d9434sewardj      if (isU64(cc_op, AMD64G_CC_OP_COPY) && isU64(cond, AMD64CondP)) {
1757b235e5b6613f6e4e00c0e50f2062d30cc99d9434sewardj         /* COPY, then P --> extract P from dep1, and test (P == 1). */
1758b235e5b6613f6e4e00c0e50f2062d30cc99d9434sewardj         return
1759b235e5b6613f6e4e00c0e50f2062d30cc99d9434sewardj            unop(
1760b235e5b6613f6e4e00c0e50f2062d30cc99d9434sewardj               Iop_1Uto64,
1761b235e5b6613f6e4e00c0e50f2062d30cc99d9434sewardj               binop(
1762b235e5b6613f6e4e00c0e50f2062d30cc99d9434sewardj                  Iop_CmpNE64,
1763b235e5b6613f6e4e00c0e50f2062d30cc99d9434sewardj                  binop(
1764b235e5b6613f6e4e00c0e50f2062d30cc99d9434sewardj                     Iop_And64,
1765b235e5b6613f6e4e00c0e50f2062d30cc99d9434sewardj                     binop(Iop_Shr64, cc_dep1, mkU8(AMD64G_CC_SHIFT_P)),
1766b235e5b6613f6e4e00c0e50f2062d30cc99d9434sewardj                     mkU64(1)
1767b235e5b6613f6e4e00c0e50f2062d30cc99d9434sewardj                  ),
1768b235e5b6613f6e4e00c0e50f2062d30cc99d9434sewardj                  mkU64(0)
1769b235e5b6613f6e4e00c0e50f2062d30cc99d9434sewardj               )
1770b235e5b6613f6e4e00c0e50f2062d30cc99d9434sewardj            );
1771b235e5b6613f6e4e00c0e50f2062d30cc99d9434sewardj      }
1772b235e5b6613f6e4e00c0e50f2062d30cc99d9434sewardj
17730354035b9222b1d6e37172ac2a70b19c816df025sewardj      return NULL;
17740354035b9222b1d6e37172ac2a70b19c816df025sewardj   }
17750354035b9222b1d6e37172ac2a70b19c816df025sewardj
17760354035b9222b1d6e37172ac2a70b19c816df025sewardj   /* --------- specialising "amd64g_calculate_rflags_c" --------- */
17770354035b9222b1d6e37172ac2a70b19c816df025sewardj
17780354035b9222b1d6e37172ac2a70b19c816df025sewardj   if (vex_streq(function_name, "amd64g_calculate_rflags_c")) {
17790354035b9222b1d6e37172ac2a70b19c816df025sewardj      /* specialise calls to above "calculate_rflags_c" function */
17800354035b9222b1d6e37172ac2a70b19c816df025sewardj      IRExpr *cc_op, *cc_dep1, *cc_dep2, *cc_ndep;
17810354035b9222b1d6e37172ac2a70b19c816df025sewardj      vassert(arity == 4);
17820354035b9222b1d6e37172ac2a70b19c816df025sewardj      cc_op   = args[0];
17830354035b9222b1d6e37172ac2a70b19c816df025sewardj      cc_dep1 = args[1];
17840354035b9222b1d6e37172ac2a70b19c816df025sewardj      cc_dep2 = args[2];
17850354035b9222b1d6e37172ac2a70b19c816df025sewardj      cc_ndep = args[3];
17860354035b9222b1d6e37172ac2a70b19c816df025sewardj
178777fd8467f1c25c2873ece6e3328d8ebf3afebb12sewardj      if (isU64(cc_op, AMD64G_CC_OP_SUBQ)) {
178877fd8467f1c25c2873ece6e3328d8ebf3afebb12sewardj         /* C after sub denotes unsigned less than */
178977fd8467f1c25c2873ece6e3328d8ebf3afebb12sewardj         return unop(Iop_1Uto64,
179077fd8467f1c25c2873ece6e3328d8ebf3afebb12sewardj                     binop(Iop_CmpLT64U,
179177fd8467f1c25c2873ece6e3328d8ebf3afebb12sewardj                           cc_dep1,
179277fd8467f1c25c2873ece6e3328d8ebf3afebb12sewardj                           cc_dep2));
179377fd8467f1c25c2873ece6e3328d8ebf3afebb12sewardj      }
17940354035b9222b1d6e37172ac2a70b19c816df025sewardj      if (isU64(cc_op, AMD64G_CC_OP_SUBL)) {
17950354035b9222b1d6e37172ac2a70b19c816df025sewardj         /* C after sub denotes unsigned less than */
17966d709a9a67687e446d25838deccd1698bfb3d273sewardj         return unop(Iop_1Uto64,
17979cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj                     binop(Iop_CmpLT32U,
17989cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj                           unop(Iop_64to32, cc_dep1),
17999cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj                           unop(Iop_64to32, cc_dep2)));
18000354035b9222b1d6e37172ac2a70b19c816df025sewardj      }
18010354035b9222b1d6e37172ac2a70b19c816df025sewardj      if (isU64(cc_op, AMD64G_CC_OP_SUBB)) {
18020354035b9222b1d6e37172ac2a70b19c816df025sewardj         /* C after sub denotes unsigned less than */
18036d709a9a67687e446d25838deccd1698bfb3d273sewardj         return unop(Iop_1Uto64,
18040354035b9222b1d6e37172ac2a70b19c816df025sewardj                     binop(Iop_CmpLT64U,
18050354035b9222b1d6e37172ac2a70b19c816df025sewardj                           binop(Iop_And64,cc_dep1,mkU64(0xFF)),
18066d709a9a67687e446d25838deccd1698bfb3d273sewardj                           binop(Iop_And64,cc_dep2,mkU64(0xFF))));
18070354035b9222b1d6e37172ac2a70b19c816df025sewardj      }
1808ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes      if (isU64(cc_op, AMD64G_CC_OP_ADDQ)) {
1809ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes         /* C after add denotes sum <u either arg */
1810ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes         return unop(Iop_1Uto64,
1811ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes                     binop(Iop_CmpLT64U,
1812ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes                           binop(Iop_Add64, cc_dep1, cc_dep2),
1813ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes                           cc_dep1));
1814ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes      }
1815ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes      if (isU64(cc_op, AMD64G_CC_OP_ADDL)) {
1816ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes         /* C after add denotes sum <u either arg */
1817ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes         return unop(Iop_1Uto64,
1818ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes                     binop(Iop_CmpLT32U,
1819ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes                           unop(Iop_64to32, binop(Iop_Add64, cc_dep1, cc_dep2)),
1820ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes                           unop(Iop_64to32, cc_dep1)));
1821ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes      }
18220354035b9222b1d6e37172ac2a70b19c816df025sewardj      if (isU64(cc_op, AMD64G_CC_OP_LOGICQ)
18230354035b9222b1d6e37172ac2a70b19c816df025sewardj          || isU64(cc_op, AMD64G_CC_OP_LOGICL)
18240354035b9222b1d6e37172ac2a70b19c816df025sewardj          || isU64(cc_op, AMD64G_CC_OP_LOGICW)
18250354035b9222b1d6e37172ac2a70b19c816df025sewardj          || isU64(cc_op, AMD64G_CC_OP_LOGICB)) {
18260354035b9222b1d6e37172ac2a70b19c816df025sewardj         /* cflag after logic is zero */
18270354035b9222b1d6e37172ac2a70b19c816df025sewardj         return mkU64(0);
18280354035b9222b1d6e37172ac2a70b19c816df025sewardj      }
18290354035b9222b1d6e37172ac2a70b19c816df025sewardj      if (isU64(cc_op, AMD64G_CC_OP_DECL) || isU64(cc_op, AMD64G_CC_OP_INCL)
18300354035b9222b1d6e37172ac2a70b19c816df025sewardj          || isU64(cc_op, AMD64G_CC_OP_DECQ) || isU64(cc_op, AMD64G_CC_OP_INCQ)) {
18310354035b9222b1d6e37172ac2a70b19c816df025sewardj         /* If the thunk is dec or inc, the cflag is supplied as CC_NDEP. */
18320354035b9222b1d6e37172ac2a70b19c816df025sewardj         return cc_ndep;
18330354035b9222b1d6e37172ac2a70b19c816df025sewardj      }
18347784bd257254f55f4b5cebbcb70d5974fb12e808sewardj
18357784bd257254f55f4b5cebbcb70d5974fb12e808sewardj#     if 0
18367784bd257254f55f4b5cebbcb70d5974fb12e808sewardj      if (cc_op->tag == Iex_Const) {
18377784bd257254f55f4b5cebbcb70d5974fb12e808sewardj         vex_printf("CFLAG "); ppIRExpr(cc_op); vex_printf("\n");
18387784bd257254f55f4b5cebbcb70d5974fb12e808sewardj      }
18397784bd257254f55f4b5cebbcb70d5974fb12e808sewardj#     endif
18400354035b9222b1d6e37172ac2a70b19c816df025sewardj
18410354035b9222b1d6e37172ac2a70b19c816df025sewardj      return NULL;
18420354035b9222b1d6e37172ac2a70b19c816df025sewardj   }
18430354035b9222b1d6e37172ac2a70b19c816df025sewardj
1844f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj#  undef unop
1845f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj#  undef binop
18460354035b9222b1d6e37172ac2a70b19c816df025sewardj#  undef mkU64
18479cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj#  undef mkU32
1848f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj#  undef mkU8
1849f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
1850f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   return NULL;
1851f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj}
1852f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
1853f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
18548d965316c72c2392f670dcdfa127547ec77c7e56sewardj/*---------------------------------------------------------------*/
18558d965316c72c2392f670dcdfa127547ec77c7e56sewardj/*--- Supporting functions for x87 FPU activities.            ---*/
18568d965316c72c2392f670dcdfa127547ec77c7e56sewardj/*---------------------------------------------------------------*/
18578d965316c72c2392f670dcdfa127547ec77c7e56sewardj
18584f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardjstatic inline Bool host_is_little_endian ( void )
18594f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj{
18604f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj   UInt x = 0x76543210;
18614f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj   UChar* p = (UChar*)(&x);
18624f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj   return toBool(*p == 0x10);
18634f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj}
18644f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj
18654f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj/* Inspect a value and its tag, as per the x87 'FXAM' instruction. */
18664f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
18674f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardjULong amd64g_calculate_FXAM ( ULong tag, ULong dbl )
18684f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj{
18694f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj   Bool   mantissaIsZero;
18704f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj   Int    bexp;
18714f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj   UChar  sign;
18724f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj   UChar* f64;
18734f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj
18744f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj   vassert(host_is_little_endian());
18754f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj
18764f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj   /* vex_printf("calculate_FXAM ( %d, %llx ) .. ", tag, dbl ); */
18774f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj
18784f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj   f64  = (UChar*)(&dbl);
18794f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj   sign = toUChar( (f64[7] >> 7) & 1 );
18804f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj
18814f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj   /* First off, if the tag indicates the register was empty,
18824f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj      return 1,0,sign,1 */
18834f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj   if (tag == 0) {
18844f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj      /* vex_printf("Empty\n"); */
18854f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj      return AMD64G_FC_MASK_C3 | 0 | (sign << AMD64G_FC_SHIFT_C1)
18864f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj                                   | AMD64G_FC_MASK_C0;
18874f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj   }
18884f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj
18894f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj   bexp = (f64[7] << 4) | ((f64[6] >> 4) & 0x0F);
18904f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj   bexp &= 0x7FF;
18914f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj
18924f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj   mantissaIsZero
18934f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj      = toBool(
18944f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj           (f64[6] & 0x0F) == 0
18954f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj           && (f64[5] | f64[4] | f64[3] | f64[2] | f64[1] | f64[0]) == 0
18964f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj        );
18974f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj
18984f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj   /* If both exponent and mantissa are zero, the value is zero.
18994f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj      Return 1,0,sign,0. */
19004f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj   if (bexp == 0 && mantissaIsZero) {
19014f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj      /* vex_printf("Zero\n"); */
19024f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj      return AMD64G_FC_MASK_C3 | 0
19034f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj                               | (sign << AMD64G_FC_SHIFT_C1) | 0;
19044f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj   }
19054f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj
19064f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj   /* If exponent is zero but mantissa isn't, it's a denormal.
19074f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj      Return 1,1,sign,0. */
19084f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj   if (bexp == 0 && !mantissaIsZero) {
19094f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj      /* vex_printf("Denormal\n"); */
19104f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj      return AMD64G_FC_MASK_C3 | AMD64G_FC_MASK_C2
19114f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj                               | (sign << AMD64G_FC_SHIFT_C1) | 0;
19124f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj   }
19134f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj
19144f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj   /* If the exponent is 7FF and the mantissa is zero, this is an infinity.
19154f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj      Return 0,1,sign,1. */
19164f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj   if (bexp == 0x7FF && mantissaIsZero) {
19174f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj      /* vex_printf("Inf\n"); */
19184f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj      return 0 | AMD64G_FC_MASK_C2 | (sign << AMD64G_FC_SHIFT_C1)
19194f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj                                   | AMD64G_FC_MASK_C0;
19204f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj   }
19214f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj
19224f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj   /* If the exponent is 7FF and the mantissa isn't zero, this is a NaN.
19234f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj      Return 0,0,sign,1. */
19244f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj   if (bexp == 0x7FF && !mantissaIsZero) {
19254f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj      /* vex_printf("NaN\n"); */
19264f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj      return 0 | 0 | (sign << AMD64G_FC_SHIFT_C1) | AMD64G_FC_MASK_C0;
19274f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj   }
19284f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj
19294f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj   /* Uh, ok, we give up.  It must be a normal finite number.
19304f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj      Return 0,1,sign,0.
19314f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj   */
19324f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj   /* vex_printf("normal\n"); */
19334f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj   return 0 | AMD64G_FC_MASK_C2 | (sign << AMD64G_FC_SHIFT_C1) | 0;
19344f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj}
19354f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj
19364f9847ddc664dd58bd9e4dbcd0626747d142cd06sewardj
19375556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj/* This is used to implement both 'frstor' and 'fldenv'.  The latter
19385556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj   appears to differ from the former only in that the 8 FP registers
19395556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj   themselves are not transferred into the guest state. */
19405556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardjstatic
19416ef84bed9bb3af22060eb1759788034602bbcc88florianVexEmNote do_put_x87 ( Bool moveRegs,
1942ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes                       /*IN*/Fpu_State* x87_state,
19435556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj                       /*OUT*/VexGuestAMD64State* vex_state )
19445556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj{
19455556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj   Int        stno, preg;
19465556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj   UInt       tag;
19475556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj   ULong*     vexRegs = (ULong*)(&vex_state->guest_FPREG[0]);
19485556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj   UChar*     vexTags = (UChar*)(&vex_state->guest_FPTAG[0]);
1949ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes   UInt       ftop    = (x87_state->env[FP_ENV_STAT] >> 11) & 7;
1950ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes   UInt       tagw    = x87_state->env[FP_ENV_TAG];
1951ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes   UInt       fpucw   = x87_state->env[FP_ENV_CTRL];
1952ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes   UInt       c3210   = x87_state->env[FP_ENV_STAT] & 0x4700;
19536ef84bed9bb3af22060eb1759788034602bbcc88florian   VexEmNote  ew;
19545556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj   UInt       fpround;
19555556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj   ULong      pair;
19565556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj
19575556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj   /* Copy registers and tags */
19585556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj   for (stno = 0; stno < 8; stno++) {
19595556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj      preg = (stno + ftop) & 7;
19605556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj      tag = (tagw >> (2*preg)) & 3;
19615556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj      if (tag == 3) {
19625556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj         /* register is empty */
19635556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj         /* hmm, if it's empty, does it still get written?  Probably
19645556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj            safer to say it does.  If we don't, memcheck could get out
19655556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj            of sync, in that it thinks all FP registers are defined by
19665556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj            this helper, but in reality some have not been updated. */
19675556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj         if (moveRegs)
19685556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj            vexRegs[preg] = 0; /* IEEE754 64-bit zero */
19695556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj         vexTags[preg] = 0;
19705556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj      } else {
19715556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj         /* register is non-empty */
19725556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj         if (moveRegs)
1973ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes            convert_f80le_to_f64le( &x87_state->reg[10*stno],
19745556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj                                    (UChar*)&vexRegs[preg] );
19755556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj         vexTags[preg] = 1;
19765556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj      }
19775556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj   }
19785556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj
19795556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj   /* stack pointer */
19805556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj   vex_state->guest_FTOP = ftop;
19815556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj
19825556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj   /* status word */
19835556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj   vex_state->guest_FC3210 = c3210;
19845556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj
19855556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj   /* handle the control word, setting FPROUND and detecting any
19865556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj      emulation warnings. */
19875556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj   pair    = amd64g_check_fldcw ( (ULong)fpucw );
19889ae42a77adfcd9fef928bef3439da258b6e6f748sewardj   fpround = (UInt)pair & 0xFFFFFFFFULL;
19896ef84bed9bb3af22060eb1759788034602bbcc88florian   ew      = (VexEmNote)(pair >> 32);
19905556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj
19915556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj   vex_state->guest_FPROUND = fpround & 3;
19925556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj
19935556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj   /* emulation warnings --> caller */
19945556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj   return ew;
19955556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj}
19965556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj
19975556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj
19985abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj/* Create an x87 FPU state from the guest state, as close as
19995abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj   we can approximate it. */
20005abcfe66bd59f67b474d0d9e4b70b852213dd910sewardjstatic
20015abcfe66bd59f67b474d0d9e4b70b852213dd910sewardjvoid do_get_x87 ( /*IN*/VexGuestAMD64State* vex_state,
2002ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes                  /*OUT*/Fpu_State* x87_state )
20035abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj{
20045abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj   Int        i, stno, preg;
20055abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj   UInt       tagw;
20065abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj   ULong*     vexRegs = (ULong*)(&vex_state->guest_FPREG[0]);
20075abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj   UChar*     vexTags = (UChar*)(&vex_state->guest_FPTAG[0]);
20085abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj   UInt       ftop    = vex_state->guest_FTOP;
20095abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj   UInt       c3210   = vex_state->guest_FC3210;
20105abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj
20115abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj   for (i = 0; i < 14; i++)
2012ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes      x87_state->env[i] = 0;
20135abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj
2014ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes   x87_state->env[1] = x87_state->env[3] = x87_state->env[5]
2015ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes      = x87_state->env[13] = 0xFFFF;
2016ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes   x87_state->env[FP_ENV_STAT]
20175abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj      = toUShort(((ftop & 7) << 11) | (c3210 & 0x4700));
2018ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes   x87_state->env[FP_ENV_CTRL]
20195abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj      = toUShort(amd64g_create_fpucw( vex_state->guest_FPROUND ));
20205abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj
20215abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj   /* Dump the register stack in ST order. */
20225abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj   tagw = 0;
20235abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj   for (stno = 0; stno < 8; stno++) {
20245abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj      preg = (stno + ftop) & 7;
20255abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj      if (vexTags[preg] == 0) {
20265abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj         /* register is empty */
20275abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj         tagw |= (3 << (2*preg));
20285abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj         convert_f64le_to_f80le( (UChar*)&vexRegs[preg],
2029ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes                                 &x87_state->reg[10*stno] );
20305abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj      } else {
20315abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj         /* register is full. */
20325abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj         tagw |= (0 << (2*preg));
20335abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj         convert_f64le_to_f80le( (UChar*)&vexRegs[preg],
2034ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes                                 &x87_state->reg[10*stno] );
20355abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj      }
20365abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj   }
2037ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes   x87_state->env[FP_ENV_TAG] = toUShort(tagw);
20385abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj}
20395abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj
20405abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj
204170dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj/*---------------------------------------------------------------*/
204270dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj/*--- Supporting functions for XSAVE/FXSAVE.                  ---*/
204370dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj/*---------------------------------------------------------------*/
204470dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj
204570dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj/* CALLED FROM GENERATED CODE */
204670dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj/* DIRTY HELPER (reads guest state, writes guest mem) */
204770dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj/* XSAVE component 0 is the x87 FPU state. */
204870dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardjvoid amd64g_dirtyhelper_XSAVE_COMPONENT_0
204970dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj        ( VexGuestAMD64State* gst, HWord addr )
20505abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj{
20515abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj   /* Derived from values obtained from
20525abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj      vendor_id       : AuthenticAMD
20535abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj      cpu family      : 15
20545abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj      model           : 12
20555abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj      model name      : AMD Athlon(tm) 64 Processor 3200+
20565abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj      stepping        : 0
20575abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj      cpu MHz         : 2200.000
20585abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj      cache size      : 512 KB
20595abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj   */
20605abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj   /* Somewhat roundabout, but at least it's simple. */
20615abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj   Fpu_State tmp;
20625abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj   UShort*   addrS = (UShort*)addr;
20635abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj   UChar*    addrC = (UChar*)addr;
20645abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj   UShort    fp_tags;
20655abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj   UInt      summary_tags;
20665abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj   Int       r, stno;
20675abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj   UShort    *srcS, *dstS;
20685abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj
2069ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes   do_get_x87( gst, &tmp );
20705abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj
207170dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   /* Now build the proper fxsave x87 image from the fsave x87 image
207270dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      we just made. */
20735abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj
20745abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj   addrS[0]  = tmp.env[FP_ENV_CTRL]; /* FCW: fpu control word */
20755abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj   addrS[1]  = tmp.env[FP_ENV_STAT]; /* FCW: fpu status word */
20765abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj
20775abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj   /* set addrS[2] in an endian-independent way */
20785abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj   summary_tags = 0;
20795abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj   fp_tags = tmp.env[FP_ENV_TAG];
20805abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj   for (r = 0; r < 8; r++) {
20815abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj      if ( ((fp_tags >> (2*r)) & 3) != 3 )
20825abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj         summary_tags |= (1 << r);
20835abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj   }
20845abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj   addrC[4]  = toUChar(summary_tags); /* FTW: tag summary byte */
20855abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj   addrC[5]  = 0; /* pad */
20865abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj
20875abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj   /* FOP: faulting fpu opcode.  From experimentation, the real CPU
20885abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj      does not write this field. (?!) */
20895abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj   addrS[3]  = 0; /* BOGUS */
20905abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj
20915abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj   /* RIP (Last x87 instruction pointer).  From experimentation, the
20925abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj      real CPU does not write this field. (?!) */
20935abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj   addrS[4]  = 0; /* BOGUS */
20945abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj   addrS[5]  = 0; /* BOGUS */
20955abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj   addrS[6]  = 0; /* BOGUS */
20965abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj   addrS[7]  = 0; /* BOGUS */
20975abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj
20985abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj   /* RDP (Last x87 data pointer).  From experimentation, the real CPU
20995abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj      does not write this field. (?!) */
21005abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj   addrS[8]  = 0; /* BOGUS */
21015abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj   addrS[9]  = 0; /* BOGUS */
21025abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj   addrS[10] = 0; /* BOGUS */
21035abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj   addrS[11] = 0; /* BOGUS */
21045abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj
210570dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   /* addrS[13,12] are MXCSR -- not written */
210670dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   /* addrS[15,14] are MXCSR_MASK -- not written */
21075abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj
21085abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj   /* Copy in the FP registers, in ST order. */
21095abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj   for (stno = 0; stno < 8; stno++) {
21105abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj      srcS = (UShort*)(&tmp.reg[10*stno]);
21115abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj      dstS = (UShort*)(&addrS[16 + 8*stno]);
21125abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj      dstS[0] = srcS[0];
21135abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj      dstS[1] = srcS[1];
21145abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj      dstS[2] = srcS[2];
21155abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj      dstS[3] = srcS[3];
21165abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj      dstS[4] = srcS[4];
21175abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj      dstS[5] = 0;
21185abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj      dstS[6] = 0;
21195abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj      dstS[7] = 0;
21205abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj   }
212170dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj}
212270dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj
212370dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj
212470dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj/* CALLED FROM GENERATED CODE */
212570dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj/* DIRTY HELPER (reads guest state, writes guest mem) */
212670dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj/* XSAVE component 1 is the SSE state. */
212770dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardjvoid amd64g_dirtyhelper_XSAVE_COMPONENT_1_EXCLUDING_XMMREGS
212870dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj        ( VexGuestAMD64State* gst, HWord addr )
212970dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj{
213070dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   UShort* addrS = (UShort*)addr;
213170dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   UInt    mxcsr;
213270dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj
213370dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   /* The only non-register parts of the SSE state are MXCSR and
213470dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      MXCSR_MASK. */
213570dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   mxcsr = amd64g_create_mxcsr( gst->guest_SSEROUND );
213670dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj
213770dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   addrS[12] = toUShort(mxcsr);  /* MXCSR */
213870dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   addrS[13] = toUShort(mxcsr >> 16);
213970dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj
214070dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   addrS[14] = 0xFFFF; /* MXCSR mask (lo16) */
214170dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   addrS[15] = 0x0000; /* MXCSR mask (hi16) */
214270dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj}
214370dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj
214470dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj
214570dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj/* VISIBLE TO LIBVEX CLIENT */
214670dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj/* Do FXSAVE from the supplied VexGuestAMD64State structure and store
214770dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   the result at the given address which represents a buffer of at
214870dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   least 416 bytes.
214970dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj
215070dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   This function is not called from generated code.  FXSAVE is dealt
215170dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   with by the amd64 front end by calling the XSAVE_COMPONENT_{0,1}
215270dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   functions above plus some in-line IR.  This function is merely a
215370dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   convenience function for VEX's users.
215470dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj*/
215570dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardjvoid LibVEX_GuestAMD64_fxsave ( /*IN*/VexGuestAMD64State* gst,
215670dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj                                /*OUT*/HWord fp_state )
215770dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj{
215870dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   /* Do the x87 part */
215970dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   amd64g_dirtyhelper_XSAVE_COMPONENT_0(gst, fp_state);
216070dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj
216170dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   /* And now the SSE part, except for the registers themselves. */
216270dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   amd64g_dirtyhelper_XSAVE_COMPONENT_1_EXCLUDING_XMMREGS(gst, fp_state);
21635abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj
21643e5d82d003f0746010e22c7cfc4a25b34c9641f1sewardj   /* That's the first 160 bytes of the image done. */
216570dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   /* Now only %xmm0 .. %xmm15 remain to be copied.  If the host is
216670dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      big-endian, these need to be byte-swapped. */
216770dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   U128 *xmm = (U128 *)(fp_state + 160);
216870dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   vassert(host_is_little_endian());
216970dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj
217070dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj#  define COPY_U128(_dst,_src)                       \
217170dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      do { _dst[0] = _src[0]; _dst[1] = _src[1];     \
217270dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj           _dst[2] = _src[2]; _dst[3] = _src[3]; }   \
217370dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      while (0)
217470dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj
217570dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   COPY_U128( xmm[0],  gst->guest_YMM0 );
217670dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   COPY_U128( xmm[1],  gst->guest_YMM1 );
217770dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   COPY_U128( xmm[2],  gst->guest_YMM2 );
217870dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   COPY_U128( xmm[3],  gst->guest_YMM3 );
217970dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   COPY_U128( xmm[4],  gst->guest_YMM4 );
218070dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   COPY_U128( xmm[5],  gst->guest_YMM5 );
218170dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   COPY_U128( xmm[6],  gst->guest_YMM6 );
218270dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   COPY_U128( xmm[7],  gst->guest_YMM7 );
218370dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   COPY_U128( xmm[8],  gst->guest_YMM8 );
218470dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   COPY_U128( xmm[9],  gst->guest_YMM9 );
218570dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   COPY_U128( xmm[10], gst->guest_YMM10 );
218670dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   COPY_U128( xmm[11], gst->guest_YMM11 );
218770dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   COPY_U128( xmm[12], gst->guest_YMM12 );
218870dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   COPY_U128( xmm[13], gst->guest_YMM13 );
218970dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   COPY_U128( xmm[14], gst->guest_YMM14 );
219070dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   COPY_U128( xmm[15], gst->guest_YMM15 );
21913e5d82d003f0746010e22c7cfc4a25b34c9641f1sewardj#  undef COPY_U128
21925abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj}
21935abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj
21945abcfe66bd59f67b474d0d9e4b70b852213dd910sewardj
219570dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj/*---------------------------------------------------------------*/
219670dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj/*--- Supporting functions for XRSTOR/FXRSTOR.                ---*/
219770dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj/*---------------------------------------------------------------*/
219870dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj
219970dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj/* CALLED FROM GENERATED CODE */
220070dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj/* DIRTY HELPER (writes guest state, reads guest mem) */
220170dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardjVexEmNote amd64g_dirtyhelper_XRSTOR_COMPONENT_0
220270dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj             ( VexGuestAMD64State* gst, HWord addr )
22035556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj{
22045556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj   Fpu_State tmp;
22055556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj   UShort*   addrS   = (UShort*)addr;
22065556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj   UChar*    addrC   = (UChar*)addr;
22075556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj   UShort    fp_tags;
22085556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj   Int       r, stno, i;
22095556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj
22105556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj   /* Copy the x87 registers out of the image, into a temporary
22115556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj      Fpu_State struct. */
22125556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj   for (i = 0; i < 14; i++) tmp.env[i] = 0;
22135556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj   for (i = 0; i < 80; i++) tmp.reg[i] = 0;
22145556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj   /* fill in tmp.reg[0..7] */
22155556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj   for (stno = 0; stno < 8; stno++) {
22165556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj      UShort* dstS = (UShort*)(&tmp.reg[10*stno]);
22175556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj      UShort* srcS = (UShort*)(&addrS[16 + 8*stno]);
22185556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj      dstS[0] = srcS[0];
22195556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj      dstS[1] = srcS[1];
22205556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj      dstS[2] = srcS[2];
22215556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj      dstS[3] = srcS[3];
22225556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj      dstS[4] = srcS[4];
22235556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj   }
22245556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj   /* fill in tmp.env[0..13] */
22255556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj   tmp.env[FP_ENV_CTRL] = addrS[0]; /* FCW: fpu control word */
22265556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj   tmp.env[FP_ENV_STAT] = addrS[1]; /* FCW: fpu status word */
22275556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj
22285556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj   fp_tags = 0;
22295556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj   for (r = 0; r < 8; r++) {
22305556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj      if (addrC[4] & (1<<r))
22315556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj         fp_tags |= (0 << (2*r)); /* EMPTY */
22325556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj      else
22335556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj         fp_tags |= (3 << (2*r)); /* VALID -- not really precise enough. */
22345556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj   }
22355556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj   tmp.env[FP_ENV_TAG] = fp_tags;
22365556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj
22375556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj   /* Now write 'tmp' into the guest state. */
2238ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes   VexEmNote warnX87 = do_put_x87( True/*moveRegs*/, &tmp, gst );
22395556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj
224070dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   return warnX87;
224170dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj}
22425556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj
22435556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj
224470dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj/* CALLED FROM GENERATED CODE */
224570dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj/* DIRTY HELPER (writes guest state, reads guest mem) */
224670dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardjVexEmNote amd64g_dirtyhelper_XRSTOR_COMPONENT_1_EXCLUDING_XMMREGS
224770dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj             ( VexGuestAMD64State* gst, HWord addr )
224870dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj{
224970dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   UShort* addrS = (UShort*)addr;
225070dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   UInt    w32   = (((UInt)addrS[12]) & 0xFFFF)
225170dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj                   | ((((UInt)addrS[13]) & 0xFFFF) << 16);
225270dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   ULong   w64   = amd64g_check_ldmxcsr( (ULong)w32 );
225370dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj
225470dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   VexEmNote warnXMM = (VexEmNote)(w64 >> 32);
225570dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj
225670dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   gst->guest_SSEROUND = w64 & 0xFFFFFFFFULL;
225770dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   return warnXMM;
225870dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj}
225970dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj
226070dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj
226170dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj/* VISIBLE TO LIBVEX CLIENT */
226270dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj/* Do FXRSTOR from the supplied address and store read values to the given
226370dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   VexGuestAMD64State structure.
226470dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj
226570dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   This function is not called from generated code.  FXRSTOR is dealt
226670dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   with by the amd64 front end by calling the XRSTOR_COMPONENT_{0,1}
226770dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   functions above plus some in-line IR.  This function is merely a
226870dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   convenience function for VEX's users.
226970dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj*/
227070dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardjVexEmNote LibVEX_GuestAMD64_fxrstor ( /*IN*/HWord fp_state,
227170dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj                                      /*MOD*/VexGuestAMD64State* gst )
227270dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj{
227370dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   /* Restore %xmm0 .. %xmm15.  If the host is big-endian, these need
227470dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      to be byte-swapped. */
227570dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   U128 *xmm = (U128 *)(fp_state + 160);
227670dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj
227770dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   vassert(host_is_little_endian());
227870dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj
227970dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj#  define COPY_U128(_dst,_src)                       \
228070dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      do { _dst[0] = _src[0]; _dst[1] = _src[1];     \
228170dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj           _dst[2] = _src[2]; _dst[3] = _src[3]; }   \
228270dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      while (0)
228370dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj
228470dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   COPY_U128( gst->guest_YMM0, xmm[0] );
228570dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   COPY_U128( gst->guest_YMM1, xmm[1] );
228670dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   COPY_U128( gst->guest_YMM2, xmm[2] );
228770dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   COPY_U128( gst->guest_YMM3, xmm[3] );
228870dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   COPY_U128( gst->guest_YMM4, xmm[4] );
228970dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   COPY_U128( gst->guest_YMM5, xmm[5] );
229070dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   COPY_U128( gst->guest_YMM6, xmm[6] );
229170dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   COPY_U128( gst->guest_YMM7, xmm[7] );
229270dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   COPY_U128( gst->guest_YMM8, xmm[8] );
229370dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   COPY_U128( gst->guest_YMM9, xmm[9] );
229470dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   COPY_U128( gst->guest_YMM10, xmm[10] );
229570dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   COPY_U128( gst->guest_YMM11, xmm[11] );
229670dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   COPY_U128( gst->guest_YMM12, xmm[12] );
229770dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   COPY_U128( gst->guest_YMM13, xmm[13] );
229870dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   COPY_U128( gst->guest_YMM14, xmm[14] );
229970dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   COPY_U128( gst->guest_YMM15, xmm[15] );
230070dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj
230170dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj#  undef COPY_U128
230270dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj
230370dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   VexEmNote warnXMM
230470dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      = amd64g_dirtyhelper_XRSTOR_COMPONENT_1_EXCLUDING_XMMREGS(gst, fp_state);
230570dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   VexEmNote warnX87
230670dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      = amd64g_dirtyhelper_XRSTOR_COMPONENT_0(gst, fp_state);
23075556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj
23085556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj   /* Prefer an X87 emwarn over an XMM one, if both exist. */
23096ef84bed9bb3af22060eb1759788034602bbcc88florian   if (warnX87 != EmNote_NONE)
23105556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj      return warnX87;
23115556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj   else
23125556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj      return warnXMM;
23135556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj}
23145556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj
23155556e5e2c77b722c233e3e49f915fa8c0aeba5b2sewardj
231670dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj/*---------------------------------------------------------------*/
231770dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj/*--- Supporting functions for FSAVE/FRSTOR                   ---*/
231870dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj/*---------------------------------------------------------------*/
23193e5d82d003f0746010e22c7cfc4a25b34c9641f1sewardj
23200585a03e90a5e6350a09e44528147e531bd77092sewardj/* DIRTY HELPER (writes guest state) */
23218d965316c72c2392f670dcdfa127547ec77c7e56sewardj/* Initialise the x87 FPU state as per 'finit'. */
23228d965316c72c2392f670dcdfa127547ec77c7e56sewardjvoid amd64g_dirtyhelper_FINIT ( VexGuestAMD64State* gst )
23238d965316c72c2392f670dcdfa127547ec77c7e56sewardj{
23248d965316c72c2392f670dcdfa127547ec77c7e56sewardj   Int i;
23258d965316c72c2392f670dcdfa127547ec77c7e56sewardj   gst->guest_FTOP = 0;
23268d965316c72c2392f670dcdfa127547ec77c7e56sewardj   for (i = 0; i < 8; i++) {
23278d965316c72c2392f670dcdfa127547ec77c7e56sewardj      gst->guest_FPTAG[i] = 0; /* empty */
23288d965316c72c2392f670dcdfa127547ec77c7e56sewardj      gst->guest_FPREG[i] = 0; /* IEEE754 64-bit zero */
23298d965316c72c2392f670dcdfa127547ec77c7e56sewardj   }
23308d965316c72c2392f670dcdfa127547ec77c7e56sewardj   gst->guest_FPROUND = (ULong)Irrm_NEAREST;
23318d965316c72c2392f670dcdfa127547ec77c7e56sewardj   gst->guest_FC3210  = 0;
23328d965316c72c2392f670dcdfa127547ec77c7e56sewardj}
23338d965316c72c2392f670dcdfa127547ec77c7e56sewardj
2334d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj
2335924215b14b9a8391f992b419220ffaa0b2e49ea7sewardj/* CALLED FROM GENERATED CODE */
2336924215b14b9a8391f992b419220ffaa0b2e49ea7sewardj/* DIRTY HELPER (reads guest memory) */
2337bdf99f06a5f44fd617c51ac80861ff07da09a50fflorianULong amd64g_dirtyhelper_loadF80le ( Addr addrU )
2338924215b14b9a8391f992b419220ffaa0b2e49ea7sewardj{
2339924215b14b9a8391f992b419220ffaa0b2e49ea7sewardj   ULong f64;
2340bdf99f06a5f44fd617c51ac80861ff07da09a50fflorian   convert_f80le_to_f64le ( (UChar*)addrU, (UChar*)&f64 );
2341924215b14b9a8391f992b419220ffaa0b2e49ea7sewardj   return f64;
2342924215b14b9a8391f992b419220ffaa0b2e49ea7sewardj}
2343924215b14b9a8391f992b419220ffaa0b2e49ea7sewardj
2344924215b14b9a8391f992b419220ffaa0b2e49ea7sewardj/* CALLED FROM GENERATED CODE */
2345924215b14b9a8391f992b419220ffaa0b2e49ea7sewardj/* DIRTY HELPER (writes guest memory) */
2346bdf99f06a5f44fd617c51ac80861ff07da09a50fflorianvoid amd64g_dirtyhelper_storeF80le ( Addr addrU, ULong f64 )
2347924215b14b9a8391f992b419220ffaa0b2e49ea7sewardj{
2348bdf99f06a5f44fd617c51ac80861ff07da09a50fflorian   convert_f64le_to_f80le( (UChar*)&f64, (UChar*)addrU );
2349924215b14b9a8391f992b419220ffaa0b2e49ea7sewardj}
2350924215b14b9a8391f992b419220ffaa0b2e49ea7sewardj
2351924215b14b9a8391f992b419220ffaa0b2e49ea7sewardj
2352bcbb9de4726dfe62898f83578e4ec8099b710734sewardj/* CALLED FROM GENERATED CODE */
2353bcbb9de4726dfe62898f83578e4ec8099b710734sewardj/* CLEAN HELPER */
2354bcbb9de4726dfe62898f83578e4ec8099b710734sewardj/* mxcsr[15:0] contains a SSE native format MXCSR value.
2355bcbb9de4726dfe62898f83578e4ec8099b710734sewardj   Extract from it the required SSEROUND value and any resulting
2356bcbb9de4726dfe62898f83578e4ec8099b710734sewardj   emulation warning, and return (warn << 32) | sseround value.
2357bcbb9de4726dfe62898f83578e4ec8099b710734sewardj*/
2358bcbb9de4726dfe62898f83578e4ec8099b710734sewardjULong amd64g_check_ldmxcsr ( ULong mxcsr )
2359bcbb9de4726dfe62898f83578e4ec8099b710734sewardj{
2360bcbb9de4726dfe62898f83578e4ec8099b710734sewardj   /* Decide on a rounding mode.  mxcsr[14:13] holds it. */
2361bcbb9de4726dfe62898f83578e4ec8099b710734sewardj   /* NOTE, encoded exactly as per enum IRRoundingMode. */
2362bcbb9de4726dfe62898f83578e4ec8099b710734sewardj   ULong rmode = (mxcsr >> 13) & 3;
2363bcbb9de4726dfe62898f83578e4ec8099b710734sewardj
2364bcbb9de4726dfe62898f83578e4ec8099b710734sewardj   /* Detect any required emulation warnings. */
23656ef84bed9bb3af22060eb1759788034602bbcc88florian   VexEmNote ew = EmNote_NONE;
2366bcbb9de4726dfe62898f83578e4ec8099b710734sewardj
2367bcbb9de4726dfe62898f83578e4ec8099b710734sewardj   if ((mxcsr & 0x1F80) != 0x1F80) {
2368bcbb9de4726dfe62898f83578e4ec8099b710734sewardj      /* unmasked exceptions! */
2369bcbb9de4726dfe62898f83578e4ec8099b710734sewardj      ew = EmWarn_X86_sseExns;
2370bcbb9de4726dfe62898f83578e4ec8099b710734sewardj   }
2371bcbb9de4726dfe62898f83578e4ec8099b710734sewardj   else
2372bcbb9de4726dfe62898f83578e4ec8099b710734sewardj   if (mxcsr & (1<<15)) {
2373bcbb9de4726dfe62898f83578e4ec8099b710734sewardj      /* FZ is set */
2374bcbb9de4726dfe62898f83578e4ec8099b710734sewardj      ew = EmWarn_X86_fz;
2375bcbb9de4726dfe62898f83578e4ec8099b710734sewardj   }
2376bcbb9de4726dfe62898f83578e4ec8099b710734sewardj   else
2377bcbb9de4726dfe62898f83578e4ec8099b710734sewardj   if (mxcsr & (1<<6)) {
2378bcbb9de4726dfe62898f83578e4ec8099b710734sewardj      /* DAZ is set */
2379bcbb9de4726dfe62898f83578e4ec8099b710734sewardj      ew = EmWarn_X86_daz;
2380bcbb9de4726dfe62898f83578e4ec8099b710734sewardj   }
2381bcbb9de4726dfe62898f83578e4ec8099b710734sewardj
2382bcbb9de4726dfe62898f83578e4ec8099b710734sewardj   return (((ULong)ew) << 32) | ((ULong)rmode);
2383bcbb9de4726dfe62898f83578e4ec8099b710734sewardj}
2384bcbb9de4726dfe62898f83578e4ec8099b710734sewardj
2385bcbb9de4726dfe62898f83578e4ec8099b710734sewardj
2386bcbb9de4726dfe62898f83578e4ec8099b710734sewardj/* CALLED FROM GENERATED CODE */
2387bcbb9de4726dfe62898f83578e4ec8099b710734sewardj/* CLEAN HELPER */
2388bcbb9de4726dfe62898f83578e4ec8099b710734sewardj/* Given sseround as an IRRoundingMode value, create a suitable SSE
2389bcbb9de4726dfe62898f83578e4ec8099b710734sewardj   native format MXCSR value. */
2390bcbb9de4726dfe62898f83578e4ec8099b710734sewardjULong amd64g_create_mxcsr ( ULong sseround )
2391bcbb9de4726dfe62898f83578e4ec8099b710734sewardj{
2392bcbb9de4726dfe62898f83578e4ec8099b710734sewardj   sseround &= 3;
2393bcbb9de4726dfe62898f83578e4ec8099b710734sewardj   return 0x1F80 | (sseround << 13);
2394bcbb9de4726dfe62898f83578e4ec8099b710734sewardj}
2395bcbb9de4726dfe62898f83578e4ec8099b710734sewardj
2396bcbb9de4726dfe62898f83578e4ec8099b710734sewardj
23975e205372f0023f11eb756ee38de40a065b0681c1sewardj/* CLEAN HELPER */
23985e205372f0023f11eb756ee38de40a065b0681c1sewardj/* fpucw[15:0] contains a x87 native format FPU control word.
23995e205372f0023f11eb756ee38de40a065b0681c1sewardj   Extract from it the required FPROUND value and any resulting
24005e205372f0023f11eb756ee38de40a065b0681c1sewardj   emulation warning, and return (warn << 32) | fpround value.
24015e205372f0023f11eb756ee38de40a065b0681c1sewardj*/
24025e205372f0023f11eb756ee38de40a065b0681c1sewardjULong amd64g_check_fldcw ( ULong fpucw )
24035e205372f0023f11eb756ee38de40a065b0681c1sewardj{
24045e205372f0023f11eb756ee38de40a065b0681c1sewardj   /* Decide on a rounding mode.  fpucw[11:10] holds it. */
24055e205372f0023f11eb756ee38de40a065b0681c1sewardj   /* NOTE, encoded exactly as per enum IRRoundingMode. */
24065e205372f0023f11eb756ee38de40a065b0681c1sewardj   ULong rmode = (fpucw >> 10) & 3;
24075e205372f0023f11eb756ee38de40a065b0681c1sewardj
24085e205372f0023f11eb756ee38de40a065b0681c1sewardj   /* Detect any required emulation warnings. */
24096ef84bed9bb3af22060eb1759788034602bbcc88florian   VexEmNote ew = EmNote_NONE;
24105e205372f0023f11eb756ee38de40a065b0681c1sewardj
24115e205372f0023f11eb756ee38de40a065b0681c1sewardj   if ((fpucw & 0x3F) != 0x3F) {
24125e205372f0023f11eb756ee38de40a065b0681c1sewardj      /* unmasked exceptions! */
24135e205372f0023f11eb756ee38de40a065b0681c1sewardj      ew = EmWarn_X86_x87exns;
24145e205372f0023f11eb756ee38de40a065b0681c1sewardj   }
24155e205372f0023f11eb756ee38de40a065b0681c1sewardj   else
24165e205372f0023f11eb756ee38de40a065b0681c1sewardj   if (((fpucw >> 8) & 3) != 3) {
24175e205372f0023f11eb756ee38de40a065b0681c1sewardj      /* unsupported precision */
24185e205372f0023f11eb756ee38de40a065b0681c1sewardj      ew = EmWarn_X86_x87precision;
24195e205372f0023f11eb756ee38de40a065b0681c1sewardj   }
24205e205372f0023f11eb756ee38de40a065b0681c1sewardj
24215e205372f0023f11eb756ee38de40a065b0681c1sewardj   return (((ULong)ew) << 32) | ((ULong)rmode);
24225e205372f0023f11eb756ee38de40a065b0681c1sewardj}
24235e205372f0023f11eb756ee38de40a065b0681c1sewardj
24245e205372f0023f11eb756ee38de40a065b0681c1sewardj
24255e205372f0023f11eb756ee38de40a065b0681c1sewardj/* CLEAN HELPER */
24265e205372f0023f11eb756ee38de40a065b0681c1sewardj/* Given fpround as an IRRoundingMode value, create a suitable x87
24275e205372f0023f11eb756ee38de40a065b0681c1sewardj   native format FPU control word. */
24285e205372f0023f11eb756ee38de40a065b0681c1sewardjULong amd64g_create_fpucw ( ULong fpround )
24295e205372f0023f11eb756ee38de40a065b0681c1sewardj{
24305e205372f0023f11eb756ee38de40a065b0681c1sewardj   fpround &= 3;
24315e205372f0023f11eb756ee38de40a065b0681c1sewardj   return 0x037F | (fpround << 10);
24325e205372f0023f11eb756ee38de40a065b0681c1sewardj}
24335e205372f0023f11eb756ee38de40a065b0681c1sewardj
2434bcbb9de4726dfe62898f83578e4ec8099b710734sewardj
24354017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj/* This is used to implement 'fldenv'.
24364017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj   Reads 28 bytes at x87_state[0 .. 27]. */
24374017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj/* CALLED FROM GENERATED CODE */
24384017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj/* DIRTY HELPER */
24396ef84bed9bb3af22060eb1759788034602bbcc88florianVexEmNote amd64g_dirtyhelper_FLDENV ( /*OUT*/VexGuestAMD64State* vex_state,
24404017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj                                      /*IN*/HWord x87_state)
24414017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj{
2442ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes   return do_put_x87( False, (Fpu_State*)x87_state, vex_state );
24434017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj}
24444017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj
24454017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj
24464017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj/* CALLED FROM GENERATED CODE */
24474017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj/* DIRTY HELPER */
24484017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj/* Create an x87 FPU env from the guest state, as close as we can
24494017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj   approximate it.  Writes 28 bytes at x87_state[0..27]. */
24504017a3b223ee0ae98f6068e5eaaee0e3151d482asewardjvoid amd64g_dirtyhelper_FSTENV ( /*IN*/VexGuestAMD64State* vex_state,
24514017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj                                 /*OUT*/HWord x87_state )
24524017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj{
24534017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj   Int        i, stno, preg;
24544017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj   UInt       tagw;
24554017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj   UChar*     vexTags = (UChar*)(&vex_state->guest_FPTAG[0]);
24564017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj   Fpu_State* x87     = (Fpu_State*)x87_state;
24574017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj   UInt       ftop    = vex_state->guest_FTOP;
24584017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj   ULong      c3210   = vex_state->guest_FC3210;
24594017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj
24604017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj   for (i = 0; i < 14; i++)
24614017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj      x87->env[i] = 0;
24624017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj
24634017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj   x87->env[1] = x87->env[3] = x87->env[5] = x87->env[13] = 0xFFFF;
24644017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj   x87->env[FP_ENV_STAT]
246581d72eaa999c0ffae0f121dbd96b9b44ba67dce5sewardj      = toUShort(toUInt( ((ftop & 7) << 11) | (c3210 & 0x4700) ));
24664017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj   x87->env[FP_ENV_CTRL]
246781d72eaa999c0ffae0f121dbd96b9b44ba67dce5sewardj      = toUShort(toUInt( amd64g_create_fpucw( vex_state->guest_FPROUND ) ));
24684017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj
24694017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj   /* Compute the x87 tag word. */
24704017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj   tagw = 0;
24714017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj   for (stno = 0; stno < 8; stno++) {
24724017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj      preg = (stno + ftop) & 7;
24734017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj      if (vexTags[preg] == 0) {
24744017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj         /* register is empty */
24754017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj         tagw |= (3 << (2*preg));
24764017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj      } else {
24774017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj         /* register is full. */
24784017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj         tagw |= (0 << (2*preg));
24794017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj      }
24804017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj   }
24814017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj   x87->env[FP_ENV_TAG] = toUShort(tagw);
24824017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj
24834017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj   /* We don't dump the x87 registers, tho. */
24844017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj}
24854017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj
24864017a3b223ee0ae98f6068e5eaaee0e3151d482asewardj
24879ae42a77adfcd9fef928bef3439da258b6e6f748sewardj/* This is used to implement 'fnsave'.
24889ae42a77adfcd9fef928bef3439da258b6e6f748sewardj   Writes 108 bytes at x87_state[0 .. 107]. */
24899ae42a77adfcd9fef928bef3439da258b6e6f748sewardj/* CALLED FROM GENERATED CODE */
24909ae42a77adfcd9fef928bef3439da258b6e6f748sewardj/* DIRTY HELPER */
24919ae42a77adfcd9fef928bef3439da258b6e6f748sewardjvoid amd64g_dirtyhelper_FNSAVE ( /*IN*/VexGuestAMD64State* vex_state,
24929ae42a77adfcd9fef928bef3439da258b6e6f748sewardj                                 /*OUT*/HWord x87_state)
24939ae42a77adfcd9fef928bef3439da258b6e6f748sewardj{
2494ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes   do_get_x87( vex_state, (Fpu_State*)x87_state );
24959ae42a77adfcd9fef928bef3439da258b6e6f748sewardj}
24969ae42a77adfcd9fef928bef3439da258b6e6f748sewardj
24979ae42a77adfcd9fef928bef3439da258b6e6f748sewardj
24989ae42a77adfcd9fef928bef3439da258b6e6f748sewardj/* This is used to implement 'fnsaves'.
24999ae42a77adfcd9fef928bef3439da258b6e6f748sewardj   Writes 94 bytes at x87_state[0 .. 93]. */
25009ae42a77adfcd9fef928bef3439da258b6e6f748sewardj/* CALLED FROM GENERATED CODE */
25019ae42a77adfcd9fef928bef3439da258b6e6f748sewardj/* DIRTY HELPER */
25029ae42a77adfcd9fef928bef3439da258b6e6f748sewardjvoid amd64g_dirtyhelper_FNSAVES ( /*IN*/VexGuestAMD64State* vex_state,
25039ae42a77adfcd9fef928bef3439da258b6e6f748sewardj                                  /*OUT*/HWord x87_state)
25049ae42a77adfcd9fef928bef3439da258b6e6f748sewardj{
25059ae42a77adfcd9fef928bef3439da258b6e6f748sewardj   Int           i, stno, preg;
25069ae42a77adfcd9fef928bef3439da258b6e6f748sewardj   UInt          tagw;
25079ae42a77adfcd9fef928bef3439da258b6e6f748sewardj   ULong*        vexRegs = (ULong*)(&vex_state->guest_FPREG[0]);
25089ae42a77adfcd9fef928bef3439da258b6e6f748sewardj   UChar*        vexTags = (UChar*)(&vex_state->guest_FPTAG[0]);
25099ae42a77adfcd9fef928bef3439da258b6e6f748sewardj   Fpu_State_16* x87     = (Fpu_State_16*)x87_state;
25109ae42a77adfcd9fef928bef3439da258b6e6f748sewardj   UInt          ftop    = vex_state->guest_FTOP;
25119ae42a77adfcd9fef928bef3439da258b6e6f748sewardj   UInt          c3210   = vex_state->guest_FC3210;
25129ae42a77adfcd9fef928bef3439da258b6e6f748sewardj
25139ae42a77adfcd9fef928bef3439da258b6e6f748sewardj   for (i = 0; i < 7; i++)
25149ae42a77adfcd9fef928bef3439da258b6e6f748sewardj      x87->env[i] = 0;
25159ae42a77adfcd9fef928bef3439da258b6e6f748sewardj
25169ae42a77adfcd9fef928bef3439da258b6e6f748sewardj   x87->env[FPS_ENV_STAT]
25179ae42a77adfcd9fef928bef3439da258b6e6f748sewardj      = toUShort(((ftop & 7) << 11) | (c3210 & 0x4700));
25189ae42a77adfcd9fef928bef3439da258b6e6f748sewardj   x87->env[FPS_ENV_CTRL]
25199ae42a77adfcd9fef928bef3439da258b6e6f748sewardj      = toUShort(amd64g_create_fpucw( vex_state->guest_FPROUND ));
25209ae42a77adfcd9fef928bef3439da258b6e6f748sewardj
25219ae42a77adfcd9fef928bef3439da258b6e6f748sewardj   /* Dump the register stack in ST order. */
25229ae42a77adfcd9fef928bef3439da258b6e6f748sewardj   tagw = 0;
25239ae42a77adfcd9fef928bef3439da258b6e6f748sewardj   for (stno = 0; stno < 8; stno++) {
25249ae42a77adfcd9fef928bef3439da258b6e6f748sewardj      preg = (stno + ftop) & 7;
25259ae42a77adfcd9fef928bef3439da258b6e6f748sewardj      if (vexTags[preg] == 0) {
25269ae42a77adfcd9fef928bef3439da258b6e6f748sewardj         /* register is empty */
25279ae42a77adfcd9fef928bef3439da258b6e6f748sewardj         tagw |= (3 << (2*preg));
25289ae42a77adfcd9fef928bef3439da258b6e6f748sewardj         convert_f64le_to_f80le( (UChar*)&vexRegs[preg],
25299ae42a77adfcd9fef928bef3439da258b6e6f748sewardj                                 &x87->reg[10*stno] );
25309ae42a77adfcd9fef928bef3439da258b6e6f748sewardj      } else {
25319ae42a77adfcd9fef928bef3439da258b6e6f748sewardj         /* register is full. */
25329ae42a77adfcd9fef928bef3439da258b6e6f748sewardj         tagw |= (0 << (2*preg));
25339ae42a77adfcd9fef928bef3439da258b6e6f748sewardj         convert_f64le_to_f80le( (UChar*)&vexRegs[preg],
25349ae42a77adfcd9fef928bef3439da258b6e6f748sewardj                                 &x87->reg[10*stno] );
25359ae42a77adfcd9fef928bef3439da258b6e6f748sewardj      }
25369ae42a77adfcd9fef928bef3439da258b6e6f748sewardj   }
25379ae42a77adfcd9fef928bef3439da258b6e6f748sewardj   x87->env[FPS_ENV_TAG] = toUShort(tagw);
25389ae42a77adfcd9fef928bef3439da258b6e6f748sewardj}
25399ae42a77adfcd9fef928bef3439da258b6e6f748sewardj
25409ae42a77adfcd9fef928bef3439da258b6e6f748sewardj
25419ae42a77adfcd9fef928bef3439da258b6e6f748sewardj/* This is used to implement 'frstor'.
25429ae42a77adfcd9fef928bef3439da258b6e6f748sewardj   Reads 108 bytes at x87_state[0 .. 107]. */
25439ae42a77adfcd9fef928bef3439da258b6e6f748sewardj/* CALLED FROM GENERATED CODE */
25449ae42a77adfcd9fef928bef3439da258b6e6f748sewardj/* DIRTY HELPER */
25456ef84bed9bb3af22060eb1759788034602bbcc88florianVexEmNote amd64g_dirtyhelper_FRSTOR ( /*OUT*/VexGuestAMD64State* vex_state,
25469ae42a77adfcd9fef928bef3439da258b6e6f748sewardj                                      /*IN*/HWord x87_state)
25479ae42a77adfcd9fef928bef3439da258b6e6f748sewardj{
2548ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes   return do_put_x87( True, (Fpu_State*)x87_state, vex_state );
25499ae42a77adfcd9fef928bef3439da258b6e6f748sewardj}
25509ae42a77adfcd9fef928bef3439da258b6e6f748sewardj
25519ae42a77adfcd9fef928bef3439da258b6e6f748sewardj
25529ae42a77adfcd9fef928bef3439da258b6e6f748sewardj/* This is used to implement 'frstors'.
25539ae42a77adfcd9fef928bef3439da258b6e6f748sewardj   Reads 94 bytes at x87_state[0 .. 93]. */
25549ae42a77adfcd9fef928bef3439da258b6e6f748sewardj/* CALLED FROM GENERATED CODE */
25559ae42a77adfcd9fef928bef3439da258b6e6f748sewardj/* DIRTY HELPER */
25566ef84bed9bb3af22060eb1759788034602bbcc88florianVexEmNote amd64g_dirtyhelper_FRSTORS ( /*OUT*/VexGuestAMD64State* vex_state,
25579ae42a77adfcd9fef928bef3439da258b6e6f748sewardj                                       /*IN*/HWord x87_state)
25589ae42a77adfcd9fef928bef3439da258b6e6f748sewardj{
25599ae42a77adfcd9fef928bef3439da258b6e6f748sewardj   Int           stno, preg;
25609ae42a77adfcd9fef928bef3439da258b6e6f748sewardj   UInt          tag;
25619ae42a77adfcd9fef928bef3439da258b6e6f748sewardj   ULong*        vexRegs = (ULong*)(&vex_state->guest_FPREG[0]);
25629ae42a77adfcd9fef928bef3439da258b6e6f748sewardj   UChar*        vexTags = (UChar*)(&vex_state->guest_FPTAG[0]);
25639ae42a77adfcd9fef928bef3439da258b6e6f748sewardj   Fpu_State_16* x87     = (Fpu_State_16*)x87_state;
25649ae42a77adfcd9fef928bef3439da258b6e6f748sewardj   UInt          ftop    = (x87->env[FPS_ENV_STAT] >> 11) & 7;
25659ae42a77adfcd9fef928bef3439da258b6e6f748sewardj   UInt          tagw    = x87->env[FPS_ENV_TAG];
25669ae42a77adfcd9fef928bef3439da258b6e6f748sewardj   UInt          fpucw   = x87->env[FPS_ENV_CTRL];
25679ae42a77adfcd9fef928bef3439da258b6e6f748sewardj   UInt          c3210   = x87->env[FPS_ENV_STAT] & 0x4700;
25686ef84bed9bb3af22060eb1759788034602bbcc88florian   VexEmNote     ew;
25699ae42a77adfcd9fef928bef3439da258b6e6f748sewardj   UInt          fpround;
25709ae42a77adfcd9fef928bef3439da258b6e6f748sewardj   ULong         pair;
25719ae42a77adfcd9fef928bef3439da258b6e6f748sewardj
25729ae42a77adfcd9fef928bef3439da258b6e6f748sewardj   /* Copy registers and tags */
25739ae42a77adfcd9fef928bef3439da258b6e6f748sewardj   for (stno = 0; stno < 8; stno++) {
25749ae42a77adfcd9fef928bef3439da258b6e6f748sewardj      preg = (stno + ftop) & 7;
25759ae42a77adfcd9fef928bef3439da258b6e6f748sewardj      tag = (tagw >> (2*preg)) & 3;
25769ae42a77adfcd9fef928bef3439da258b6e6f748sewardj      if (tag == 3) {
25779ae42a77adfcd9fef928bef3439da258b6e6f748sewardj         /* register is empty */
25789ae42a77adfcd9fef928bef3439da258b6e6f748sewardj         /* hmm, if it's empty, does it still get written?  Probably
25799ae42a77adfcd9fef928bef3439da258b6e6f748sewardj            safer to say it does.  If we don't, memcheck could get out
25809ae42a77adfcd9fef928bef3439da258b6e6f748sewardj            of sync, in that it thinks all FP registers are defined by
25819ae42a77adfcd9fef928bef3439da258b6e6f748sewardj            this helper, but in reality some have not been updated. */
25829ae42a77adfcd9fef928bef3439da258b6e6f748sewardj         vexRegs[preg] = 0; /* IEEE754 64-bit zero */
25839ae42a77adfcd9fef928bef3439da258b6e6f748sewardj         vexTags[preg] = 0;
25849ae42a77adfcd9fef928bef3439da258b6e6f748sewardj      } else {
25859ae42a77adfcd9fef928bef3439da258b6e6f748sewardj         /* register is non-empty */
25869ae42a77adfcd9fef928bef3439da258b6e6f748sewardj         convert_f80le_to_f64le( &x87->reg[10*stno],
25879ae42a77adfcd9fef928bef3439da258b6e6f748sewardj                                 (UChar*)&vexRegs[preg] );
25889ae42a77adfcd9fef928bef3439da258b6e6f748sewardj         vexTags[preg] = 1;
25899ae42a77adfcd9fef928bef3439da258b6e6f748sewardj      }
25909ae42a77adfcd9fef928bef3439da258b6e6f748sewardj   }
25919ae42a77adfcd9fef928bef3439da258b6e6f748sewardj
25929ae42a77adfcd9fef928bef3439da258b6e6f748sewardj   /* stack pointer */
25939ae42a77adfcd9fef928bef3439da258b6e6f748sewardj   vex_state->guest_FTOP = ftop;
25949ae42a77adfcd9fef928bef3439da258b6e6f748sewardj
25959ae42a77adfcd9fef928bef3439da258b6e6f748sewardj   /* status word */
25969ae42a77adfcd9fef928bef3439da258b6e6f748sewardj   vex_state->guest_FC3210 = c3210;
25979ae42a77adfcd9fef928bef3439da258b6e6f748sewardj
25989ae42a77adfcd9fef928bef3439da258b6e6f748sewardj   /* handle the control word, setting FPROUND and detecting any
25999ae42a77adfcd9fef928bef3439da258b6e6f748sewardj      emulation warnings. */
26009ae42a77adfcd9fef928bef3439da258b6e6f748sewardj   pair    = amd64g_check_fldcw ( (ULong)fpucw );
26019ae42a77adfcd9fef928bef3439da258b6e6f748sewardj   fpround = (UInt)pair & 0xFFFFFFFFULL;
26026ef84bed9bb3af22060eb1759788034602bbcc88florian   ew      = (VexEmNote)(pair >> 32);
26039ae42a77adfcd9fef928bef3439da258b6e6f748sewardj
26049ae42a77adfcd9fef928bef3439da258b6e6f748sewardj   vex_state->guest_FPROUND = fpround & 3;
26059ae42a77adfcd9fef928bef3439da258b6e6f748sewardj
26069ae42a77adfcd9fef928bef3439da258b6e6f748sewardj   /* emulation warnings --> caller */
26079ae42a77adfcd9fef928bef3439da258b6e6f748sewardj   return ew;
26089ae42a77adfcd9fef928bef3439da258b6e6f748sewardj}
26099ae42a77adfcd9fef928bef3439da258b6e6f748sewardj
26109ae42a77adfcd9fef928bef3439da258b6e6f748sewardj
2611d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj/*---------------------------------------------------------------*/
261270dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj/*--- CPUID helpers.                                          ---*/
2613d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj/*---------------------------------------------------------------*/
2614d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj
2615e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj/* Claim to be the following CPU, which is probably representative of
2616e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   the lowliest (earliest) amd64 offerings.  It can do neither sse3
2617e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   nor cx16.
2618e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj
2619e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   vendor_id       : AuthenticAMD
2620e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   cpu family      : 15
2621e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   model           : 5
2622e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   model name      : AMD Opteron (tm) Processor 848
2623e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   stepping        : 10
2624e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   cpu MHz         : 1797.682
2625e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   cache size      : 1024 KB
2626e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   fpu             : yes
2627e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   fpu_exception   : yes
2628e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   cpuid level     : 1
2629e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   wp              : yes
2630e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   flags           : fpu vme de pse tsc msr pae mce cx8 apic sep
2631e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                     mtrr pge mca cmov pat pse36 clflush mmx fxsr
2632e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                     sse sse2 syscall nx mmxext lm 3dnowext 3dnow
2633e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   bogomips        : 3600.62
2634e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   TLB size        : 1088 4K pages
2635e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   clflush size    : 64
2636e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   cache_alignment : 64
2637e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   address sizes   : 40 bits physical, 48 bits virtual
26381aa3aefc284aee6a947e7f52079eb5e4e48f59acsewardj   power management: ts fid vid ttp
26391aa3aefc284aee6a947e7f52079eb5e4e48f59acsewardj
26401aa3aefc284aee6a947e7f52079eb5e4e48f59acsewardj   2012-Feb-21: don't claim 3dnow or 3dnowext, since in fact
26411aa3aefc284aee6a947e7f52079eb5e4e48f59acsewardj   we don't support them.  See #291568.  3dnow is 80000001.EDX.31
26421aa3aefc284aee6a947e7f52079eb5e4e48f59acsewardj   and 3dnowext is 80000001.EDX.30.
2643e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj*/
2644e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardjvoid amd64g_dirtyhelper_CPUID_baseline ( VexGuestAMD64State* st )
2645e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj{
2646e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj#  define SET_ABCD(_a,_b,_c,_d)                \
2647e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      do { st->guest_RAX = (ULong)(_a);        \
2648e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj           st->guest_RBX = (ULong)(_b);        \
2649e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj           st->guest_RCX = (ULong)(_c);        \
2650e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj           st->guest_RDX = (ULong)(_d);        \
2651e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      } while (0)
2652e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj
2653e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   switch (0xFFFFFFFF & st->guest_RAX) {
2654e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      case 0x00000000:
2655e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         SET_ABCD(0x00000001, 0x68747541, 0x444d4163, 0x69746e65);
2656e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         break;
2657e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      case 0x00000001:
2658e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         SET_ABCD(0x00000f5a, 0x01000800, 0x00000000, 0x078bfbff);
2659e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         break;
2660e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      case 0x80000000:
2661e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         SET_ABCD(0x80000018, 0x68747541, 0x444d4163, 0x69746e65);
2662e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         break;
2663e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      case 0x80000001:
26641aa3aefc284aee6a947e7f52079eb5e4e48f59acsewardj         /* Don't claim to support 3dnow or 3dnowext.  0xe1d3fbff is
26651aa3aefc284aee6a947e7f52079eb5e4e48f59acsewardj            the original it-is-supported value that the h/w provides.
26661aa3aefc284aee6a947e7f52079eb5e4e48f59acsewardj            See #291568. */
26671aa3aefc284aee6a947e7f52079eb5e4e48f59acsewardj         SET_ABCD(0x00000f5a, 0x00000505, 0x00000000, /*0xe1d3fbff*/
26681aa3aefc284aee6a947e7f52079eb5e4e48f59acsewardj                                                      0x21d3fbff);
2669e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         break;
2670e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      case 0x80000002:
2671e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         SET_ABCD(0x20444d41, 0x6574704f, 0x206e6f72, 0x296d7428);
2672e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         break;
2673e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      case 0x80000003:
2674e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         SET_ABCD(0x6f725020, 0x73736563, 0x3820726f, 0x00003834);
2675e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         break;
2676e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      case 0x80000004:
2677e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2678e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         break;
2679e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      case 0x80000005:
2680e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         SET_ABCD(0xff08ff08, 0xff20ff20, 0x40020140, 0x40020140);
2681e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         break;
2682e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      case 0x80000006:
2683e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         SET_ABCD(0x00000000, 0x42004200, 0x04008140, 0x00000000);
2684e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         break;
2685e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      case 0x80000007:
2686e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x0000000f);
2687e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         break;
2688e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      case 0x80000008:
2689e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         SET_ABCD(0x00003028, 0x00000000, 0x00000000, 0x00000000);
2690e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         break;
2691e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      default:
2692e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2693e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         break;
2694e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   }
2695e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj#  undef SET_ABCD
2696e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj}
2697e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj
2698e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj
2699e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj/* Claim to be the following CPU (2 x ...), which is sse3 and cx16
2700e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   capable.
2701e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj
2702150c9cddb753ad4dc38f43484144523174d38b02sewardj   vendor_id       : GenuineIntel
2703150c9cddb753ad4dc38f43484144523174d38b02sewardj   cpu family      : 6
2704150c9cddb753ad4dc38f43484144523174d38b02sewardj   model           : 15
2705150c9cddb753ad4dc38f43484144523174d38b02sewardj   model name      : Intel(R) Core(TM)2 CPU 6600 @ 2.40GHz
2706150c9cddb753ad4dc38f43484144523174d38b02sewardj   stepping        : 6
2707150c9cddb753ad4dc38f43484144523174d38b02sewardj   cpu MHz         : 2394.000
2708150c9cddb753ad4dc38f43484144523174d38b02sewardj   cache size      : 4096 KB
2709150c9cddb753ad4dc38f43484144523174d38b02sewardj   physical id     : 0
2710150c9cddb753ad4dc38f43484144523174d38b02sewardj   siblings        : 2
2711150c9cddb753ad4dc38f43484144523174d38b02sewardj   core id         : 0
2712150c9cddb753ad4dc38f43484144523174d38b02sewardj   cpu cores       : 2
2713d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj   fpu             : yes
2714d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj   fpu_exception   : yes
2715150c9cddb753ad4dc38f43484144523174d38b02sewardj   cpuid level     : 10
2716d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj   wp              : yes
2717150c9cddb753ad4dc38f43484144523174d38b02sewardj   flags           : fpu vme de pse tsc msr pae mce cx8 apic sep
2718150c9cddb753ad4dc38f43484144523174d38b02sewardj                     mtrr pge mca cmov pat pse36 clflush dts acpi
2719150c9cddb753ad4dc38f43484144523174d38b02sewardj                     mmx fxsr sse sse2 ss ht tm syscall nx lm
2720150c9cddb753ad4dc38f43484144523174d38b02sewardj                     constant_tsc pni monitor ds_cpl vmx est tm2
2721150c9cddb753ad4dc38f43484144523174d38b02sewardj                     cx16 xtpr lahf_lm
2722150c9cddb753ad4dc38f43484144523174d38b02sewardj   bogomips        : 4798.78
2723d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj   clflush size    : 64
2724d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj   cache_alignment : 64
2725150c9cddb753ad4dc38f43484144523174d38b02sewardj   address sizes   : 36 bits physical, 48 bits virtual
2726150c9cddb753ad4dc38f43484144523174d38b02sewardj   power management:
2727d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj*/
2728e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardjvoid amd64g_dirtyhelper_CPUID_sse3_and_cx16 ( VexGuestAMD64State* st )
2729d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj{
2730d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj#  define SET_ABCD(_a,_b,_c,_d)                \
2731d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj      do { st->guest_RAX = (ULong)(_a);        \
2732d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj           st->guest_RBX = (ULong)(_b);        \
2733d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj           st->guest_RCX = (ULong)(_c);        \
2734d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj           st->guest_RDX = (ULong)(_d);        \
2735d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj      } while (0)
2736d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj
2737d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj   switch (0xFFFFFFFF & st->guest_RAX) {
2738150c9cddb753ad4dc38f43484144523174d38b02sewardj      case 0x00000000:
2739150c9cddb753ad4dc38f43484144523174d38b02sewardj         SET_ABCD(0x0000000a, 0x756e6547, 0x6c65746e, 0x49656e69);
2740d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj         break;
2741150c9cddb753ad4dc38f43484144523174d38b02sewardj      case 0x00000001:
2742150c9cddb753ad4dc38f43484144523174d38b02sewardj         SET_ABCD(0x000006f6, 0x00020800, 0x0000e3bd, 0xbfebfbff);
2743d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj         break;
2744150c9cddb753ad4dc38f43484144523174d38b02sewardj      case 0x00000002:
2745150c9cddb753ad4dc38f43484144523174d38b02sewardj         SET_ABCD(0x05b0b101, 0x005657f0, 0x00000000, 0x2cb43049);
2746d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj         break;
2747150c9cddb753ad4dc38f43484144523174d38b02sewardj      case 0x00000003:
2748150c9cddb753ad4dc38f43484144523174d38b02sewardj         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2749d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj         break;
275032bfd3e057bf3e0b215b1d234398b4d7791eba9asewardj      case 0x00000004: {
275132bfd3e057bf3e0b215b1d234398b4d7791eba9asewardj         switch (0xFFFFFFFF & st->guest_RCX) {
275232bfd3e057bf3e0b215b1d234398b4d7791eba9asewardj            case 0x00000000: SET_ABCD(0x04000121, 0x01c0003f,
275332bfd3e057bf3e0b215b1d234398b4d7791eba9asewardj                                      0x0000003f, 0x00000001); break;
275432bfd3e057bf3e0b215b1d234398b4d7791eba9asewardj            case 0x00000001: SET_ABCD(0x04000122, 0x01c0003f,
275532bfd3e057bf3e0b215b1d234398b4d7791eba9asewardj                                      0x0000003f, 0x00000001); break;
275632bfd3e057bf3e0b215b1d234398b4d7791eba9asewardj            case 0x00000002: SET_ABCD(0x04004143, 0x03c0003f,
275732bfd3e057bf3e0b215b1d234398b4d7791eba9asewardj                                      0x00000fff, 0x00000001); break;
275832bfd3e057bf3e0b215b1d234398b4d7791eba9asewardj            default:         SET_ABCD(0x00000000, 0x00000000,
275932bfd3e057bf3e0b215b1d234398b4d7791eba9asewardj                                      0x00000000, 0x00000000); break;
276032bfd3e057bf3e0b215b1d234398b4d7791eba9asewardj         }
2761d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj         break;
276232bfd3e057bf3e0b215b1d234398b4d7791eba9asewardj      }
2763150c9cddb753ad4dc38f43484144523174d38b02sewardj      case 0x00000005:
2764150c9cddb753ad4dc38f43484144523174d38b02sewardj         SET_ABCD(0x00000040, 0x00000040, 0x00000003, 0x00000020);
2765d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj         break;
2766150c9cddb753ad4dc38f43484144523174d38b02sewardj      case 0x00000006:
2767150c9cddb753ad4dc38f43484144523174d38b02sewardj         SET_ABCD(0x00000001, 0x00000002, 0x00000001, 0x00000000);
2768d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj         break;
2769150c9cddb753ad4dc38f43484144523174d38b02sewardj      case 0x00000007:
2770150c9cddb753ad4dc38f43484144523174d38b02sewardj         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2771d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj         break;
2772150c9cddb753ad4dc38f43484144523174d38b02sewardj      case 0x00000008:
2773150c9cddb753ad4dc38f43484144523174d38b02sewardj         SET_ABCD(0x00000400, 0x00000000, 0x00000000, 0x00000000);
2774d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj         break;
2775150c9cddb753ad4dc38f43484144523174d38b02sewardj      case 0x00000009:
2776150c9cddb753ad4dc38f43484144523174d38b02sewardj         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2777d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj         break;
2778150c9cddb753ad4dc38f43484144523174d38b02sewardj      case 0x0000000a:
277932bfd3e057bf3e0b215b1d234398b4d7791eba9asewardj      unhandled_eax_value:
2780150c9cddb753ad4dc38f43484144523174d38b02sewardj         SET_ABCD(0x07280202, 0x00000000, 0x00000000, 0x00000000);
2781150c9cddb753ad4dc38f43484144523174d38b02sewardj         break;
2782150c9cddb753ad4dc38f43484144523174d38b02sewardj      case 0x80000000:
2783150c9cddb753ad4dc38f43484144523174d38b02sewardj         SET_ABCD(0x80000008, 0x00000000, 0x00000000, 0x00000000);
2784150c9cddb753ad4dc38f43484144523174d38b02sewardj         break;
2785150c9cddb753ad4dc38f43484144523174d38b02sewardj      case 0x80000001:
2786150c9cddb753ad4dc38f43484144523174d38b02sewardj         SET_ABCD(0x00000000, 0x00000000, 0x00000001, 0x20100800);
2787150c9cddb753ad4dc38f43484144523174d38b02sewardj         break;
2788150c9cddb753ad4dc38f43484144523174d38b02sewardj      case 0x80000002:
2789150c9cddb753ad4dc38f43484144523174d38b02sewardj         SET_ABCD(0x65746e49, 0x2952286c, 0x726f4320, 0x4d542865);
2790150c9cddb753ad4dc38f43484144523174d38b02sewardj         break;
2791150c9cddb753ad4dc38f43484144523174d38b02sewardj      case 0x80000003:
2792150c9cddb753ad4dc38f43484144523174d38b02sewardj         SET_ABCD(0x43203229, 0x20205550, 0x20202020, 0x20202020);
2793150c9cddb753ad4dc38f43484144523174d38b02sewardj         break;
2794150c9cddb753ad4dc38f43484144523174d38b02sewardj      case 0x80000004:
2795150c9cddb753ad4dc38f43484144523174d38b02sewardj         SET_ABCD(0x30303636, 0x20402020, 0x30342e32, 0x007a4847);
2796150c9cddb753ad4dc38f43484144523174d38b02sewardj         break;
2797150c9cddb753ad4dc38f43484144523174d38b02sewardj      case 0x80000005:
2798150c9cddb753ad4dc38f43484144523174d38b02sewardj         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2799150c9cddb753ad4dc38f43484144523174d38b02sewardj         break;
2800150c9cddb753ad4dc38f43484144523174d38b02sewardj      case 0x80000006:
2801150c9cddb753ad4dc38f43484144523174d38b02sewardj         SET_ABCD(0x00000000, 0x00000000, 0x10008040, 0x00000000);
2802150c9cddb753ad4dc38f43484144523174d38b02sewardj         break;
2803150c9cddb753ad4dc38f43484144523174d38b02sewardj      case 0x80000007:
2804150c9cddb753ad4dc38f43484144523174d38b02sewardj         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2805150c9cddb753ad4dc38f43484144523174d38b02sewardj         break;
2806150c9cddb753ad4dc38f43484144523174d38b02sewardj      case 0x80000008:
2807150c9cddb753ad4dc38f43484144523174d38b02sewardj         SET_ABCD(0x00003024, 0x00000000, 0x00000000, 0x00000000);
2808150c9cddb753ad4dc38f43484144523174d38b02sewardj         break;
2809d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj      default:
281032bfd3e057bf3e0b215b1d234398b4d7791eba9asewardj         goto unhandled_eax_value;
2811d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj   }
2812d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj#  undef SET_ABCD
2813d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj}
2814d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj
2815d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj
28160b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj/* Claim to be the following CPU (4 x ...), which is sse4.2 and cx16
28170b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj   capable.
28180b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj
28190b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj   vendor_id       : GenuineIntel
28200b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj   cpu family      : 6
28210b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj   model           : 37
28220b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj   model name      : Intel(R) Core(TM) i5 CPU         670  @ 3.47GHz
28230b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj   stepping        : 2
28240b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj   cpu MHz         : 3334.000
28250b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj   cache size      : 4096 KB
28260b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj   physical id     : 0
28270b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj   siblings        : 4
28280b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj   core id         : 0
28290b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj   cpu cores       : 2
28300b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj   apicid          : 0
28310b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj   initial apicid  : 0
28320b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj   fpu             : yes
28330b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj   fpu_exception   : yes
28340b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj   cpuid level     : 11
28350b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj   wp              : yes
28360b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj   flags           : fpu vme de pse tsc msr pae mce cx8 apic sep
28370b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj                     mtrr pge mca cmov pat pse36 clflush dts acpi
28380b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj                     mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp
28390b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj                     lm constant_tsc arch_perfmon pebs bts rep_good
28400b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj                     xtopology nonstop_tsc aperfmperf pni pclmulqdq
28410b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj                     dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16
28420b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj                     xtpr pdcm sse4_1 sse4_2 popcnt aes lahf_lm ida
28430b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj                     arat tpr_shadow vnmi flexpriority ept vpid
28440b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj   bogomips        : 6957.57
28450b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj   clflush size    : 64
28460b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj   cache_alignment : 64
28470b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj   address sizes   : 36 bits physical, 48 bits virtual
28480b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj   power management:
28490b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj*/
28500b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardjvoid amd64g_dirtyhelper_CPUID_sse42_and_cx16 ( VexGuestAMD64State* st )
28510b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj{
28520b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj#  define SET_ABCD(_a,_b,_c,_d)                \
28530b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj      do { st->guest_RAX = (ULong)(_a);        \
28540b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj           st->guest_RBX = (ULong)(_b);        \
28550b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj           st->guest_RCX = (ULong)(_c);        \
28560b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj           st->guest_RDX = (ULong)(_d);        \
28570b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj      } while (0)
28580b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj
28590b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj   UInt old_eax = (UInt)st->guest_RAX;
28600b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj   UInt old_ecx = (UInt)st->guest_RCX;
28610b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj
28620b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj   switch (old_eax) {
28630b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj      case 0x00000000:
28640b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj         SET_ABCD(0x0000000b, 0x756e6547, 0x6c65746e, 0x49656e69);
28650b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj         break;
28660b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj      case 0x00000001:
2867ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe         SET_ABCD(0x00020652, 0x00100800, 0x0298e3ff, 0xbfebfbff);
28680b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj         break;
28690b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj      case 0x00000002:
28700b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj         SET_ABCD(0x55035a01, 0x00f0b2e3, 0x00000000, 0x09ca212c);
28710b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj         break;
28720b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj      case 0x00000003:
28730b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
28740b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj         break;
28750b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj      case 0x00000004:
28760b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj         switch (old_ecx) {
28770b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj            case 0x00000000: SET_ABCD(0x1c004121, 0x01c0003f,
28780b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj                                      0x0000003f, 0x00000000); break;
28790b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj            case 0x00000001: SET_ABCD(0x1c004122, 0x00c0003f,
28800b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj                                      0x0000007f, 0x00000000); break;
28810b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj            case 0x00000002: SET_ABCD(0x1c004143, 0x01c0003f,
28820b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj                                      0x000001ff, 0x00000000); break;
28830b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj            case 0x00000003: SET_ABCD(0x1c03c163, 0x03c0003f,
28840b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj                                      0x00000fff, 0x00000002); break;
28850b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj            default:         SET_ABCD(0x00000000, 0x00000000,
28860b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj                                      0x00000000, 0x00000000); break;
28870b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj         }
28880b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj         break;
28890b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj      case 0x00000005:
28900b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj         SET_ABCD(0x00000040, 0x00000040, 0x00000003, 0x00001120);
28910b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj         break;
28920b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj      case 0x00000006:
28930b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj         SET_ABCD(0x00000007, 0x00000002, 0x00000001, 0x00000000);
28940b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj         break;
28950b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj      case 0x00000007:
28960b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
28970b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj         break;
28980b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj      case 0x00000008:
28990b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
29000b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj         break;
29010b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj      case 0x00000009:
29020b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
29030b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj         break;
29040b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj      case 0x0000000a:
29050b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj         SET_ABCD(0x07300403, 0x00000004, 0x00000000, 0x00000603);
29060b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj         break;
29070b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj      case 0x0000000b:
29080b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj         switch (old_ecx) {
29090b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj            case 0x00000000:
29100b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj               SET_ABCD(0x00000001, 0x00000002,
29110b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj                        0x00000100, 0x00000000); break;
29120b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj            case 0x00000001:
29130b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj               SET_ABCD(0x00000004, 0x00000004,
29140b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj                        0x00000201, 0x00000000); break;
29150b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj            default:
29160b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj               SET_ABCD(0x00000000, 0x00000000,
29170b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj                        old_ecx,    0x00000000); break;
29180b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj         }
29190b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj         break;
29200b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj      case 0x0000000c:
29210b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj         SET_ABCD(0x00000001, 0x00000002, 0x00000100, 0x00000000);
29220b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj         break;
29230b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj      case 0x0000000d:
29240b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj         switch (old_ecx) {
29250b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj            case 0x00000000: SET_ABCD(0x00000001, 0x00000002,
29260b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj                                      0x00000100, 0x00000000); break;
29270b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj            case 0x00000001: SET_ABCD(0x00000004, 0x00000004,
29280b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj                                      0x00000201, 0x00000000); break;
29290b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj            default:         SET_ABCD(0x00000000, 0x00000000,
29300b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj                                      old_ecx,    0x00000000); break;
29310b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj         }
29320b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj         break;
29330b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj      case 0x80000000:
29340b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj         SET_ABCD(0x80000008, 0x00000000, 0x00000000, 0x00000000);
29350b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj         break;
29360b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj      case 0x80000001:
29370b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj         SET_ABCD(0x00000000, 0x00000000, 0x00000001, 0x28100800);
29380b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj         break;
29390b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj      case 0x80000002:
29400b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj         SET_ABCD(0x65746e49, 0x2952286c, 0x726f4320, 0x4d542865);
29410b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj         break;
29420b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj      case 0x80000003:
29430b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj         SET_ABCD(0x35692029, 0x55504320, 0x20202020, 0x20202020);
29440b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj         break;
29450b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj      case 0x80000004:
29460b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj         SET_ABCD(0x30373620, 0x20402020, 0x37342e33, 0x007a4847);
29470b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj         break;
29480b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj      case 0x80000005:
29490b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
29500b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj         break;
29510b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj      case 0x80000006:
29520b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj         SET_ABCD(0x00000000, 0x00000000, 0x01006040, 0x00000000);
29530b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj         break;
29540b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj      case 0x80000007:
29550b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000100);
29560b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj         break;
29570b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj      case 0x80000008:
29580b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj         SET_ABCD(0x00003024, 0x00000000, 0x00000000, 0x00000000);
29590b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj         break;
29600b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj      default:
29610b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj         SET_ABCD(0x00000001, 0x00000002, 0x00000100, 0x00000000);
29620b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj         break;
29630b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj   }
29640b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj#  undef SET_ABCD
29650b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj}
29660b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj
29670b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj
2968fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj/* Claim to be the following CPU (4 x ...), which is AVX and cx16
29699e4c3763314031a712e06d96746716aa2dd96a31sewardj   capable.  Plus (kludge!) it "supports" HTM.
2970fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj
297170dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   Also with the following change: claim that XSaveOpt is not
297270dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   available, by cpuid(eax=0xD,ecx=1).eax[0] returns 0, compared to 1
297370dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   on the real CPU.  Consequently, programs that correctly observe
297470dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   these CPUID values should only try to use 3 of the 8 XSave-family
297570dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   instructions: XGETBV, XSAVE and XRSTOR.  In particular this avoids
297670dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   having to implement the compacted or optimised save/restore
297770dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   variants.
297870dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj
2979fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj   vendor_id       : GenuineIntel
2980fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj   cpu family      : 6
2981fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj   model           : 42
2982fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj   model name      : Intel(R) Core(TM) i5-2300 CPU @ 2.80GHz
2983fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj   stepping        : 7
2984fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj   cpu MHz         : 1600.000
2985fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj   cache size      : 6144 KB
2986fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj   physical id     : 0
2987fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj   siblings        : 4
2988fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj   core id         : 3
2989fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj   cpu cores       : 4
2990fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj   apicid          : 6
2991fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj   initial apicid  : 6
2992fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj   fpu             : yes
2993fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj   fpu_exception   : yes
2994fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj   cpuid level     : 13
2995fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj   wp              : yes
2996fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj   flags           : fpu vme de pse tsc msr pae mce cx8 apic sep
2997fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj                     mtrr pge mca cmov pat pse36 clflush dts acpi
2998fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj                     mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp
2999fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj                     lm constant_tsc arch_perfmon pebs bts rep_good
3000fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj                     nopl xtopology nonstop_tsc aperfmperf pni pclmulqdq
3001fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj                     dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16
3002fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj                     xtpr pdcm sse4_1 sse4_2 popcnt aes xsave avx
3003fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj                     lahf_lm ida arat epb xsaveopt pln pts dts
3004fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj                     tpr_shadow vnmi flexpriority ept vpid
3005fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj
3006fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj   bogomips        : 5768.94
3007fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj   clflush size    : 64
3008fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj   cache_alignment : 64
3009fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj   address sizes   : 36 bits physical, 48 bits virtual
3010fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj   power management:
3011fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj*/
3012fe0c5e78ee12edb0a857e73dd21181b03299e560sewardjvoid amd64g_dirtyhelper_CPUID_avx_and_cx16 ( VexGuestAMD64State* st )
3013fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj{
3014fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj#  define SET_ABCD(_a,_b,_c,_d)                \
3015fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj      do { st->guest_RAX = (ULong)(_a);        \
3016fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj           st->guest_RBX = (ULong)(_b);        \
3017fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj           st->guest_RCX = (ULong)(_c);        \
3018fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj           st->guest_RDX = (ULong)(_d);        \
3019fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj      } while (0)
3020fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj
3021fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj   UInt old_eax = (UInt)st->guest_RAX;
3022fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj   UInt old_ecx = (UInt)st->guest_RCX;
3023fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj
3024fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj   switch (old_eax) {
3025fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj      case 0x00000000:
3026fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         SET_ABCD(0x0000000d, 0x756e6547, 0x6c65746e, 0x49656e69);
3027fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         break;
3028fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj      case 0x00000001:
3029fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         SET_ABCD(0x000206a7, 0x00100800, 0x1f9ae3bf, 0xbfebfbff);
3030fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         break;
3031fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj      case 0x00000002:
3032fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         SET_ABCD(0x76035a01, 0x00f0b0ff, 0x00000000, 0x00ca0000);
3033fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         break;
3034fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj      case 0x00000003:
3035fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
3036fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         break;
3037fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj      case 0x00000004:
3038fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         switch (old_ecx) {
3039fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj            case 0x00000000: SET_ABCD(0x1c004121, 0x01c0003f,
3040fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj                                      0x0000003f, 0x00000000); break;
3041fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj            case 0x00000001: SET_ABCD(0x1c004122, 0x01c0003f,
3042fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj                                      0x0000003f, 0x00000000); break;
3043fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj            case 0x00000002: SET_ABCD(0x1c004143, 0x01c0003f,
3044fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj                                      0x000001ff, 0x00000000); break;
3045fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj            case 0x00000003: SET_ABCD(0x1c03c163, 0x02c0003f,
3046fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj                                      0x00001fff, 0x00000006); break;
3047fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj            default:         SET_ABCD(0x00000000, 0x00000000,
3048fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj                                      0x00000000, 0x00000000); break;
3049fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         }
3050fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         break;
3051fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj      case 0x00000005:
3052fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         SET_ABCD(0x00000040, 0x00000040, 0x00000003, 0x00001120);
3053fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         break;
3054fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj      case 0x00000006:
3055fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         SET_ABCD(0x00000077, 0x00000002, 0x00000009, 0x00000000);
3056fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         break;
3057fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj      case 0x00000007:
30589e4c3763314031a712e06d96746716aa2dd96a31sewardj         SET_ABCD(0x00000000, 0x00000800, 0x00000000, 0x00000000);
3059fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         break;
3060fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj      case 0x00000008:
3061fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
3062fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         break;
3063fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj      case 0x00000009:
3064fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
3065fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         break;
3066fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj      case 0x0000000a:
3067fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         SET_ABCD(0x07300803, 0x00000000, 0x00000000, 0x00000603);
3068fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         break;
3069fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj      case 0x0000000b:
3070fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         switch (old_ecx) {
3071fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj            case 0x00000000:
3072fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj               SET_ABCD(0x00000001, 0x00000001,
3073fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj                        0x00000100, 0x00000000); break;
3074fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj            case 0x00000001:
3075fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj               SET_ABCD(0x00000004, 0x00000004,
3076fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj                        0x00000201, 0x00000000); break;
3077fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj            default:
3078fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj               SET_ABCD(0x00000000, 0x00000000,
3079fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj                        old_ecx,    0x00000000); break;
3080fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         }
3081fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         break;
3082fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj      case 0x0000000c:
3083fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
3084fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         break;
3085fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj      case 0x0000000d:
3086fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         switch (old_ecx) {
3087fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj            case 0x00000000: SET_ABCD(0x00000007, 0x00000340,
3088fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj                                      0x00000340, 0x00000000); break;
308970dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj            case 0x00000001: SET_ABCD(0x00000000, 0x00000000,
3090fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj                                      0x00000000, 0x00000000); break;
3091fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj            case 0x00000002: SET_ABCD(0x00000100, 0x00000240,
3092fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj                                      0x00000000, 0x00000000); break;
3093fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj            default:         SET_ABCD(0x00000000, 0x00000000,
3094fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj                                      0x00000000, 0x00000000); break;
3095fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         }
3096fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         break;
3097fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj      case 0x0000000e:
3098fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         SET_ABCD(0x00000007, 0x00000340, 0x00000340, 0x00000000);
3099fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         break;
3100fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj      case 0x0000000f:
3101fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         SET_ABCD(0x00000007, 0x00000340, 0x00000340, 0x00000000);
3102fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         break;
3103fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj      case 0x80000000:
3104fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         SET_ABCD(0x80000008, 0x00000000, 0x00000000, 0x00000000);
3105fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         break;
3106fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj      case 0x80000001:
3107fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         SET_ABCD(0x00000000, 0x00000000, 0x00000001, 0x28100800);
3108fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         break;
3109fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj      case 0x80000002:
3110fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         SET_ABCD(0x20202020, 0x20202020, 0x65746e49, 0x2952286c);
3111fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         break;
3112fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj      case 0x80000003:
3113fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         SET_ABCD(0x726f4320, 0x4d542865, 0x35692029, 0x3033322d);
3114fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         break;
3115fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj      case 0x80000004:
3116fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         SET_ABCD(0x50432030, 0x20402055, 0x30382e32, 0x007a4847);
3117fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         break;
3118fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj      case 0x80000005:
3119fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
3120fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         break;
3121fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj      case 0x80000006:
3122fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         SET_ABCD(0x00000000, 0x00000000, 0x01006040, 0x00000000);
3123fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         break;
3124fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj      case 0x80000007:
3125fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000100);
3126fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         break;
3127fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj      case 0x80000008:
3128fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         SET_ABCD(0x00003024, 0x00000000, 0x00000000, 0x00000000);
3129fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         break;
3130fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj      default:
3131fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         SET_ABCD(0x00000007, 0x00000340, 0x00000340, 0x00000000);
3132fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj         break;
3133fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj   }
3134fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj#  undef SET_ABCD
3135fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj}
3136fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj
3137fe0c5e78ee12edb0a857e73dd21181b03299e560sewardj
313870dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj/* Claim to be the following CPU (4 x ...), which is AVX2 capable.
313970dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj
314070dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   With the following change: claim that XSaveOpt is not available, by
314170dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   cpuid(eax=0xD,ecx=1).eax[0] returns 0, compared to 1 on the real
314270dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   CPU.  Consequently, programs that correctly observe these CPUID
314370dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   values should only try to use 3 of the 8 XSave-family instructions:
314470dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   XGETBV, XSAVE and XRSTOR.  In particular this avoids having to
314570dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   implement the compacted or optimised save/restore variants.
314670dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj
314770dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   vendor_id       : GenuineIntel
314870dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   cpu family      : 6
314970dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   model           : 60
315070dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   model name      : Intel(R) Core(TM) i7-4910MQ CPU @ 2.90GHz
315170dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   stepping        : 3
315270dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   microcode       : 0x1c
315370dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   cpu MHz         : 919.957
315470dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   cache size      : 8192 KB
315570dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   physical id     : 0
315670dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   siblings        : 4
315770dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   core id         : 3
315870dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   cpu cores       : 4
315970dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   apicid          : 6
316070dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   initial apicid  : 6
316170dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   fpu             : yes
316270dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   fpu_exception   : yes
316370dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   cpuid level     : 13
316470dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   wp              : yes
316570dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca
316670dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj                     cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht
316770dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj                     tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc
316870dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj                     arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc
316970dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj                     aperfmperf eagerfpu pni pclmulqdq dtes64 monitor ds_cpl
317070dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj                     vmx smx est tm2 ssse3 fma cx16 xtpr pdcm pcid sse4_1
317170dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj                     sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave
317270dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj                     avx f16c rdrand lahf_lm abm ida arat epb pln pts dtherm
317370dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj                     tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust
317470dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj                     bmi1 avx2 smep bmi2 erms invpcid xsaveopt
317570dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   bugs            :
317670dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   bogomips        : 5786.68
317770dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   clflush size    : 64
317870dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   cache_alignment : 64
317970dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   address sizes   : 39 bits physical, 48 bits virtual
318070dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   power management:
318170dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj*/
318270dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardjvoid amd64g_dirtyhelper_CPUID_avx2 ( VexGuestAMD64State* st )
318370dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj{
318470dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj#  define SET_ABCD(_a,_b,_c,_d)                \
318570dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      do { st->guest_RAX = (ULong)(_a);        \
318670dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj           st->guest_RBX = (ULong)(_b);        \
318770dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj           st->guest_RCX = (ULong)(_c);        \
318870dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj           st->guest_RDX = (ULong)(_d);        \
318970dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      } while (0)
319070dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj
319170dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   UInt old_eax = (UInt)st->guest_RAX;
319270dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   UInt old_ecx = (UInt)st->guest_RCX;
319370dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj
319470dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   switch (old_eax) {
319570dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      case 0x00000000:
319670dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         SET_ABCD(0x0000000d, 0x756e6547, 0x6c65746e, 0x49656e69);
319770dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         break;
319870dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      case 0x00000001:
3199e602fa310dfa91e38a164d4d88603eaa7bdf6b2fmjw         /* Don't advertise RDRAND support, bit 30 in ECX.  */
3200e602fa310dfa91e38a164d4d88603eaa7bdf6b2fmjw         SET_ABCD(0x000306c3, 0x02100800, 0x3ffafbff, 0xbfebfbff);
320170dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         break;
320270dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      case 0x00000002:
320370dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         SET_ABCD(0x76036301, 0x00f0b6ff, 0x00000000, 0x00c10000);
320470dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         break;
320570dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      case 0x00000003:
320670dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
320770dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         break;
320870dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      case 0x00000004:
320970dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         switch (old_ecx) {
321070dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj            case 0x00000000: SET_ABCD(0x1c004121, 0x01c0003f,
321170dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj                                      0x0000003f, 0x00000000); break;
321270dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj            case 0x00000001: SET_ABCD(0x1c004122, 0x01c0003f,
321370dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj                                      0x0000003f, 0x00000000); break;
321470dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj            case 0x00000002: SET_ABCD(0x1c004143, 0x01c0003f,
321570dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj                                      0x000001ff, 0x00000000); break;
321670dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj            case 0x00000003: SET_ABCD(0x1c03c163, 0x03c0003f,
321770dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj                                      0x00001fff, 0x00000006); break;
321870dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj            default:         SET_ABCD(0x00000000, 0x00000000,
321970dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj                                      0x00000000, 0x00000000); break;
322070dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         }
322170dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         break;
322270dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      case 0x00000005:
322370dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         SET_ABCD(0x00000040, 0x00000040, 0x00000003, 0x00042120);
322470dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         break;
322570dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      case 0x00000006:
322670dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         SET_ABCD(0x00000077, 0x00000002, 0x00000009, 0x00000000);
322770dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         break;
322870dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      case 0x00000007:
322970dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         switch (old_ecx) {
323070dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj            case 0x00000000: SET_ABCD(0x00000000, 0x000027ab,
323170dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj                                      0x00000000, 0x00000000); break;
323270dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj            default:         SET_ABCD(0x00000000, 0x00000000,
323370dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj                                      0x00000000, 0x00000000); break;
323470dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         }
323570dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         break;
323670dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      case 0x00000008:
323770dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
323870dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         break;
323970dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      case 0x00000009:
324070dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
324170dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         break;
324270dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      case 0x0000000a:
324370dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         SET_ABCD(0x07300803, 0x00000000, 0x00000000, 0x00000603);
324470dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         break;
324570dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      case 0x0000000b:
324670dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         switch (old_ecx) {
324770dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj            case 0x00000000: SET_ABCD(0x00000001, 0x00000002,
324870dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj                                      0x00000100, 0x00000002); break;
324970dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj            case 0x00000001: SET_ABCD(0x00000004, 0x00000008,
325070dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj                                      0x00000201, 0x00000002); break;
325170dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj            default:         SET_ABCD(0x00000000, 0x00000000,
325270dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj                                      old_ecx,    0x00000002); break;
325370dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         }
325470dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         break;
325570dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      case 0x0000000c:
325670dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
325770dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         break;
325870dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      case 0x0000000d:
325970dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         switch (old_ecx) {
326070dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj            case 0x00000000: SET_ABCD(0x00000007, 0x00000340,
326170dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj                                      0x00000340, 0x00000000); break;
326270dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj            case 0x00000001: SET_ABCD(0x00000000, 0x00000000,
326370dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj                                      0x00000000, 0x00000000); break;
326470dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj            case 0x00000002: SET_ABCD(0x00000100, 0x00000240,
326570dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj                                      0x00000000, 0x00000000); break;
326670dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj            default:         SET_ABCD(0x00000000, 0x00000000,
326770dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj                                      0x00000000, 0x00000000); break;
326870dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         }
326970dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         break;
327070dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      case 0x80000000:
327170dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         SET_ABCD(0x80000008, 0x00000000, 0x00000000, 0x00000000);
327270dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         break;
327370dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      case 0x80000001:
327470dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         SET_ABCD(0x00000000, 0x00000000, 0x00000021, 0x2c100800);
327570dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         break;
327670dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      case 0x80000002:
327770dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         SET_ABCD(0x65746e49, 0x2952286c, 0x726f4320, 0x4d542865);
327870dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         break;
327970dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      case 0x80000003:
328070dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         SET_ABCD(0x37692029, 0x3139342d, 0x20514d30, 0x20555043);
328170dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         break;
328270dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      case 0x80000004:
328370dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         SET_ABCD(0x2e322040, 0x48473039, 0x0000007a, 0x00000000);
328470dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         break;
328570dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      case 0x80000005:
328670dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
328770dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         break;
328870dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      case 0x80000006:
328970dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         SET_ABCD(0x00000000, 0x00000000, 0x01006040, 0x00000000);
329070dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         break;
329170dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      case 0x80000007:
329270dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000100);
329370dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         break;
329470dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      case 0x80000008:
329570dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         SET_ABCD(0x00003027, 0x00000000, 0x00000000, 0x00000000);
329670dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         break;
329770dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      default:
329870dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         SET_ABCD(0x00000007, 0x00000340, 0x00000340, 0x00000000);
329970dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         break;
330070dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   }
330170dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj#  undef SET_ABCD
330270dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj}
330370dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj
330470dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj
330570dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj/*---------------------------------------------------------------*/
330670dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj/*--- Misc integer helpers, including rotates and crypto.     ---*/
330770dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj/*---------------------------------------------------------------*/
330870dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj
3309112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardjULong amd64g_calculate_RCR ( ULong arg,
3310112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj                             ULong rot_amt,
3311112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj                             ULong rflags_in,
3312112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj                             Long  szIN )
3313112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj{
3314112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj   Bool  wantRflags = toBool(szIN < 0);
3315112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj   ULong sz         = wantRflags ? (-szIN) : szIN;
3316112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj   ULong tempCOUNT  = rot_amt & (sz == 8 ? 0x3F : 0x1F);
3317112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj   ULong cf=0, of=0, tempcf;
3318112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj
3319112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj   switch (sz) {
3320112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj      case 8:
3321112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj         cf        = (rflags_in >> AMD64G_CC_SHIFT_C) & 1;
3322112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj         of        = ((arg >> 63) ^ cf) & 1;
3323112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj         while (tempCOUNT > 0) {
3324112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj            tempcf = arg & 1;
3325112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj            arg    = (arg >> 1) | (cf << 63);
3326112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj            cf     = tempcf;
3327112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj            tempCOUNT--;
3328112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj         }
3329112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj         break;
3330112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj      case 4:
3331112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj         while (tempCOUNT >= 33) tempCOUNT -= 33;
3332112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj         cf        = (rflags_in >> AMD64G_CC_SHIFT_C) & 1;
3333112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj         of        = ((arg >> 31) ^ cf) & 1;
3334112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj         while (tempCOUNT > 0) {
3335112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj            tempcf = arg & 1;
3336112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj            arg    = ((arg >> 1) & 0x7FFFFFFFULL) | (cf << 31);
3337112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj            cf     = tempcf;
3338112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj            tempCOUNT--;
3339112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj         }
3340112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj         break;
3341112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj      case 2:
3342112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj         while (tempCOUNT >= 17) tempCOUNT -= 17;
3343112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj         cf        = (rflags_in >> AMD64G_CC_SHIFT_C) & 1;
3344112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj         of        = ((arg >> 15) ^ cf) & 1;
3345112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj         while (tempCOUNT > 0) {
3346112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj            tempcf = arg & 1;
3347112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj            arg    = ((arg >> 1) & 0x7FFFULL) | (cf << 15);
3348112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj            cf     = tempcf;
3349112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj            tempCOUNT--;
3350112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj         }
3351112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj         break;
3352112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj      case 1:
3353112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj         while (tempCOUNT >= 9) tempCOUNT -= 9;
3354112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj         cf        = (rflags_in >> AMD64G_CC_SHIFT_C) & 1;
3355112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj         of        = ((arg >> 7) ^ cf) & 1;
3356112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj         while (tempCOUNT > 0) {
3357112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj            tempcf = arg & 1;
3358112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj            arg    = ((arg >> 1) & 0x7FULL) | (cf << 7);
3359112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj            cf     = tempcf;
3360112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj            tempCOUNT--;
3361112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj         }
3362112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj         break;
3363112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj      default:
3364112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj         vpanic("calculate_RCR(amd64g): invalid size");
3365112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj   }
3366112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj
3367112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj   cf &= 1;
3368112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj   of &= 1;
3369112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj   rflags_in &= ~(AMD64G_CC_MASK_C | AMD64G_CC_MASK_O);
3370112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj   rflags_in |= (cf << AMD64G_CC_SHIFT_C) | (of << AMD64G_CC_SHIFT_O);
3371112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj
3372112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj   /* caller can ask to have back either the resulting flags or
3373112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj      resulting value, but not both */
3374112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj   return wantRflags ? rflags_in : arg;
3375112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj}
3376112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj
3377b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardjULong amd64g_calculate_RCL ( ULong arg,
3378b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj                             ULong rot_amt,
3379b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj                             ULong rflags_in,
3380b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj                             Long  szIN )
3381b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj{
3382b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj   Bool  wantRflags = toBool(szIN < 0);
3383b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj   ULong sz         = wantRflags ? (-szIN) : szIN;
3384b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj   ULong tempCOUNT  = rot_amt & (sz == 8 ? 0x3F : 0x1F);
3385b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj   ULong cf=0, of=0, tempcf;
3386b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj
3387b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj   switch (sz) {
3388b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj      case 8:
3389b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj         cf = (rflags_in >> AMD64G_CC_SHIFT_C) & 1;
3390b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj         while (tempCOUNT > 0) {
3391b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj            tempcf = (arg >> 63) & 1;
3392b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj            arg    = (arg << 1) | (cf & 1);
3393b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj            cf     = tempcf;
3394b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj            tempCOUNT--;
3395b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj         }
3396b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj         of = ((arg >> 63) ^ cf) & 1;
3397b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj         break;
3398b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj      case 4:
3399b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj         while (tempCOUNT >= 33) tempCOUNT -= 33;
3400b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj         cf = (rflags_in >> AMD64G_CC_SHIFT_C) & 1;
3401b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj         while (tempCOUNT > 0) {
3402b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj            tempcf = (arg >> 31) & 1;
3403b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj            arg    = 0xFFFFFFFFULL & ((arg << 1) | (cf & 1));
3404b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj            cf     = tempcf;
3405b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj            tempCOUNT--;
3406b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj         }
3407b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj         of = ((arg >> 31) ^ cf) & 1;
3408b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj         break;
3409b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj      case 2:
3410b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj         while (tempCOUNT >= 17) tempCOUNT -= 17;
3411b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj         cf = (rflags_in >> AMD64G_CC_SHIFT_C) & 1;
3412b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj         while (tempCOUNT > 0) {
3413b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj            tempcf = (arg >> 15) & 1;
3414b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj            arg    = 0xFFFFULL & ((arg << 1) | (cf & 1));
3415b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj            cf     = tempcf;
3416b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj            tempCOUNT--;
3417b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj         }
3418b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj         of = ((arg >> 15) ^ cf) & 1;
3419b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj         break;
3420b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj      case 1:
3421b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj         while (tempCOUNT >= 9) tempCOUNT -= 9;
3422b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj         cf = (rflags_in >> AMD64G_CC_SHIFT_C) & 1;
3423b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj         while (tempCOUNT > 0) {
3424b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj            tempcf = (arg >> 7) & 1;
3425b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj            arg    = 0xFFULL & ((arg << 1) | (cf & 1));
3426b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj            cf     = tempcf;
3427b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj            tempCOUNT--;
3428b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj         }
3429b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj         of = ((arg >> 7) ^ cf) & 1;
3430b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj         break;
3431b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj      default:
3432b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj         vpanic("calculate_RCL(amd64g): invalid size");
3433b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj   }
3434b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj
3435b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj   cf &= 1;
3436b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj   of &= 1;
3437b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj   rflags_in &= ~(AMD64G_CC_MASK_C | AMD64G_CC_MASK_O);
3438b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj   rflags_in |= (cf << AMD64G_CC_SHIFT_C) | (of << AMD64G_CC_SHIFT_O);
3439b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj
3440b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj   return wantRflags ? rflags_in : arg;
3441b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj}
3442b5e5c6ddb5ebc23c19494c2e3a8e8b9a6b36a04asewardj
34431a179b5d699c167427e6a1f37ec01ba66674b2e1sewardj/* Taken from gf2x-0.9.5, released under GPLv2+ (later versions LGPLv2+)
34441a179b5d699c167427e6a1f37ec01ba66674b2e1sewardj * svn://scm.gforge.inria.fr/svn/gf2x/trunk/hardware/opteron/gf2x_mul1.h@25
34451a179b5d699c167427e6a1f37ec01ba66674b2e1sewardj */
34461a179b5d699c167427e6a1f37ec01ba66674b2e1sewardjULong amd64g_calculate_pclmul(ULong a, ULong b, ULong which)
34471a179b5d699c167427e6a1f37ec01ba66674b2e1sewardj{
34481a179b5d699c167427e6a1f37ec01ba66674b2e1sewardj    ULong hi, lo, tmp, A[16];
34491a179b5d699c167427e6a1f37ec01ba66674b2e1sewardj
34501a179b5d699c167427e6a1f37ec01ba66674b2e1sewardj   A[0] = 0;            A[1] = a;
34511a179b5d699c167427e6a1f37ec01ba66674b2e1sewardj   A[2] = A[1] << 1;    A[3] = A[2] ^ a;
34521a179b5d699c167427e6a1f37ec01ba66674b2e1sewardj   A[4] = A[2] << 1;    A[5] = A[4] ^ a;
34531a179b5d699c167427e6a1f37ec01ba66674b2e1sewardj   A[6] = A[3] << 1;    A[7] = A[6] ^ a;
34541a179b5d699c167427e6a1f37ec01ba66674b2e1sewardj   A[8] = A[4] << 1;    A[9] = A[8] ^ a;
34551a179b5d699c167427e6a1f37ec01ba66674b2e1sewardj   A[10] = A[5] << 1;   A[11] = A[10] ^ a;
34561a179b5d699c167427e6a1f37ec01ba66674b2e1sewardj   A[12] = A[6] << 1;   A[13] = A[12] ^ a;
34571a179b5d699c167427e6a1f37ec01ba66674b2e1sewardj   A[14] = A[7] << 1;   A[15] = A[14] ^ a;
34581a179b5d699c167427e6a1f37ec01ba66674b2e1sewardj
34591a179b5d699c167427e6a1f37ec01ba66674b2e1sewardj   lo = (A[b >> 60] << 4) ^ A[(b >> 56) & 15];
34601a179b5d699c167427e6a1f37ec01ba66674b2e1sewardj   hi = lo >> 56;
34611a179b5d699c167427e6a1f37ec01ba66674b2e1sewardj   lo = (lo << 8) ^ (A[(b >> 52) & 15] << 4) ^ A[(b >> 48) & 15];
34621a179b5d699c167427e6a1f37ec01ba66674b2e1sewardj   hi = (hi << 8) | (lo >> 56);
34631a179b5d699c167427e6a1f37ec01ba66674b2e1sewardj   lo = (lo << 8) ^ (A[(b >> 44) & 15] << 4) ^ A[(b >> 40) & 15];
34641a179b5d699c167427e6a1f37ec01ba66674b2e1sewardj   hi = (hi << 8) | (lo >> 56);
34651a179b5d699c167427e6a1f37ec01ba66674b2e1sewardj   lo = (lo << 8) ^ (A[(b >> 36) & 15] << 4) ^ A[(b >> 32) & 15];
34661a179b5d699c167427e6a1f37ec01ba66674b2e1sewardj   hi = (hi << 8) | (lo >> 56);
34671a179b5d699c167427e6a1f37ec01ba66674b2e1sewardj   lo = (lo << 8) ^ (A[(b >> 28) & 15] << 4) ^ A[(b >> 24) & 15];
34681a179b5d699c167427e6a1f37ec01ba66674b2e1sewardj   hi = (hi << 8) | (lo >> 56);
34691a179b5d699c167427e6a1f37ec01ba66674b2e1sewardj   lo = (lo << 8) ^ (A[(b >> 20) & 15] << 4) ^ A[(b >> 16) & 15];
34701a179b5d699c167427e6a1f37ec01ba66674b2e1sewardj   hi = (hi << 8) | (lo >> 56);
34711a179b5d699c167427e6a1f37ec01ba66674b2e1sewardj   lo = (lo << 8) ^ (A[(b >> 12) & 15] << 4) ^ A[(b >> 8) & 15];
34721a179b5d699c167427e6a1f37ec01ba66674b2e1sewardj   hi = (hi << 8) | (lo >> 56);
34731a179b5d699c167427e6a1f37ec01ba66674b2e1sewardj   lo = (lo << 8) ^ (A[(b >> 4) & 15] << 4) ^ A[b & 15];
34741a179b5d699c167427e6a1f37ec01ba66674b2e1sewardj
34751a179b5d699c167427e6a1f37ec01ba66674b2e1sewardj   ULong m0 = -1;
34761a179b5d699c167427e6a1f37ec01ba66674b2e1sewardj   m0 /= 255;
34771a179b5d699c167427e6a1f37ec01ba66674b2e1sewardj   tmp = -((a >> 63) & 1); tmp &= ((b & (m0 * 0xfe)) >> 1); hi = hi ^ tmp;
34781a179b5d699c167427e6a1f37ec01ba66674b2e1sewardj   tmp = -((a >> 62) & 1); tmp &= ((b & (m0 * 0xfc)) >> 2); hi = hi ^ tmp;
34791a179b5d699c167427e6a1f37ec01ba66674b2e1sewardj   tmp = -((a >> 61) & 1); tmp &= ((b & (m0 * 0xf8)) >> 3); hi = hi ^ tmp;
34801a179b5d699c167427e6a1f37ec01ba66674b2e1sewardj   tmp = -((a >> 60) & 1); tmp &= ((b & (m0 * 0xf0)) >> 4); hi = hi ^ tmp;
34811a179b5d699c167427e6a1f37ec01ba66674b2e1sewardj   tmp = -((a >> 59) & 1); tmp &= ((b & (m0 * 0xe0)) >> 5); hi = hi ^ tmp;
34821a179b5d699c167427e6a1f37ec01ba66674b2e1sewardj   tmp = -((a >> 58) & 1); tmp &= ((b & (m0 * 0xc0)) >> 6); hi = hi ^ tmp;
34831a179b5d699c167427e6a1f37ec01ba66674b2e1sewardj   tmp = -((a >> 57) & 1); tmp &= ((b & (m0 * 0x80)) >> 7); hi = hi ^ tmp;
34841a179b5d699c167427e6a1f37ec01ba66674b2e1sewardj
34851a179b5d699c167427e6a1f37ec01ba66674b2e1sewardj   return which ? hi : lo;
34861a179b5d699c167427e6a1f37ec01ba66674b2e1sewardj}
34871a179b5d699c167427e6a1f37ec01ba66674b2e1sewardj
3488112b09931d68ea3bf991ad5582f5fe0c7e481ae2sewardj
3489bc6af53b0ac9e4199fbbfde77c275fa04f2841bfsewardj/* CALLED FROM GENERATED CODE */
3490bc6af53b0ac9e4199fbbfde77c275fa04f2841bfsewardj/* DIRTY HELPER (non-referentially-transparent) */
3491bc6af53b0ac9e4199fbbfde77c275fa04f2841bfsewardj/* Horrible hack.  On non-amd64 platforms, return 1. */
3492bc6af53b0ac9e4199fbbfde77c275fa04f2841bfsewardjULong amd64g_dirtyhelper_RDTSC ( void )
3493bc6af53b0ac9e4199fbbfde77c275fa04f2841bfsewardj{
3494bc6af53b0ac9e4199fbbfde77c275fa04f2841bfsewardj#  if defined(__x86_64__)
3495bc6af53b0ac9e4199fbbfde77c275fa04f2841bfsewardj   UInt  eax, edx;
3496bc6af53b0ac9e4199fbbfde77c275fa04f2841bfsewardj   __asm__ __volatile__("rdtsc" : "=a" (eax), "=d" (edx));
3497bc6af53b0ac9e4199fbbfde77c275fa04f2841bfsewardj   return (((ULong)edx) << 32) | ((ULong)eax);
3498bc6af53b0ac9e4199fbbfde77c275fa04f2841bfsewardj#  else
3499bc6af53b0ac9e4199fbbfde77c275fa04f2841bfsewardj   return 1ULL;
3500bc6af53b0ac9e4199fbbfde77c275fa04f2841bfsewardj#  endif
3501bc6af53b0ac9e4199fbbfde77c275fa04f2841bfsewardj}
3502bc6af53b0ac9e4199fbbfde77c275fa04f2841bfsewardj
3503818c730f624828ef2d5532e32e952924094b699esewardj/* CALLED FROM GENERATED CODE */
3504818c730f624828ef2d5532e32e952924094b699esewardj/* DIRTY HELPER (non-referentially-transparent) */
3505818c730f624828ef2d5532e32e952924094b699esewardj/* Horrible hack.  On non-amd64 platforms, return 1. */
3506818c730f624828ef2d5532e32e952924094b699esewardj/* This uses a different calling convention from _RDTSC just above
3507818c730f624828ef2d5532e32e952924094b699esewardj   only because of the difficulty of returning 96 bits from a C
3508818c730f624828ef2d5532e32e952924094b699esewardj   function -- RDTSC returns 64 bits and so is simple by comparison,
3509818c730f624828ef2d5532e32e952924094b699esewardj   on amd64. */
3510818c730f624828ef2d5532e32e952924094b699esewardjvoid amd64g_dirtyhelper_RDTSCP ( VexGuestAMD64State* st )
3511818c730f624828ef2d5532e32e952924094b699esewardj{
3512818c730f624828ef2d5532e32e952924094b699esewardj#  if defined(__x86_64__)
3513818c730f624828ef2d5532e32e952924094b699esewardj   UInt eax, ecx, edx;
3514818c730f624828ef2d5532e32e952924094b699esewardj   __asm__ __volatile__("rdtscp" : "=a" (eax), "=d" (edx), "=c" (ecx));
3515818c730f624828ef2d5532e32e952924094b699esewardj   st->guest_RAX = (ULong)eax;
3516818c730f624828ef2d5532e32e952924094b699esewardj   st->guest_RCX = (ULong)ecx;
3517818c730f624828ef2d5532e32e952924094b699esewardj   st->guest_RDX = (ULong)edx;
3518818c730f624828ef2d5532e32e952924094b699esewardj#  else
3519818c730f624828ef2d5532e32e952924094b699esewardj   /* Do nothing. */
3520818c730f624828ef2d5532e32e952924094b699esewardj#  endif
3521818c730f624828ef2d5532e32e952924094b699esewardj}
3522bc6af53b0ac9e4199fbbfde77c275fa04f2841bfsewardj
3523bb4396c768958b79f0ec1f737fe457aad984a0absewardj/* CALLED FROM GENERATED CODE */
3524bb4396c768958b79f0ec1f737fe457aad984a0absewardj/* DIRTY HELPER (non-referentially-transparent) */
3525bb4396c768958b79f0ec1f737fe457aad984a0absewardj/* Horrible hack.  On non-amd64 platforms, return 0. */
3526bb4396c768958b79f0ec1f737fe457aad984a0absewardjULong amd64g_dirtyhelper_IN ( ULong portno, ULong sz/*1,2 or 4*/ )
3527bb4396c768958b79f0ec1f737fe457aad984a0absewardj{
3528bb4396c768958b79f0ec1f737fe457aad984a0absewardj#  if defined(__x86_64__)
3529bb4396c768958b79f0ec1f737fe457aad984a0absewardj   ULong r = 0;
3530bb4396c768958b79f0ec1f737fe457aad984a0absewardj   portno &= 0xFFFF;
3531bb4396c768958b79f0ec1f737fe457aad984a0absewardj   switch (sz) {
3532bb4396c768958b79f0ec1f737fe457aad984a0absewardj      case 4:
3533bb4396c768958b79f0ec1f737fe457aad984a0absewardj         __asm__ __volatile__("movq $0,%%rax; inl %w1,%%eax; movq %%rax,%0"
3534bb4396c768958b79f0ec1f737fe457aad984a0absewardj                              : "=a" (r) : "Nd" (portno));
3535bb4396c768958b79f0ec1f737fe457aad984a0absewardj	 break;
3536bb4396c768958b79f0ec1f737fe457aad984a0absewardj      case 2:
3537bb4396c768958b79f0ec1f737fe457aad984a0absewardj         __asm__ __volatile__("movq $0,%%rax; inw %w1,%w0"
3538bb4396c768958b79f0ec1f737fe457aad984a0absewardj                              : "=a" (r) : "Nd" (portno));
3539bb4396c768958b79f0ec1f737fe457aad984a0absewardj	 break;
3540bb4396c768958b79f0ec1f737fe457aad984a0absewardj      case 1:
3541bb4396c768958b79f0ec1f737fe457aad984a0absewardj         __asm__ __volatile__("movq $0,%%rax; inb %w1,%b0"
3542bb4396c768958b79f0ec1f737fe457aad984a0absewardj                              : "=a" (r) : "Nd" (portno));
3543bb4396c768958b79f0ec1f737fe457aad984a0absewardj	 break;
3544bb4396c768958b79f0ec1f737fe457aad984a0absewardj      default:
3545bb4396c768958b79f0ec1f737fe457aad984a0absewardj         break; /* note: no 64-bit version of insn exists */
3546bb4396c768958b79f0ec1f737fe457aad984a0absewardj   }
3547bb4396c768958b79f0ec1f737fe457aad984a0absewardj   return r;
3548bb4396c768958b79f0ec1f737fe457aad984a0absewardj#  else
3549bb4396c768958b79f0ec1f737fe457aad984a0absewardj   return 0;
3550bb4396c768958b79f0ec1f737fe457aad984a0absewardj#  endif
3551bb4396c768958b79f0ec1f737fe457aad984a0absewardj}
3552bb4396c768958b79f0ec1f737fe457aad984a0absewardj
3553bb4396c768958b79f0ec1f737fe457aad984a0absewardj
3554bb4396c768958b79f0ec1f737fe457aad984a0absewardj/* CALLED FROM GENERATED CODE */
3555bb4396c768958b79f0ec1f737fe457aad984a0absewardj/* DIRTY HELPER (non-referentially-transparent) */
3556bb4396c768958b79f0ec1f737fe457aad984a0absewardj/* Horrible hack.  On non-amd64 platforms, do nothing. */
3557bb4396c768958b79f0ec1f737fe457aad984a0absewardjvoid amd64g_dirtyhelper_OUT ( ULong portno, ULong data, ULong sz/*1,2 or 4*/ )
3558bb4396c768958b79f0ec1f737fe457aad984a0absewardj{
3559bb4396c768958b79f0ec1f737fe457aad984a0absewardj#  if defined(__x86_64__)
3560bb4396c768958b79f0ec1f737fe457aad984a0absewardj   portno &= 0xFFFF;
3561bb4396c768958b79f0ec1f737fe457aad984a0absewardj   switch (sz) {
3562bb4396c768958b79f0ec1f737fe457aad984a0absewardj      case 4:
3563bb4396c768958b79f0ec1f737fe457aad984a0absewardj         __asm__ __volatile__("movq %0,%%rax; outl %%eax, %w1"
3564bb4396c768958b79f0ec1f737fe457aad984a0absewardj                              : : "a" (data), "Nd" (portno));
3565bb4396c768958b79f0ec1f737fe457aad984a0absewardj	 break;
3566bb4396c768958b79f0ec1f737fe457aad984a0absewardj      case 2:
3567bb4396c768958b79f0ec1f737fe457aad984a0absewardj         __asm__ __volatile__("outw %w0, %w1"
3568bb4396c768958b79f0ec1f737fe457aad984a0absewardj                              : : "a" (data), "Nd" (portno));
3569bb4396c768958b79f0ec1f737fe457aad984a0absewardj	 break;
3570bb4396c768958b79f0ec1f737fe457aad984a0absewardj      case 1:
3571bb4396c768958b79f0ec1f737fe457aad984a0absewardj         __asm__ __volatile__("outb %b0, %w1"
3572bb4396c768958b79f0ec1f737fe457aad984a0absewardj                              : : "a" (data), "Nd" (portno));
3573bb4396c768958b79f0ec1f737fe457aad984a0absewardj	 break;
3574bb4396c768958b79f0ec1f737fe457aad984a0absewardj      default:
3575bb4396c768958b79f0ec1f737fe457aad984a0absewardj         break; /* note: no 64-bit version of insn exists */
3576bb4396c768958b79f0ec1f737fe457aad984a0absewardj   }
3577bb4396c768958b79f0ec1f737fe457aad984a0absewardj#  else
3578bb4396c768958b79f0ec1f737fe457aad984a0absewardj   /* do nothing */
3579bb4396c768958b79f0ec1f737fe457aad984a0absewardj#  endif
3580bb4396c768958b79f0ec1f737fe457aad984a0absewardj}
3581bb4396c768958b79f0ec1f737fe457aad984a0absewardj
3582b9dc2430577bddf8c42e3d3fbe887c32cada9130sewardj/* CALLED FROM GENERATED CODE */
3583b9dc2430577bddf8c42e3d3fbe887c32cada9130sewardj/* DIRTY HELPER (non-referentially-transparent) */
3584b9dc2430577bddf8c42e3d3fbe887c32cada9130sewardj/* Horrible hack.  On non-amd64 platforms, do nothing. */
3585b9dc2430577bddf8c42e3d3fbe887c32cada9130sewardj/* op = 0: call the native SGDT instruction.
3586b9dc2430577bddf8c42e3d3fbe887c32cada9130sewardj   op = 1: call the native SIDT instruction.
3587b9dc2430577bddf8c42e3d3fbe887c32cada9130sewardj*/
3588b9dc2430577bddf8c42e3d3fbe887c32cada9130sewardjvoid amd64g_dirtyhelper_SxDT ( void *address, ULong op ) {
3589b9dc2430577bddf8c42e3d3fbe887c32cada9130sewardj#  if defined(__x86_64__)
3590b9dc2430577bddf8c42e3d3fbe887c32cada9130sewardj   switch (op) {
3591b9dc2430577bddf8c42e3d3fbe887c32cada9130sewardj      case 0:
3592b9dc2430577bddf8c42e3d3fbe887c32cada9130sewardj         __asm__ __volatile__("sgdt (%0)" : : "r" (address) : "memory");
3593b9dc2430577bddf8c42e3d3fbe887c32cada9130sewardj         break;
3594b9dc2430577bddf8c42e3d3fbe887c32cada9130sewardj      case 1:
3595b9dc2430577bddf8c42e3d3fbe887c32cada9130sewardj         __asm__ __volatile__("sidt (%0)" : : "r" (address) : "memory");
3596b9dc2430577bddf8c42e3d3fbe887c32cada9130sewardj         break;
3597b9dc2430577bddf8c42e3d3fbe887c32cada9130sewardj      default:
3598b9dc2430577bddf8c42e3d3fbe887c32cada9130sewardj         vpanic("amd64g_dirtyhelper_SxDT");
3599b9dc2430577bddf8c42e3d3fbe887c32cada9130sewardj   }
3600b9dc2430577bddf8c42e3d3fbe887c32cada9130sewardj#  else
3601b9dc2430577bddf8c42e3d3fbe887c32cada9130sewardj   /* do nothing */
3602b9dc2430577bddf8c42e3d3fbe887c32cada9130sewardj   UChar* p = (UChar*)address;
3603b9dc2430577bddf8c42e3d3fbe887c32cada9130sewardj   p[0] = p[1] = p[2] = p[3] = p[4] = p[5] = 0;
3604b9dc2430577bddf8c42e3d3fbe887c32cada9130sewardj   p[6] = p[7] = p[8] = p[9] = 0;
3605b9dc2430577bddf8c42e3d3fbe887c32cada9130sewardj#  endif
3606b9dc2430577bddf8c42e3d3fbe887c32cada9130sewardj}
3607bb4396c768958b79f0ec1f737fe457aad984a0absewardj
36088711f665fcdcfa7cc49e06eb6ec4f27de1e4efafsewardj/*---------------------------------------------------------------*/
36098711f665fcdcfa7cc49e06eb6ec4f27de1e4efafsewardj/*--- Helpers for MMX/SSE/SSE2.                               ---*/
36108711f665fcdcfa7cc49e06eb6ec4f27de1e4efafsewardj/*---------------------------------------------------------------*/
36118711f665fcdcfa7cc49e06eb6ec4f27de1e4efafsewardj
3612a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardjstatic inline UChar abdU8 ( UChar xx, UChar yy ) {
3613a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj   return toUChar(xx>yy ? xx-yy : yy-xx);
3614a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj}
3615a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj
36168711f665fcdcfa7cc49e06eb6ec4f27de1e4efafsewardjstatic inline ULong mk32x2 ( UInt w1, UInt w0 ) {
36178711f665fcdcfa7cc49e06eb6ec4f27de1e4efafsewardj   return (((ULong)w1) << 32) | ((ULong)w0);
36188711f665fcdcfa7cc49e06eb6ec4f27de1e4efafsewardj}
36198711f665fcdcfa7cc49e06eb6ec4f27de1e4efafsewardj
36208711f665fcdcfa7cc49e06eb6ec4f27de1e4efafsewardjstatic inline UShort sel16x4_3 ( ULong w64 ) {
36218711f665fcdcfa7cc49e06eb6ec4f27de1e4efafsewardj   UInt hi32 = toUInt(w64 >> 32);
36228711f665fcdcfa7cc49e06eb6ec4f27de1e4efafsewardj   return toUShort(hi32 >> 16);
36238711f665fcdcfa7cc49e06eb6ec4f27de1e4efafsewardj}
36248711f665fcdcfa7cc49e06eb6ec4f27de1e4efafsewardjstatic inline UShort sel16x4_2 ( ULong w64 ) {
36258711f665fcdcfa7cc49e06eb6ec4f27de1e4efafsewardj   UInt hi32 = toUInt(w64 >> 32);
36268711f665fcdcfa7cc49e06eb6ec4f27de1e4efafsewardj   return toUShort(hi32);
36278711f665fcdcfa7cc49e06eb6ec4f27de1e4efafsewardj}
36288711f665fcdcfa7cc49e06eb6ec4f27de1e4efafsewardjstatic inline UShort sel16x4_1 ( ULong w64 ) {
36298711f665fcdcfa7cc49e06eb6ec4f27de1e4efafsewardj   UInt lo32 = toUInt(w64);
36308711f665fcdcfa7cc49e06eb6ec4f27de1e4efafsewardj   return toUShort(lo32 >> 16);
36318711f665fcdcfa7cc49e06eb6ec4f27de1e4efafsewardj}
36328711f665fcdcfa7cc49e06eb6ec4f27de1e4efafsewardjstatic inline UShort sel16x4_0 ( ULong w64 ) {
36338711f665fcdcfa7cc49e06eb6ec4f27de1e4efafsewardj   UInt lo32 = toUInt(w64);
36348711f665fcdcfa7cc49e06eb6ec4f27de1e4efafsewardj   return toUShort(lo32);
36358711f665fcdcfa7cc49e06eb6ec4f27de1e4efafsewardj}
36368711f665fcdcfa7cc49e06eb6ec4f27de1e4efafsewardj
3637a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardjstatic inline UChar sel8x8_7 ( ULong w64 ) {
3638a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj   UInt hi32 = toUInt(w64 >> 32);
3639a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj   return toUChar(hi32 >> 24);
3640a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj}
3641a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardjstatic inline UChar sel8x8_6 ( ULong w64 ) {
3642a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj   UInt hi32 = toUInt(w64 >> 32);
3643a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj   return toUChar(hi32 >> 16);
3644a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj}
3645a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardjstatic inline UChar sel8x8_5 ( ULong w64 ) {
3646a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj   UInt hi32 = toUInt(w64 >> 32);
3647a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj   return toUChar(hi32 >> 8);
3648a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj}
3649a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardjstatic inline UChar sel8x8_4 ( ULong w64 ) {
3650a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj   UInt hi32 = toUInt(w64 >> 32);
3651a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj   return toUChar(hi32 >> 0);
3652a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj}
3653a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardjstatic inline UChar sel8x8_3 ( ULong w64 ) {
3654a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj   UInt lo32 = toUInt(w64);
3655a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj   return toUChar(lo32 >> 24);
3656a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj}
3657a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardjstatic inline UChar sel8x8_2 ( ULong w64 ) {
3658a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj   UInt lo32 = toUInt(w64);
3659a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj   return toUChar(lo32 >> 16);
3660a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj}
3661a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardjstatic inline UChar sel8x8_1 ( ULong w64 ) {
3662a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj   UInt lo32 = toUInt(w64);
3663a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj   return toUChar(lo32 >> 8);
3664a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj}
3665a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardjstatic inline UChar sel8x8_0 ( ULong w64 ) {
3666a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj   UInt lo32 = toUInt(w64);
3667a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj   return toUChar(lo32 >> 0);
3668a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj}
3669a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj
36708711f665fcdcfa7cc49e06eb6ec4f27de1e4efafsewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
36718711f665fcdcfa7cc49e06eb6ec4f27de1e4efafsewardjULong amd64g_calculate_mmx_pmaddwd ( ULong xx, ULong yy )
36728711f665fcdcfa7cc49e06eb6ec4f27de1e4efafsewardj{
36738711f665fcdcfa7cc49e06eb6ec4f27de1e4efafsewardj   return
36748711f665fcdcfa7cc49e06eb6ec4f27de1e4efafsewardj      mk32x2(
36758711f665fcdcfa7cc49e06eb6ec4f27de1e4efafsewardj         (((Int)(Short)sel16x4_3(xx)) * ((Int)(Short)sel16x4_3(yy)))
36768711f665fcdcfa7cc49e06eb6ec4f27de1e4efafsewardj            + (((Int)(Short)sel16x4_2(xx)) * ((Int)(Short)sel16x4_2(yy))),
36778711f665fcdcfa7cc49e06eb6ec4f27de1e4efafsewardj         (((Int)(Short)sel16x4_1(xx)) * ((Int)(Short)sel16x4_1(yy)))
36788711f665fcdcfa7cc49e06eb6ec4f27de1e4efafsewardj            + (((Int)(Short)sel16x4_0(xx)) * ((Int)(Short)sel16x4_0(yy)))
36798711f665fcdcfa7cc49e06eb6ec4f27de1e4efafsewardj      );
36808711f665fcdcfa7cc49e06eb6ec4f27de1e4efafsewardj}
36818711f665fcdcfa7cc49e06eb6ec4f27de1e4efafsewardj
3682a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
3683a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardjULong amd64g_calculate_mmx_psadbw ( ULong xx, ULong yy )
3684a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj{
3685a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj   UInt t = 0;
3686a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj   t += (UInt)abdU8( sel8x8_7(xx), sel8x8_7(yy) );
3687a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj   t += (UInt)abdU8( sel8x8_6(xx), sel8x8_6(yy) );
3688a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj   t += (UInt)abdU8( sel8x8_5(xx), sel8x8_5(yy) );
3689a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj   t += (UInt)abdU8( sel8x8_4(xx), sel8x8_4(yy) );
3690a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj   t += (UInt)abdU8( sel8x8_3(xx), sel8x8_3(yy) );
3691a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj   t += (UInt)abdU8( sel8x8_2(xx), sel8x8_2(yy) );
3692a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj   t += (UInt)abdU8( sel8x8_1(xx), sel8x8_1(yy) );
3693a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj   t += (UInt)abdU8( sel8x8_0(xx), sel8x8_0(yy) );
3694a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj   t &= 0xFFFF;
3695a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj   return (ULong)t;
3696a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj}
3697a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj
3698adffcef004712e8afc6a7d87b30ef90e4685df40sewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
36998cb931eee8a5567a7d2b7eee011ebc4757474910sewardjULong amd64g_calculate_sse_phminposuw ( ULong sLo, ULong sHi )
37008cb931eee8a5567a7d2b7eee011ebc4757474910sewardj{
37018cb931eee8a5567a7d2b7eee011ebc4757474910sewardj   UShort t, min;
37028cb931eee8a5567a7d2b7eee011ebc4757474910sewardj   UInt   idx;
37038cb931eee8a5567a7d2b7eee011ebc4757474910sewardj   t = sel16x4_0(sLo); if (True)    { min = t; idx = 0; }
37048cb931eee8a5567a7d2b7eee011ebc4757474910sewardj   t = sel16x4_1(sLo); if (t < min) { min = t; idx = 1; }
37058cb931eee8a5567a7d2b7eee011ebc4757474910sewardj   t = sel16x4_2(sLo); if (t < min) { min = t; idx = 2; }
37068cb931eee8a5567a7d2b7eee011ebc4757474910sewardj   t = sel16x4_3(sLo); if (t < min) { min = t; idx = 3; }
37078cb931eee8a5567a7d2b7eee011ebc4757474910sewardj   t = sel16x4_0(sHi); if (t < min) { min = t; idx = 4; }
37088cb931eee8a5567a7d2b7eee011ebc4757474910sewardj   t = sel16x4_1(sHi); if (t < min) { min = t; idx = 5; }
37098cb931eee8a5567a7d2b7eee011ebc4757474910sewardj   t = sel16x4_2(sHi); if (t < min) { min = t; idx = 6; }
37108cb931eee8a5567a7d2b7eee011ebc4757474910sewardj   t = sel16x4_3(sHi); if (t < min) { min = t; idx = 7; }
37118cb931eee8a5567a7d2b7eee011ebc4757474910sewardj   return ((ULong)(idx << 16)) | ((ULong)min);
37128cb931eee8a5567a7d2b7eee011ebc4757474910sewardj}
37138cb931eee8a5567a7d2b7eee011ebc4757474910sewardj
37148cb931eee8a5567a7d2b7eee011ebc4757474910sewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
3715186f8692b53961e36a7eb4b2d845c26ad2114039sewardjULong amd64g_calc_crc32b ( ULong crcIn, ULong b )
3716186f8692b53961e36a7eb4b2d845c26ad2114039sewardj{
3717186f8692b53961e36a7eb4b2d845c26ad2114039sewardj   UInt  i;
3718186f8692b53961e36a7eb4b2d845c26ad2114039sewardj   ULong crc = (b & 0xFFULL) ^ crcIn;
3719186f8692b53961e36a7eb4b2d845c26ad2114039sewardj   for (i = 0; i < 8; i++)
3720186f8692b53961e36a7eb4b2d845c26ad2114039sewardj      crc = (crc >> 1) ^ ((crc & 1) ? 0x82f63b78ULL : 0);
3721186f8692b53961e36a7eb4b2d845c26ad2114039sewardj   return crc;
3722186f8692b53961e36a7eb4b2d845c26ad2114039sewardj}
3723186f8692b53961e36a7eb4b2d845c26ad2114039sewardj
3724186f8692b53961e36a7eb4b2d845c26ad2114039sewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
3725186f8692b53961e36a7eb4b2d845c26ad2114039sewardjULong amd64g_calc_crc32w ( ULong crcIn, ULong w )
3726186f8692b53961e36a7eb4b2d845c26ad2114039sewardj{
3727186f8692b53961e36a7eb4b2d845c26ad2114039sewardj   UInt  i;
3728186f8692b53961e36a7eb4b2d845c26ad2114039sewardj   ULong crc = (w & 0xFFFFULL) ^ crcIn;
3729186f8692b53961e36a7eb4b2d845c26ad2114039sewardj   for (i = 0; i < 16; i++)
3730186f8692b53961e36a7eb4b2d845c26ad2114039sewardj      crc = (crc >> 1) ^ ((crc & 1) ? 0x82f63b78ULL : 0);
3731186f8692b53961e36a7eb4b2d845c26ad2114039sewardj   return crc;
3732186f8692b53961e36a7eb4b2d845c26ad2114039sewardj}
3733186f8692b53961e36a7eb4b2d845c26ad2114039sewardj
3734186f8692b53961e36a7eb4b2d845c26ad2114039sewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
3735186f8692b53961e36a7eb4b2d845c26ad2114039sewardjULong amd64g_calc_crc32l ( ULong crcIn, ULong l )
3736186f8692b53961e36a7eb4b2d845c26ad2114039sewardj{
3737186f8692b53961e36a7eb4b2d845c26ad2114039sewardj   UInt i;
3738186f8692b53961e36a7eb4b2d845c26ad2114039sewardj   ULong crc = (l & 0xFFFFFFFFULL) ^ crcIn;
3739186f8692b53961e36a7eb4b2d845c26ad2114039sewardj   for (i = 0; i < 32; i++)
3740186f8692b53961e36a7eb4b2d845c26ad2114039sewardj      crc = (crc >> 1) ^ ((crc & 1) ? 0x82f63b78ULL : 0);
3741186f8692b53961e36a7eb4b2d845c26ad2114039sewardj   return crc;
3742186f8692b53961e36a7eb4b2d845c26ad2114039sewardj}
3743186f8692b53961e36a7eb4b2d845c26ad2114039sewardj
3744186f8692b53961e36a7eb4b2d845c26ad2114039sewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
3745186f8692b53961e36a7eb4b2d845c26ad2114039sewardjULong amd64g_calc_crc32q ( ULong crcIn, ULong q )
3746186f8692b53961e36a7eb4b2d845c26ad2114039sewardj{
3747186f8692b53961e36a7eb4b2d845c26ad2114039sewardj   ULong crc = amd64g_calc_crc32l(crcIn, q);
3748186f8692b53961e36a7eb4b2d845c26ad2114039sewardj   return amd64g_calc_crc32l(crc, q >> 32);
3749186f8692b53961e36a7eb4b2d845c26ad2114039sewardj}
3750186f8692b53961e36a7eb4b2d845c26ad2114039sewardj
3751d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj
37524d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj/* .. helper for next fn .. */
37534d5bce29aabaa27792db8e4ac17da5d174df88e2sewardjstatic inline ULong sad_8x4 ( ULong xx, ULong yy )
37544d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj{
37554d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj   UInt t = 0;
37564d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj   t += (UInt)abdU8( sel8x8_3(xx), sel8x8_3(yy) );
37574d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj   t += (UInt)abdU8( sel8x8_2(xx), sel8x8_2(yy) );
37584d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj   t += (UInt)abdU8( sel8x8_1(xx), sel8x8_1(yy) );
37594d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj   t += (UInt)abdU8( sel8x8_0(xx), sel8x8_0(yy) );
37604d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj   return (ULong)t;
37614d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj}
37624d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj
37634d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
37644d5bce29aabaa27792db8e4ac17da5d174df88e2sewardjULong amd64g_calc_mpsadbw ( ULong sHi, ULong sLo,
37654d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj                            ULong dHi, ULong dLo,
37664d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj                            ULong imm_and_return_control_bit )
37674d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj{
37684d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj   UInt imm8     = imm_and_return_control_bit & 7;
37694d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj   Bool calcHi   = (imm_and_return_control_bit >> 7) & 1;
37704d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj   UInt srcOffsL = imm8 & 3; /* src offs in 32-bit (L) chunks */
37714d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj   UInt dstOffsL = (imm8 >> 2) & 1; /* dst offs in ditto chunks */
37724d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj   /* For src we only need 32 bits, so get them into the
37734d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj      lower half of a 64 bit word. */
37744d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj   ULong src = ((srcOffsL & 2) ? sHi : sLo) >> (32 * (srcOffsL & 1));
37754d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj   /* For dst we need to get hold of 56 bits (7 bytes) from a total of
37764d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj      11 bytes.  If calculating the low part of the result, need bytes
37774d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj      dstOffsL * 4 + (0 .. 6); if calculating the high part,
37784d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj      dstOffsL * 4 + (4 .. 10). */
37794d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj   ULong dst;
37804d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj   /* dstOffL = 0, Lo  ->  0 .. 6
37814d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj      dstOffL = 1, Lo  ->  4 .. 10
37824d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj      dstOffL = 0, Hi  ->  4 .. 10
37834d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj      dstOffL = 1, Hi  ->  8 .. 14
37844d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj   */
37854d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj   if (calcHi && dstOffsL) {
37864d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj      /* 8 .. 14 */
37874d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj      dst = dHi & 0x00FFFFFFFFFFFFFFULL;
37884d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj   }
37894d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj   else if (!calcHi && !dstOffsL) {
37904d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj      /* 0 .. 6 */
37914d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj      dst = dLo & 0x00FFFFFFFFFFFFFFULL;
37924d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj   }
37934d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj   else {
37944d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj      /* 4 .. 10 */
37954d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj      dst = (dLo >> 32) | ((dHi & 0x00FFFFFFULL) << 32);
37964d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj   }
37974d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj   ULong r0  = sad_8x4( dst >>  0, src );
37984d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj   ULong r1  = sad_8x4( dst >>  8, src );
37994d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj   ULong r2  = sad_8x4( dst >> 16, src );
38004d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj   ULong r3  = sad_8x4( dst >> 24, src );
38014d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj   ULong res = (r3 << 48) | (r2 << 32) | (r1 << 16) | r0;
38024d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj   return res;
38034d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj}
38044d5bce29aabaa27792db8e4ac17da5d174df88e2sewardj
3805cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
3806cc3d219c3120150c9ab67f1f4850be0f39a9499csewardjULong amd64g_calculate_pext ( ULong src_masked, ULong mask )
3807cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj{
3808cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj   ULong dst = 0;
3809cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj   ULong src_bit;
3810cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj   ULong dst_bit = 1;
3811cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj   for (src_bit = 1; src_bit; src_bit <<= 1) {
3812cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj      if (mask & src_bit) {
3813cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj         if (src_masked & src_bit) dst |= dst_bit;
3814cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj         dst_bit <<= 1;
3815cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj      }
3816cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj   }
3817cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj   return dst;
3818cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj}
3819cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj
3820cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
3821cc3d219c3120150c9ab67f1f4850be0f39a9499csewardjULong amd64g_calculate_pdep ( ULong src, ULong mask )
3822cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj{
3823cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj   ULong dst = 0;
3824cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj   ULong dst_bit;
3825cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj   ULong src_bit = 1;
3826cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj   for (dst_bit = 1; dst_bit; dst_bit <<= 1) {
3827cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj      if (mask & dst_bit) {
3828cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj         if (src & src_bit) dst |= dst_bit;
3829cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj         src_bit <<= 1;
3830cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj      }
3831cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj   }
3832cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj   return dst;
3833cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj}
3834cc3d219c3120150c9ab67f1f4850be0f39a9499csewardj
3835f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj/*---------------------------------------------------------------*/
38360b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj/*--- Helpers for SSE4.2 PCMP{E,I}STR{I,M}                    ---*/
38370b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj/*---------------------------------------------------------------*/
38380b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj
3839acfbd7d59ee5c85911c687c6666940a38019f48fsewardjstatic UInt zmask_from_V128 ( V128* arg )
38400b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj{
3841acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   UInt i, res = 0;
3842acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   for (i = 0; i < 16; i++) {
3843acfbd7d59ee5c85911c687c6666940a38019f48fsewardj      res |=  ((arg->w8[i] == 0) ? 1 : 0) << i;
3844acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   }
3845acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   return res;
38460b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj}
38470b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj
38483c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardjstatic UInt zmask_from_V128_wide ( V128* arg )
38493c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj{
38503c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj   UInt i, res = 0;
38513c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj   for (i = 0; i < 8; i++) {
38523c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj      res |=  ((arg->w16[i] == 0) ? 1 : 0) << i;
38533c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj   }
38543c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj   return res;
38553c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj}
38563c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj
3857acfbd7d59ee5c85911c687c6666940a38019f48fsewardj/* Helps with PCMP{I,E}STR{I,M}.
38580b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj
3859acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   CALLED FROM GENERATED CODE: DIRTY HELPER(s).  (But not really,
3860acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   actually it could be a clean helper, but for the fact that we can't
3861acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   pass by value 2 x V128 to a clean helper, nor have one returned.)
3862acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   Reads guest state, writes to guest state for the xSTRM cases, no
3863acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   accesses of memory, is a pure function.
3864acfbd7d59ee5c85911c687c6666940a38019f48fsewardj
3865acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   opc_and_imm contains (4th byte of opcode << 8) | the-imm8-byte so
3866acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   the callee knows which I/E and I/M variant it is dealing with and
3867acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   what the specific operation is.  4th byte of opcode is in the range
3868acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   0x60 to 0x63:
3869acfbd7d59ee5c85911c687c6666940a38019f48fsewardj       istri  66 0F 3A 63
3870acfbd7d59ee5c85911c687c6666940a38019f48fsewardj       istrm  66 0F 3A 62
3871acfbd7d59ee5c85911c687c6666940a38019f48fsewardj       estri  66 0F 3A 61
3872acfbd7d59ee5c85911c687c6666940a38019f48fsewardj       estrm  66 0F 3A 60
3873acfbd7d59ee5c85911c687c6666940a38019f48fsewardj
3874acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   gstOffL and gstOffR are the guest state offsets for the two XMM
3875acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   register inputs.  We never have to deal with the memory case since
3876acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   that is handled by pre-loading the relevant value into the fake
3877acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   XMM16 register.
3878acfbd7d59ee5c85911c687c6666940a38019f48fsewardj
3879acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   For ESTRx variants, edxIN and eaxIN hold the values of those two
3880acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   registers.
3881acfbd7d59ee5c85911c687c6666940a38019f48fsewardj
3882acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   In all cases, the bottom 16 bits of the result contain the new
3883acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   OSZACP %rflags values.  For xSTRI variants, bits[31:16] of the
3884acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   result hold the new %ecx value.  For xSTRM variants, the helper
3885acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   writes the result directly to the guest XMM0.
3886acfbd7d59ee5c85911c687c6666940a38019f48fsewardj
3887acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   Declarable side effects: in all cases, reads guest state at
3888acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   [gstOffL, +16) and [gstOffR, +16).  For xSTRM variants, also writes
3889acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   guest_XMM0.
3890acfbd7d59ee5c85911c687c6666940a38019f48fsewardj
3891acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   Is expected to be called with opc_and_imm combinations which have
3892acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   actually been validated, and will assert if otherwise.  The front
3893acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   end should ensure we're only called with verified values.
3894acfbd7d59ee5c85911c687c6666940a38019f48fsewardj*/
3895acfbd7d59ee5c85911c687c6666940a38019f48fsewardjULong amd64g_dirtyhelper_PCMPxSTRx (
3896acfbd7d59ee5c85911c687c6666940a38019f48fsewardj          VexGuestAMD64State* gst,
3897acfbd7d59ee5c85911c687c6666940a38019f48fsewardj          HWord opc4_and_imm,
3898acfbd7d59ee5c85911c687c6666940a38019f48fsewardj          HWord gstOffL, HWord gstOffR,
3899acfbd7d59ee5c85911c687c6666940a38019f48fsewardj          HWord edxIN, HWord eaxIN
3900acfbd7d59ee5c85911c687c6666940a38019f48fsewardj       )
39010b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj{
3902acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   HWord opc4 = (opc4_and_imm >> 8) & 0xFF;
3903acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   HWord imm8 = opc4_and_imm & 0xFF;
3904acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   HWord isISTRx = opc4 & 2;
3905acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   HWord isxSTRM = (opc4 & 1) ^ 1;
3906acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   vassert((opc4 & 0xFC) == 0x60); /* 0x60 .. 0x63 */
39073c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj   HWord wide = (imm8 & 1);
3908acfbd7d59ee5c85911c687c6666940a38019f48fsewardj
3909acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   // where the args are
3910acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   V128* argL = (V128*)( ((UChar*)gst) + gstOffL );
3911acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   V128* argR = (V128*)( ((UChar*)gst) + gstOffR );
3912acfbd7d59ee5c85911c687c6666940a38019f48fsewardj
3913acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   /* Create the arg validity masks, either from the vectors
3914acfbd7d59ee5c85911c687c6666940a38019f48fsewardj      themselves or from the supplied edx/eax values. */
3915acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   // FIXME: this is only right for the 8-bit data cases.
3916acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   // At least that is asserted above.
3917acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   UInt zmaskL, zmaskR;
39180b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj
3919acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   // temp spot for the resulting flags and vector.
3920acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   V128 resV;
3921acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   UInt resOSZACP;
3922acfbd7d59ee5c85911c687c6666940a38019f48fsewardj
39233c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj   // for checking whether case was handled
39243c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj   Bool ok = False;
39253c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj
39263c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj   if (wide) {
39273c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj      if (isISTRx) {
39283c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj         zmaskL = zmask_from_V128_wide(argL);
39293c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj         zmaskR = zmask_from_V128_wide(argR);
39303c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj      } else {
39313c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj         Int tmp;
39323c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj         tmp = edxIN & 0xFFFFFFFF;
39333c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj         if (tmp < -8) tmp = -8;
39343c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj         if (tmp > 8)  tmp = 8;
39353c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj         if (tmp < 0)  tmp = -tmp;
39363c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj         vassert(tmp >= 0 && tmp <= 8);
39373c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj         zmaskL = (1 << tmp) & 0xFF;
39383c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj         tmp = eaxIN & 0xFFFFFFFF;
39393c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj         if (tmp < -8) tmp = -8;
39403c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj         if (tmp > 8)  tmp = 8;
39413c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj         if (tmp < 0)  tmp = -tmp;
39423c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj         vassert(tmp >= 0 && tmp <= 8);
39433c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj         zmaskR = (1 << tmp) & 0xFF;
39443c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj      }
39453c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj      // do the meyaath
39463c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj      ok = compute_PCMPxSTRx_wide (
39473c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj              &resV, &resOSZACP, argL, argR,
39483c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj              zmaskL, zmaskR, imm8, (Bool)isxSTRM
39493c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj           );
39503c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj   } else {
39513c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj      if (isISTRx) {
39523c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj         zmaskL = zmask_from_V128(argL);
39533c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj         zmaskR = zmask_from_V128(argR);
39543c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj      } else {
39553c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj         Int tmp;
39563c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj         tmp = edxIN & 0xFFFFFFFF;
39573c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj         if (tmp < -16) tmp = -16;
39583c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj         if (tmp > 16)  tmp = 16;
39593c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj         if (tmp < 0)   tmp = -tmp;
39603c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj         vassert(tmp >= 0 && tmp <= 16);
39613c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj         zmaskL = (1 << tmp) & 0xFFFF;
39623c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj         tmp = eaxIN & 0xFFFFFFFF;
39633c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj         if (tmp < -16) tmp = -16;
39643c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj         if (tmp > 16)  tmp = 16;
39653c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj         if (tmp < 0)   tmp = -tmp;
39663c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj         vassert(tmp >= 0 && tmp <= 16);
39673c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj         zmaskR = (1 << tmp) & 0xFFFF;
39683c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj      }
39693c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj      // do the meyaath
39703c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj      ok = compute_PCMPxSTRx (
39713c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj              &resV, &resOSZACP, argL, argR,
39723c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj              zmaskL, zmaskR, imm8, (Bool)isxSTRM
39733c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj           );
39743c3d6d62cb9fcf2cb8f96b21f28788a51960c5c3sewardj   }
3975acfbd7d59ee5c85911c687c6666940a38019f48fsewardj
3976acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   // front end shouldn't pass us any imm8 variants we can't
3977acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   // handle.  Hence:
3978acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   vassert(ok);
3979acfbd7d59ee5c85911c687c6666940a38019f48fsewardj
3980acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   // So, finally we need to get the results back to the caller.
3981acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   // In all cases, the new OSZACP value is the lowest 16 of
3982acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   // the return value.
3983acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   if (isxSTRM) {
3984c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj      gst->guest_YMM0[0] = resV.w32[0];
3985c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj      gst->guest_YMM0[1] = resV.w32[1];
3986c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj      gst->guest_YMM0[2] = resV.w32[2];
3987c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj      gst->guest_YMM0[3] = resV.w32[3];
3988acfbd7d59ee5c85911c687c6666940a38019f48fsewardj      return resOSZACP & 0x8D5;
3989acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   } else {
3990acfbd7d59ee5c85911c687c6666940a38019f48fsewardj      UInt newECX = resV.w32[0] & 0xFFFF;
3991acfbd7d59ee5c85911c687c6666940a38019f48fsewardj      return (newECX << 16) | (resOSZACP & 0x8D5);
3992acfbd7d59ee5c85911c687c6666940a38019f48fsewardj   }
39930b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj}
39940b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj
3995ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe/*---------------------------------------------------------------*/
3996ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe/*--- AES primitives and helpers                              ---*/
3997ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe/*---------------------------------------------------------------*/
3998ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe/* a 16 x 16 matrix */
3999ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippestatic const UChar sbox[256] = {                   // row nr
4000ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, // 1
4001ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
4002ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, // 2
4003ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
4004ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, // 3
4005ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
4006ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, // 4
4007ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
4008ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, // 5
4009ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
4010ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, // 6
4011ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
4012ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, // 7
4013ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
4014ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, // 8
4015ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
4016ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, // 9
4017ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
4018ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, //10
4019ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
4020ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, //11
4021ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
4022ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, //12
4023ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
4024ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, //13
4025ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
4026ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, //14
4027ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
4028ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, //15
4029ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
4030ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, //16
4031ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
4032ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe};
4033ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippestatic void SubBytes (V128* v)
4034ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe{
4035ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   V128 r;
4036ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   UInt i;
4037ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   for (i = 0; i < 16; i++)
4038ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe      r.w8[i] = sbox[v->w8[i]];
4039ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   *v = r;
4040ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe}
4041ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe
4042ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe/* a 16 x 16 matrix */
4043ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippestatic const UChar invsbox[256] = {                // row nr
4044ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, // 1
4045ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
4046ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, // 2
4047ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
4048ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, // 3
4049ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
4050ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, // 4
4051ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
4052ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, // 5
4053ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
4054ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, // 6
4055ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
4056ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, // 7
4057ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
4058ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, // 8
4059ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
4060ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, // 9
4061ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
4062ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, //10
4063ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
4064ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, //11
4065ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
4066ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, //12
4067ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
4068ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, //13
4069ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
4070ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, //14
4071ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
4072ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, //15
4073ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
4074ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, //16
4075ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
4076ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe};
4077ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippestatic void InvSubBytes (V128* v)
4078ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe{
4079ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   V128 r;
4080ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   UInt i;
4081ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   for (i = 0; i < 16; i++)
4082ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe      r.w8[i] = invsbox[v->w8[i]];
4083ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   *v = r;
4084ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe}
4085ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe
4086ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippestatic const UChar ShiftRows_op[16] =
4087ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   {11, 6, 1, 12, 7, 2, 13, 8, 3, 14, 9, 4, 15, 10, 5, 0};
4088ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippestatic void ShiftRows (V128* v)
4089ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe{
4090ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   V128 r;
4091ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   UInt i;
4092ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   for (i = 0; i < 16; i++)
4093ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe      r.w8[i] = v->w8[ShiftRows_op[15-i]];
4094ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   *v = r;
4095ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe}
4096ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe
4097ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippestatic const UChar InvShiftRows_op[16] =
4098ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   {3, 6, 9, 12, 15, 2, 5, 8, 11, 14, 1, 4, 7, 10, 13, 0};
4099ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippestatic void InvShiftRows (V128* v)
4100ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe{
4101ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   V128 r;
4102ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   UInt i;
4103ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   for (i = 0; i < 16; i++)
4104ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe      r.w8[i] = v->w8[InvShiftRows_op[15-i]];
4105ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   *v = r;
4106ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe}
4107ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe
4108ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe/* Multiplication of the finite fields elements of AES.
4109ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   See "A Specification for The AES Algorithm Rijndael
4110ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe        (by Joan Daemen & Vincent Rijmen)"
4111ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe        Dr. Brian Gladman, v3.1, 3rd March 2001. */
4112ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe/* N values so that (hex) xy = 0x03^N.
4113ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x00 cannot be used. We put 0xff for this value.*/
4114ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe/* a 16 x 16 matrix */
4115ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippestatic const UChar Nxy[256] = {                    // row nr
4116ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0xff, 0x00, 0x19, 0x01, 0x32, 0x02, 0x1a, 0xc6, // 1
4117ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x4b, 0xc7, 0x1b, 0x68, 0x33, 0xee, 0xdf, 0x03,
4118ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x64, 0x04, 0xe0, 0x0e, 0x34, 0x8d, 0x81, 0xef, // 2
4119ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x4c, 0x71, 0x08, 0xc8, 0xf8, 0x69, 0x1c, 0xc1,
4120ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x7d, 0xc2, 0x1d, 0xb5, 0xf9, 0xb9, 0x27, 0x6a, // 3
4121ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x4d, 0xe4, 0xa6, 0x72, 0x9a, 0xc9, 0x09, 0x78,
4122ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x65, 0x2f, 0x8a, 0x05, 0x21, 0x0f, 0xe1, 0x24, // 4
4123ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x12, 0xf0, 0x82, 0x45, 0x35, 0x93, 0xda, 0x8e,
4124ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x96, 0x8f, 0xdb, 0xbd, 0x36, 0xd0, 0xce, 0x94, // 5
4125ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x13, 0x5c, 0xd2, 0xf1, 0x40, 0x46, 0x83, 0x38,
4126ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x66, 0xdd, 0xfd, 0x30, 0xbf, 0x06, 0x8b, 0x62, // 6
4127ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0xb3, 0x25, 0xe2, 0x98, 0x22, 0x88, 0x91, 0x10,
4128ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x7e, 0x6e, 0x48, 0xc3, 0xa3, 0xb6, 0x1e, 0x42, // 7
4129ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x3a, 0x6b, 0x28, 0x54, 0xfa, 0x85, 0x3d, 0xba,
4130ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x2b, 0x79, 0x0a, 0x15, 0x9b, 0x9f, 0x5e, 0xca, // 8
4131ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x4e, 0xd4, 0xac, 0xe5, 0xf3, 0x73, 0xa7, 0x57,
4132ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0xaf, 0x58, 0xa8, 0x50, 0xf4, 0xea, 0xd6, 0x74, // 9
4133ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x4f, 0xae, 0xe9, 0xd5, 0xe7, 0xe6, 0xad, 0xe8,
4134ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x2c, 0xd7, 0x75, 0x7a, 0xeb, 0x16, 0x0b, 0xf5, //10
4135ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x59, 0xcb, 0x5f, 0xb0, 0x9c, 0xa9, 0x51, 0xa0,
4136ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x7f, 0x0c, 0xf6, 0x6f, 0x17, 0xc4, 0x49, 0xec, //11
4137ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0xd8, 0x43, 0x1f, 0x2d, 0xa4, 0x76, 0x7b, 0xb7,
4138ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0xcc, 0xbb, 0x3e, 0x5a, 0xfb, 0x60, 0xb1, 0x86, //12
4139ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x3b, 0x52, 0xa1, 0x6c, 0xaa, 0x55, 0x29, 0x9d,
4140ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x97, 0xb2, 0x87, 0x90, 0x61, 0xbe, 0xdc, 0xfc, //13
4141ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0xbc, 0x95, 0xcf, 0xcd, 0x37, 0x3f, 0x5b, 0xd1,
4142ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x53, 0x39, 0x84, 0x3c, 0x41, 0xa2, 0x6d, 0x47, //14
4143ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x14, 0x2a, 0x9e, 0x5d, 0x56, 0xf2, 0xd3, 0xab,
4144ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x44, 0x11, 0x92, 0xd9, 0x23, 0x20, 0x2e, 0x89, //15
4145ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0xb4, 0x7c, 0xb8, 0x26, 0x77, 0x99, 0xe3, 0xa5,
4146ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x67, 0x4a, 0xed, 0xde, 0xc5, 0x31, 0xfe, 0x18, //16
4147ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x0d, 0x63, 0x8c, 0x80, 0xc0, 0xf7, 0x70, 0x07
4148ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe};
4149ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe
4150ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe/* E values so that E = 0x03^xy. */
4151ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippestatic const UChar Exy[256] = {                    // row nr
4152ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x01, 0x03, 0x05, 0x0f, 0x11, 0x33, 0x55, 0xff, // 1
4153ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x1a, 0x2e, 0x72, 0x96, 0xa1, 0xf8, 0x13, 0x35,
4154ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x5f, 0xe1, 0x38, 0x48, 0xd8, 0x73, 0x95, 0xa4, // 2
4155ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0xf7, 0x02, 0x06, 0x0a, 0x1e, 0x22, 0x66, 0xaa,
4156ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0xe5, 0x34, 0x5c, 0xe4, 0x37, 0x59, 0xeb, 0x26, // 3
4157ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x6a, 0xbe, 0xd9, 0x70, 0x90, 0xab, 0xe6, 0x31,
4158ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x53, 0xf5, 0x04, 0x0c, 0x14, 0x3c, 0x44, 0xcc, // 4
4159ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x4f, 0xd1, 0x68, 0xb8, 0xd3, 0x6e, 0xb2, 0xcd,
4160ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x4c, 0xd4, 0x67, 0xa9, 0xe0, 0x3b, 0x4d, 0xd7, // 5
4161ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x62, 0xa6, 0xf1, 0x08, 0x18, 0x28, 0x78, 0x88,
4162ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x83, 0x9e, 0xb9, 0xd0, 0x6b, 0xbd, 0xdc, 0x7f, // 6
4163ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x81, 0x98, 0xb3, 0xce, 0x49, 0xdb, 0x76, 0x9a,
4164ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0xb5, 0xc4, 0x57, 0xf9, 0x10, 0x30, 0x50, 0xf0, // 7
4165ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x0b, 0x1d, 0x27, 0x69, 0xbb, 0xd6, 0x61, 0xa3,
4166ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0xfe, 0x19, 0x2b, 0x7d, 0x87, 0x92, 0xad, 0xec, // 8
4167ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x2f, 0x71, 0x93, 0xae, 0xe9, 0x20, 0x60, 0xa0,
4168ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0xfb, 0x16, 0x3a, 0x4e, 0xd2, 0x6d, 0xb7, 0xc2, // 9
4169ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x5d, 0xe7, 0x32, 0x56, 0xfa, 0x15, 0x3f, 0x41,
4170ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0xc3, 0x5e, 0xe2, 0x3d, 0x47, 0xc9, 0x40, 0xc0, //10
4171ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x5b, 0xed, 0x2c, 0x74, 0x9c, 0xbf, 0xda, 0x75,
4172ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x9f, 0xba, 0xd5, 0x64, 0xac, 0xef, 0x2a, 0x7e, //11
4173ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x82, 0x9d, 0xbc, 0xdf, 0x7a, 0x8e, 0x89, 0x80,
4174ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x9b, 0xb6, 0xc1, 0x58, 0xe8, 0x23, 0x65, 0xaf, //12
4175ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0xea, 0x25, 0x6f, 0xb1, 0xc8, 0x43, 0xc5, 0x54,
4176ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0xfc, 0x1f, 0x21, 0x63, 0xa5, 0xf4, 0x07, 0x09, //13
4177ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x1b, 0x2d, 0x77, 0x99, 0xb0, 0xcb, 0x46, 0xca,
4178ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x45, 0xcf, 0x4a, 0xde, 0x79, 0x8b, 0x86, 0x91, //14
4179ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0xa8, 0xe3, 0x3e, 0x42, 0xc6, 0x51, 0xf3, 0x0e,
4180ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x12, 0x36, 0x5a, 0xee, 0x29, 0x7b, 0x8d, 0x8c, //15
4181ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x8f, 0x8a, 0x85, 0x94, 0xa7, 0xf2, 0x0d, 0x17,
4182ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x39, 0x4b, 0xdd, 0x7c, 0x84, 0x97, 0xa2, 0xfd, //16
4183ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   0x1c, 0x24, 0x6c, 0xb4, 0xc7, 0x52, 0xf6, 0x01};
4184ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe
4185ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippestatic inline UChar ff_mul(UChar u1, UChar u2)
4186ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe{
4187ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   if ((u1 > 0) && (u2 > 0)) {
4188ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe      UInt ui = Nxy[u1] + Nxy[u2];
4189ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe      if (ui >= 255)
4190ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe         ui = ui - 255;
4191ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe      return Exy[ui];
4192ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   } else {
4193ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe      return 0;
4194ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   };
4195ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe}
4196ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe
4197ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippestatic void MixColumns (V128* v)
4198ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe{
4199ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   V128 r;
4200ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   Int j;
4201ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe#define P(x,row,col) (x)->w8[((row)*4+(col))]
4202ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   for (j = 0; j < 4; j++) {
4203ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe      P(&r,j,0) = ff_mul(0x02, P(v,j,0)) ^ ff_mul(0x03, P(v,j,1))
4204ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe         ^ P(v,j,2) ^ P(v,j,3);
4205ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe      P(&r,j,1) = P(v,j,0) ^ ff_mul( 0x02, P(v,j,1) )
4206ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe         ^ ff_mul(0x03, P(v,j,2) ) ^ P(v,j,3);
4207ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe      P(&r,j,2) = P(v,j,0) ^ P(v,j,1) ^ ff_mul( 0x02, P(v,j,2) )
4208ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe         ^ ff_mul(0x03, P(v,j,3) );
4209ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe      P(&r,j,3) = ff_mul(0x03, P(v,j,0) ) ^ P(v,j,1) ^ P(v,j,2)
4210ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe         ^ ff_mul( 0x02, P(v,j,3) );
4211ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   }
4212ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   *v = r;
4213ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe#undef P
4214ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe}
4215ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe
4216ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippestatic void InvMixColumns (V128* v)
4217ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe{
4218ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   V128 r;
4219ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   Int j;
4220ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe#define P(x,row,col) (x)->w8[((row)*4+(col))]
4221ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   for (j = 0; j < 4; j++) {
4222ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe      P(&r,j,0) = ff_mul(0x0e, P(v,j,0) ) ^ ff_mul(0x0b, P(v,j,1) )
4223ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe         ^ ff_mul(0x0d,P(v,j,2) ) ^ ff_mul(0x09, P(v,j,3) );
4224ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe      P(&r,j,1) = ff_mul(0x09, P(v,j,0) ) ^ ff_mul(0x0e, P(v,j,1) )
4225ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe         ^ ff_mul(0x0b,P(v,j,2) ) ^ ff_mul(0x0d, P(v,j,3) );
4226ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe      P(&r,j,2) = ff_mul(0x0d, P(v,j,0) ) ^ ff_mul(0x09, P(v,j,1) )
4227ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe         ^ ff_mul(0x0e,P(v,j,2) ) ^ ff_mul(0x0b, P(v,j,3) );
4228ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe      P(&r,j,3) = ff_mul(0x0b, P(v,j,0) ) ^ ff_mul(0x0d, P(v,j,1) )
4229ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe         ^ ff_mul(0x09,P(v,j,2) ) ^ ff_mul(0x0e, P(v,j,3) );
4230ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   }
4231ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   *v = r;
4232ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe#undef P
4233ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe
4234ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe}
4235ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe
4236ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe/* For description, see definition in guest_amd64_defs.h */
4237ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippevoid amd64g_dirtyhelper_AES (
4238ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe          VexGuestAMD64State* gst,
42391407a363d94885ef7f748299ad54669dd97361efsewardj          HWord opc4, HWord gstOffD,
4240ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe          HWord gstOffL, HWord gstOffR
4241ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe       )
4242ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe{
4243ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   // where the args are
42441407a363d94885ef7f748299ad54669dd97361efsewardj   V128* argD = (V128*)( ((UChar*)gst) + gstOffD );
4245ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   V128* argL = (V128*)( ((UChar*)gst) + gstOffL );
4246ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   V128* argR = (V128*)( ((UChar*)gst) + gstOffR );
42471407a363d94885ef7f748299ad54669dd97361efsewardj   V128  r;
4248ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe
4249ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   switch (opc4) {
4250ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe      case 0xDC: /* AESENC */
4251ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe      case 0xDD: /* AESENCLAST */
42521407a363d94885ef7f748299ad54669dd97361efsewardj         r = *argR;
42531407a363d94885ef7f748299ad54669dd97361efsewardj         ShiftRows (&r);
42541407a363d94885ef7f748299ad54669dd97361efsewardj         SubBytes  (&r);
4255ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe         if (opc4 == 0xDC)
42561407a363d94885ef7f748299ad54669dd97361efsewardj            MixColumns (&r);
42571407a363d94885ef7f748299ad54669dd97361efsewardj         argD->w64[0] = r.w64[0] ^ argL->w64[0];
42581407a363d94885ef7f748299ad54669dd97361efsewardj         argD->w64[1] = r.w64[1] ^ argL->w64[1];
4259ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe         break;
4260ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe
4261ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe      case 0xDE: /* AESDEC */
4262ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe      case 0xDF: /* AESDECLAST */
42631407a363d94885ef7f748299ad54669dd97361efsewardj         r = *argR;
42641407a363d94885ef7f748299ad54669dd97361efsewardj         InvShiftRows (&r);
42651407a363d94885ef7f748299ad54669dd97361efsewardj         InvSubBytes (&r);
4266ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe         if (opc4 == 0xDE)
42671407a363d94885ef7f748299ad54669dd97361efsewardj            InvMixColumns (&r);
42681407a363d94885ef7f748299ad54669dd97361efsewardj         argD->w64[0] = r.w64[0] ^ argL->w64[0];
42691407a363d94885ef7f748299ad54669dd97361efsewardj         argD->w64[1] = r.w64[1] ^ argL->w64[1];
4270ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe         break;
4271ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe
4272ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe      case 0xDB: /* AESIMC */
42731407a363d94885ef7f748299ad54669dd97361efsewardj         *argD = *argL;
42741407a363d94885ef7f748299ad54669dd97361efsewardj         InvMixColumns (argD);
4275ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe         break;
4276ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe      default: vassert(0);
4277ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   }
4278ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe}
4279ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe
4280ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippestatic inline UInt RotWord (UInt   w32)
4281ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe{
4282ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   return ((w32 >> 8) | (w32 << 24));
4283ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe}
4284ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe
4285ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippestatic inline UInt SubWord (UInt   w32)
4286ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe{
4287ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   UChar *w8;
4288ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   UChar *r8;
4289ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   UInt res;
4290ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   w8 = (UChar*) &w32;
4291ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   r8 = (UChar*) &res;
4292ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   r8[0] = sbox[w8[0]];
4293ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   r8[1] = sbox[w8[1]];
4294ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   r8[2] = sbox[w8[2]];
4295ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   r8[3] = sbox[w8[3]];
4296ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   return res;
4297ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe}
4298ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe
4299ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe/* For description, see definition in guest_amd64_defs.h */
4300ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippeextern void amd64g_dirtyhelper_AESKEYGENASSIST (
4301ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe          VexGuestAMD64State* gst,
4302ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe          HWord imm8,
4303ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe          HWord gstOffL, HWord gstOffR
4304ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe       )
4305ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe{
4306ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   // where the args are
4307ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   V128* argL = (V128*)( ((UChar*)gst) + gstOffL );
4308ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe   V128* argR = (V128*)( ((UChar*)gst) + gstOffR );
4309ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe
4310a35a6db21ee5267b80a07fa40158df5306feaf42sewardj   // We have to create the result in a temporary in the
4311a35a6db21ee5267b80a07fa40158df5306feaf42sewardj   // case where the src and dst regs are the same.  See #341698.
4312a35a6db21ee5267b80a07fa40158df5306feaf42sewardj   V128 tmp;
4313a35a6db21ee5267b80a07fa40158df5306feaf42sewardj
4314a35a6db21ee5267b80a07fa40158df5306feaf42sewardj   tmp.w32[3] = RotWord (SubWord (argL->w32[3])) ^ imm8;
4315a35a6db21ee5267b80a07fa40158df5306feaf42sewardj   tmp.w32[2] = SubWord (argL->w32[3]);
4316a35a6db21ee5267b80a07fa40158df5306feaf42sewardj   tmp.w32[1] = RotWord (SubWord (argL->w32[1])) ^ imm8;
4317a35a6db21ee5267b80a07fa40158df5306feaf42sewardj   tmp.w32[0] = SubWord (argL->w32[1]);
4318a35a6db21ee5267b80a07fa40158df5306feaf42sewardj
4319a35a6db21ee5267b80a07fa40158df5306feaf42sewardj   argR->w32[3] = tmp.w32[3];
4320a35a6db21ee5267b80a07fa40158df5306feaf42sewardj   argR->w32[2] = tmp.w32[2];
4321a35a6db21ee5267b80a07fa40158df5306feaf42sewardj   argR->w32[1] = tmp.w32[1];
4322a35a6db21ee5267b80a07fa40158df5306feaf42sewardj   argR->w32[0] = tmp.w32[0];
4323ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe}
4324ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe
4325ff4d6beb6a5b17380bc9e08b5d239f5bffa90262philippe
43260b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj
43270b2d3fe2b6eba2410dfcd3874af5bb78078f09c8sewardj/*---------------------------------------------------------------*/
4328f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj/*--- Helpers for dealing with, and describing,               ---*/
4329f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj/*--- guest state as a whole.                                 ---*/
4330f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj/*---------------------------------------------------------------*/
4331f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
4332f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj/* Initialise the entire amd64 guest state. */
4333f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj/* VISIBLE TO LIBVEX CLIENT */
4334f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardjvoid LibVEX_GuestAMD64_initialise ( /*OUT*/VexGuestAMD64State* vex_state )
4335f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj{
4336c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   vex_state->host_EvC_FAILADDR = 0;
4337c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   vex_state->host_EvC_COUNTER = 0;
4338c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   vex_state->pad0 = 0;
4339c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj
4340f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   vex_state->guest_RAX = 0;
4341f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   vex_state->guest_RCX = 0;
4342f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   vex_state->guest_RDX = 0;
4343f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   vex_state->guest_RBX = 0;
4344f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   vex_state->guest_RSP = 0;
4345f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   vex_state->guest_RBP = 0;
4346f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   vex_state->guest_RSI = 0;
4347f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   vex_state->guest_RDI = 0;
4348f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   vex_state->guest_R8  = 0;
4349f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   vex_state->guest_R9  = 0;
4350f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   vex_state->guest_R10 = 0;
4351f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   vex_state->guest_R11 = 0;
4352f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   vex_state->guest_R12 = 0;
4353f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   vex_state->guest_R13 = 0;
4354f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   vex_state->guest_R14 = 0;
4355f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   vex_state->guest_R15 = 0;
4356f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
4357f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   vex_state->guest_CC_OP   = AMD64G_CC_OP_COPY;
4358f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   vex_state->guest_CC_DEP1 = 0;
4359f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   vex_state->guest_CC_DEP2 = 0;
4360f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   vex_state->guest_CC_NDEP = 0;
4361f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
4362d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj   vex_state->guest_DFLAG   = 1; /* forwards */
436385520e44c14bebadea604ba9ba32113b55988227sewardj   vex_state->guest_IDFLAG  = 0;
43640e457fcf846af2963d8eea8ad728309d8a66a263sewardj   vex_state->guest_ACFLAG  = 0;
4365f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
4366e2cc4defff3eec3be8e38ccc21df5ee460f930e9philippe   /* HACK: represent the offset associated with a constant %fs.
4367e2cc4defff3eec3be8e38ccc21df5ee460f930e9philippe      Typically, on linux, this assumes that %fs is only ever zero (main
4368e2cc4defff3eec3be8e38ccc21df5ee460f930e9philippe      thread) or 0x63. */
4369e2cc4defff3eec3be8e38ccc21df5ee460f930e9philippe   vex_state->guest_FS_CONST = 0;
4370a6b93d109a1d3b18e1ffaf3c1721216e79aaadc7sewardj
4371f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj   vex_state->guest_RIP = 0;
4372f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
43738d965316c72c2392f670dcdfa127547ec77c7e56sewardj   /* Initialise the simulated FPU */
43748d965316c72c2392f670dcdfa127547ec77c7e56sewardj   amd64g_dirtyhelper_FINIT( vex_state );
43758d965316c72c2392f670dcdfa127547ec77c7e56sewardj
4376c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj   /* Initialise the AVX state. */
4377c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj#  define AVXZERO(_ymm) \
4378c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj      do { _ymm[0]=_ymm[1]=_ymm[2]=_ymm[3] = 0; \
4379c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj           _ymm[4]=_ymm[5]=_ymm[6]=_ymm[7] = 0; \
4380c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj      } while (0)
4381cb6091d51134327150448a26a897dc8acb4dde0fsewardj   vex_state->guest_SSEROUND = (ULong)Irrm_NEAREST;
4382c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj   AVXZERO(vex_state->guest_YMM0);
4383c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj   AVXZERO(vex_state->guest_YMM1);
4384c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj   AVXZERO(vex_state->guest_YMM2);
4385c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj   AVXZERO(vex_state->guest_YMM3);
4386c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj   AVXZERO(vex_state->guest_YMM4);
4387c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj   AVXZERO(vex_state->guest_YMM5);
4388c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj   AVXZERO(vex_state->guest_YMM6);
4389c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj   AVXZERO(vex_state->guest_YMM7);
4390c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj   AVXZERO(vex_state->guest_YMM8);
4391c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj   AVXZERO(vex_state->guest_YMM9);
4392c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj   AVXZERO(vex_state->guest_YMM10);
4393c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj   AVXZERO(vex_state->guest_YMM11);
4394c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj   AVXZERO(vex_state->guest_YMM12);
4395c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj   AVXZERO(vex_state->guest_YMM13);
4396c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj   AVXZERO(vex_state->guest_YMM14);
4397c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj   AVXZERO(vex_state->guest_YMM15);
4398c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj   AVXZERO(vex_state->guest_YMM16);
4399c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj
4400c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj#  undef AVXZERO
4401f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
44026ef84bed9bb3af22060eb1759788034602bbcc88florian   vex_state->guest_EMNOTE = EmNote_NONE;
44031f126c5c092801acfc1ac968d2f1a37dde334bccsewardj
44041f126c5c092801acfc1ac968d2f1a37dde334bccsewardj   /* These should not ever be either read or written, but we
44051f126c5c092801acfc1ac968d2f1a37dde334bccsewardj      initialise them anyway. */
440605f5e0172384dd2983fb16fbb7deebd74d71cd35sewardj   vex_state->guest_CMSTART = 0;
440705f5e0172384dd2983fb16fbb7deebd74d71cd35sewardj   vex_state->guest_CMLEN   = 0;
4408ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj
4409d660d41d4174e44f284bad3264601662ed68d4a1sewardj   vex_state->guest_NRADDR   = 0;
4410d660d41d4174e44f284bad3264601662ed68d4a1sewardj   vex_state->guest_SC_CLASS = 0;
4411e2cc4defff3eec3be8e38ccc21df5ee460f930e9philippe   vex_state->guest_GS_CONST = 0;
4412d660d41d4174e44f284bad3264601662ed68d4a1sewardj
4413e86310f555a233cc2ca02e1a5d0adb555f12bdcdsewardj   vex_state->guest_IP_AT_SYSCALL = 0;
4414c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   vex_state->pad1 = 0;
441544d494dfad0c12f96f61cf9edfc889dfa69e3b30sewardj}
441644d494dfad0c12f96f61cf9edfc889dfa69e3b30sewardj
4417f8c37f78bcd038e9e8513a415bf7b6e675fc6804sewardj
44182f959cc53dea4ec13926d7a829dd6fb79225c5c3sewardj/* Figure out if any part of the guest state contained in minoff
44192f959cc53dea4ec13926d7a829dd6fb79225c5c3sewardj   .. maxoff requires precise memory exceptions.  If in doubt return
44206c46befd9eb90c1b6e739926c1fa335cba75bf46philippe   True (but this generates significantly slower code).
44212f959cc53dea4ec13926d7a829dd6fb79225c5c3sewardj
44224cca75cb48776ceda40e8e305232d85f62021804sewardj   By default we enforce precise exns for guest %RSP, %RBP and %RIP
44234cca75cb48776ceda40e8e305232d85f62021804sewardj   only.  These are the minimum needed to extract correct stack
44244cca75cb48776ceda40e8e305232d85f62021804sewardj   backtraces from amd64 code.
44256c46befd9eb90c1b6e739926c1fa335cba75bf46philippe
44266c46befd9eb90c1b6e739926c1fa335cba75bf46philippe   Only %RSP is needed in mode VexRegUpdSpAtMemAccess.
44272f959cc53dea4ec13926d7a829dd6fb79225c5c3sewardj*/
4428ca2c3c75784d35d136fc7c952717cdee5063c193sewardjBool guest_amd64_state_requires_precise_mem_exns (
4429ca2c3c75784d35d136fc7c952717cdee5063c193sewardj        Int minoff, Int maxoff, VexRegisterUpdates pxControl
4430ca2c3c75784d35d136fc7c952717cdee5063c193sewardj     )
443144d494dfad0c12f96f61cf9edfc889dfa69e3b30sewardj{
44324cca75cb48776ceda40e8e305232d85f62021804sewardj   Int rbp_min = offsetof(VexGuestAMD64State, guest_RBP);
44334cca75cb48776ceda40e8e305232d85f62021804sewardj   Int rbp_max = rbp_min + 8 - 1;
44342f959cc53dea4ec13926d7a829dd6fb79225c5c3sewardj   Int rsp_min = offsetof(VexGuestAMD64State, guest_RSP);
44352f959cc53dea4ec13926d7a829dd6fb79225c5c3sewardj   Int rsp_max = rsp_min + 8 - 1;
44362f959cc53dea4ec13926d7a829dd6fb79225c5c3sewardj   Int rip_min = offsetof(VexGuestAMD64State, guest_RIP);
44372f959cc53dea4ec13926d7a829dd6fb79225c5c3sewardj   Int rip_max = rip_min + 8 - 1;
44382f959cc53dea4ec13926d7a829dd6fb79225c5c3sewardj
44396c46befd9eb90c1b6e739926c1fa335cba75bf46philippe   if (maxoff < rsp_min || minoff > rsp_max) {
44406c46befd9eb90c1b6e739926c1fa335cba75bf46philippe      /* no overlap with rsp */
4441ca2c3c75784d35d136fc7c952717cdee5063c193sewardj      if (pxControl == VexRegUpdSpAtMemAccess)
44426c46befd9eb90c1b6e739926c1fa335cba75bf46philippe         return False; // We only need to check stack pointer.
44434cca75cb48776ceda40e8e305232d85f62021804sewardj   } else {
44444cca75cb48776ceda40e8e305232d85f62021804sewardj      return True;
44454cca75cb48776ceda40e8e305232d85f62021804sewardj   }
44464cca75cb48776ceda40e8e305232d85f62021804sewardj
44476c46befd9eb90c1b6e739926c1fa335cba75bf46philippe   if (maxoff < rbp_min || minoff > rbp_max) {
44486c46befd9eb90c1b6e739926c1fa335cba75bf46philippe      /* no overlap with rbp */
44492f959cc53dea4ec13926d7a829dd6fb79225c5c3sewardj   } else {
44502f959cc53dea4ec13926d7a829dd6fb79225c5c3sewardj      return True;
44512f959cc53dea4ec13926d7a829dd6fb79225c5c3sewardj   }
44522f959cc53dea4ec13926d7a829dd6fb79225c5c3sewardj
44532f959cc53dea4ec13926d7a829dd6fb79225c5c3sewardj   if (maxoff < rip_min || minoff > rip_max) {
44542f959cc53dea4ec13926d7a829dd6fb79225c5c3sewardj      /* no overlap with eip */
44552f959cc53dea4ec13926d7a829dd6fb79225c5c3sewardj   } else {
44562f959cc53dea4ec13926d7a829dd6fb79225c5c3sewardj      return True;
44572f959cc53dea4ec13926d7a829dd6fb79225c5c3sewardj   }
44582f959cc53dea4ec13926d7a829dd6fb79225c5c3sewardj
44592f959cc53dea4ec13926d7a829dd6fb79225c5c3sewardj   return False;
446044d494dfad0c12f96f61cf9edfc889dfa69e3b30sewardj}
44612f959cc53dea4ec13926d7a829dd6fb79225c5c3sewardj
44622f959cc53dea4ec13926d7a829dd6fb79225c5c3sewardj
4463c85e91c7db5b5957cc2682275e98b224bcd33270sewardj#define ALWAYSDEFD(field)                             \
4464c85e91c7db5b5957cc2682275e98b224bcd33270sewardj    { offsetof(VexGuestAMD64State, field),            \
4465c85e91c7db5b5957cc2682275e98b224bcd33270sewardj      (sizeof ((VexGuestAMD64State*)0)->field) }
446644d494dfad0c12f96f61cf9edfc889dfa69e3b30sewardj
446744d494dfad0c12f96f61cf9edfc889dfa69e3b30sewardjVexGuestLayout
4468c85e91c7db5b5957cc2682275e98b224bcd33270sewardj   amd64guest_layout
446944d494dfad0c12f96f61cf9edfc889dfa69e3b30sewardj      = {
447044d494dfad0c12f96f61cf9edfc889dfa69e3b30sewardj          /* Total size of the guest state, in bytes. */
4471c85e91c7db5b5957cc2682275e98b224bcd33270sewardj          .total_sizeB = sizeof(VexGuestAMD64State),
447244d494dfad0c12f96f61cf9edfc889dfa69e3b30sewardj
447344d494dfad0c12f96f61cf9edfc889dfa69e3b30sewardj          /* Describe the stack pointer. */
4474c85e91c7db5b5957cc2682275e98b224bcd33270sewardj          .offset_SP = offsetof(VexGuestAMD64State,guest_RSP),
4475c85e91c7db5b5957cc2682275e98b224bcd33270sewardj          .sizeof_SP = 8,
447644d494dfad0c12f96f61cf9edfc889dfa69e3b30sewardj
4477a203330aad67bc3e52ca1395a55e94ef9a091223sewardj          /* Describe the frame pointer. */
4478a203330aad67bc3e52ca1395a55e94ef9a091223sewardj          .offset_FP = offsetof(VexGuestAMD64State,guest_RBP),
4479a203330aad67bc3e52ca1395a55e94ef9a091223sewardj          .sizeof_FP = 8,
4480a203330aad67bc3e52ca1395a55e94ef9a091223sewardj
448144d494dfad0c12f96f61cf9edfc889dfa69e3b30sewardj          /* Describe the instruction pointer. */
4482c85e91c7db5b5957cc2682275e98b224bcd33270sewardj          .offset_IP = offsetof(VexGuestAMD64State,guest_RIP),
4483c85e91c7db5b5957cc2682275e98b224bcd33270sewardj          .sizeof_IP = 8,
448444d494dfad0c12f96f61cf9edfc889dfa69e3b30sewardj
448544d494dfad0c12f96f61cf9edfc889dfa69e3b30sewardj          /* Describe any sections to be regarded by Memcheck as
448644d494dfad0c12f96f61cf9edfc889dfa69e3b30sewardj             'always-defined'. */
4487e86310f555a233cc2ca02e1a5d0adb555f12bdcdsewardj          .n_alwaysDefd = 16,
448844d494dfad0c12f96f61cf9edfc889dfa69e3b30sewardj
448944d494dfad0c12f96f61cf9edfc889dfa69e3b30sewardj          /* flags thunk: OP and NDEP are always defd, whereas DEP1
449044d494dfad0c12f96f61cf9edfc889dfa69e3b30sewardj             and DEP2 have to be tracked.  See detailed comment in
449144d494dfad0c12f96f61cf9edfc889dfa69e3b30sewardj             gdefs.h on meaning of thunk fields. */
449244d494dfad0c12f96f61cf9edfc889dfa69e3b30sewardj          .alwaysDefd
449344d494dfad0c12f96f61cf9edfc889dfa69e3b30sewardj             = { /*  0 */ ALWAYSDEFD(guest_CC_OP),
449444d494dfad0c12f96f61cf9edfc889dfa69e3b30sewardj                 /*  1 */ ALWAYSDEFD(guest_CC_NDEP),
449585520e44c14bebadea604ba9ba32113b55988227sewardj		 /*  2 */ ALWAYSDEFD(guest_DFLAG),
449685520e44c14bebadea604ba9ba32113b55988227sewardj                 /*  3 */ ALWAYSDEFD(guest_IDFLAG),
449785520e44c14bebadea604ba9ba32113b55988227sewardj                 /*  4 */ ALWAYSDEFD(guest_RIP),
4498e2cc4defff3eec3be8e38ccc21df5ee460f930e9philippe                 /*  5 */ ALWAYSDEFD(guest_FS_CONST),
44998d965316c72c2392f670dcdfa127547ec77c7e56sewardj                 /*  6 */ ALWAYSDEFD(guest_FTOP),
45008d965316c72c2392f670dcdfa127547ec77c7e56sewardj                 /*  7 */ ALWAYSDEFD(guest_FPTAG),
45018d965316c72c2392f670dcdfa127547ec77c7e56sewardj                 /*  8 */ ALWAYSDEFD(guest_FPROUND),
45028d965316c72c2392f670dcdfa127547ec77c7e56sewardj                 /*  9 */ ALWAYSDEFD(guest_FC3210),
450385520e44c14bebadea604ba9ba32113b55988227sewardj                 // /* */ ALWAYSDEFD(guest_CS),
450485520e44c14bebadea604ba9ba32113b55988227sewardj                 // /* */ ALWAYSDEFD(guest_DS),
450585520e44c14bebadea604ba9ba32113b55988227sewardj                 // /* */ ALWAYSDEFD(guest_ES),
450685520e44c14bebadea604ba9ba32113b55988227sewardj                 // /* */ ALWAYSDEFD(guest_FS),
450785520e44c14bebadea604ba9ba32113b55988227sewardj                 // /* */ ALWAYSDEFD(guest_GS),
450885520e44c14bebadea604ba9ba32113b55988227sewardj                 // /* */ ALWAYSDEFD(guest_SS),
450985520e44c14bebadea604ba9ba32113b55988227sewardj                 // /* */ ALWAYSDEFD(guest_LDT),
451085520e44c14bebadea604ba9ba32113b55988227sewardj                 // /* */ ALWAYSDEFD(guest_GDT),
45116ef84bed9bb3af22060eb1759788034602bbcc88florian                 /* 10 */ ALWAYSDEFD(guest_EMNOTE),
451216a403bac07df30df6e6587c8c911cf6df3f780dsewardj                 /* 11 */ ALWAYSDEFD(guest_SSEROUND),
451305f5e0172384dd2983fb16fbb7deebd74d71cd35sewardj                 /* 12 */ ALWAYSDEFD(guest_CMSTART),
451405f5e0172384dd2983fb16fbb7deebd74d71cd35sewardj                 /* 13 */ ALWAYSDEFD(guest_CMLEN),
4515e86310f555a233cc2ca02e1a5d0adb555f12bdcdsewardj                 /* 14 */ ALWAYSDEFD(guest_SC_CLASS),
4516e86310f555a233cc2ca02e1a5d0adb555f12bdcdsewardj                 /* 15 */ ALWAYSDEFD(guest_IP_AT_SYSCALL)
451744d494dfad0c12f96f61cf9edfc889dfa69e3b30sewardj               }
451844d494dfad0c12f96f61cf9edfc889dfa69e3b30sewardj        };
45199c6acb0c7f7b5ff5c4a8d5a22259d8151edff499njn
45209c6acb0c7f7b5ff5c4a8d5a22259d8151edff499njn
45219c6acb0c7f7b5ff5c4a8d5a22259d8151edff499njn/*---------------------------------------------------------------*/
4522cef7d3e3df4796e35b4521158d9dc058f034aa87sewardj/*--- end                               guest_amd64_helpers.c ---*/
45239c6acb0c7f7b5ff5c4a8d5a22259d8151edff499njn/*---------------------------------------------------------------*/
4524