blob: ddcccafd5ecdcbaed68f4367daae0a5639464ce4 [file] [log] [blame]
njn9c6acb02004-11-30 15:56:47 +00001
2/*---------------------------------------------------------------*/
sewardj752f9062010-05-03 21:38:49 +00003/*--- begin guest_amd64_helpers.c ---*/
njn9c6acb02004-11-30 15:56:47 +00004/*---------------------------------------------------------------*/
5
6/*
sewardj752f9062010-05-03 21:38:49 +00007 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
njn9c6acb02004-11-30 15:56:47 +00009
sewardj89ae8472013-10-18 14:12:58 +000010 Copyright (C) 2004-2013 OpenWorks LLP
sewardj752f9062010-05-03 21:38:49 +000011 info@open-works.net
njn9c6acb02004-11-30 15:56:47 +000012
sewardj752f9062010-05-03 21:38:49 +000013 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
njn9c6acb02004-11-30 15:56:47 +000017
sewardj752f9062010-05-03 21:38:49 +000018 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
sewardj7bd6ffe2005-08-03 16:07:36 +000026 02110-1301, USA.
27
sewardj752f9062010-05-03 21:38:49 +000028 The GNU General Public License is contained in the file COPYING.
njn9c6acb02004-11-30 15:56:47 +000029
30 Neither the names of the U.S. Department of Energy nor the
31 University of California nor the names of its contributors may be
32 used to endorse or promote products derived from this software
33 without prior written permission.
njn9c6acb02004-11-30 15:56:47 +000034*/
35
36#include "libvex_basictypes.h"
florian33b02432012-08-25 21:48:04 +000037#include "libvex_emnote.h"
njn9c6acb02004-11-30 15:56:47 +000038#include "libvex_guest_amd64.h"
39#include "libvex_ir.h"
40#include "libvex.h"
41
sewardjcef7d3e2009-07-02 12:21:59 +000042#include "main_util.h"
philippe6c46bef2012-08-14 22:29:01 +000043#include "main_globals.h"
sewardjcef7d3e2009-07-02 12:21:59 +000044#include "guest_generic_bb_to_IR.h"
45#include "guest_amd64_defs.h"
46#include "guest_generic_x87.h"
sewardj44d494d2005-01-20 20:26:33 +000047
sewardjf8c37f72005-02-07 18:55:29 +000048
49/* This file contains helper functions for amd64 guest code.
50 Calls to these functions are generated by the back end.
51 These calls are of course in the host machine code and
52 this file will be compiled to host machine code, so that
53 all makes sense.
54
55 Only change the signatures of these helper functions very
56 carefully. If you change the signature here, you'll have to change
57 the parameters passed to it in the IR calls constructed by
58 guest-amd64/toIR.c.
59
60 The convention used is that all functions called from generated
61 code are named amd64g_<something>, and any function whose name lacks
62 that prefix is not called from generated code. Note that some
63 LibVEX_* functions can however be called by VEX's client, but that
64 is not the same as calling them from VEX-generated code.
65*/
66
67
68/* Set to 1 to get detailed profiling info about use of the flag
69 machinery. */
70#define PROFILE_RFLAGS 0
71
72
73/*---------------------------------------------------------------*/
74/*--- %rflags run-time helpers. ---*/
75/*---------------------------------------------------------------*/
76
sewardj1a01e652005-02-23 11:39:21 +000077/* Do 64x64 -> 128 signed/unsigned multiplies, for computing flags
78 after imulq/mulq. */
79
80static void mullS64 ( Long u, Long v, Long* rHi, Long* rLo )
81{
82 ULong u0, v0, w0;
83 Long u1, v1, w1, w2, t;
sewardjdbdc5b32005-03-25 20:31:46 +000084 u0 = u & 0xFFFFFFFFULL;
sewardj1a01e652005-02-23 11:39:21 +000085 u1 = u >> 32;
sewardjdbdc5b32005-03-25 20:31:46 +000086 v0 = v & 0xFFFFFFFFULL;
sewardj1a01e652005-02-23 11:39:21 +000087 v1 = v >> 32;
88 w0 = u0 * v0;
89 t = u1 * v0 + (w0 >> 32);
sewardjdbdc5b32005-03-25 20:31:46 +000090 w1 = t & 0xFFFFFFFFULL;
sewardj1a01e652005-02-23 11:39:21 +000091 w2 = t >> 32;
92 w1 = u0 * v1 + w1;
93 *rHi = u1 * v1 + w2 + (w1 >> 32);
94 *rLo = u * v;
95}
96
97static void mullU64 ( ULong u, ULong v, ULong* rHi, ULong* rLo )
98{
99 ULong u0, v0, w0;
100 ULong u1, v1, w1,w2,t;
sewardjdbdc5b32005-03-25 20:31:46 +0000101 u0 = u & 0xFFFFFFFFULL;
sewardj1a01e652005-02-23 11:39:21 +0000102 u1 = u >> 32;
sewardjdbdc5b32005-03-25 20:31:46 +0000103 v0 = v & 0xFFFFFFFFULL;
sewardj1a01e652005-02-23 11:39:21 +0000104 v1 = v >> 32;
105 w0 = u0 * v0;
106 t = u1 * v0 + (w0 >> 32);
sewardjdbdc5b32005-03-25 20:31:46 +0000107 w1 = t & 0xFFFFFFFFULL;
sewardj1a01e652005-02-23 11:39:21 +0000108 w2 = t >> 32;
109 w1 = u0 * v1 + w1;
110 *rHi = u1 * v1 + w2 + (w1 >> 32);
111 *rLo = u * v;
112}
113
114
sewardjf8c37f72005-02-07 18:55:29 +0000115static const UChar parity_table[256] = {
116 AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
117 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
118 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
119 AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
120 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
121 AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
122 AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
123 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
124 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
125 AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
126 AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
127 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
128 AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
129 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
130 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
131 AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
132 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
133 AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
134 AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
135 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
136 AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
137 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
138 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
139 AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
140 AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
141 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
142 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
143 AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
144 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
145 AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
146 AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
147 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
148};
149
sewardj4a6f3842005-03-26 11:59:23 +0000150/* generalised left-shifter */
sewardj1fa7b802005-03-25 14:39:37 +0000151static inline Long lshift ( Long x, Int n )
sewardj118b23e2005-01-29 02:14:44 +0000152{
sewardjf8c37f72005-02-07 18:55:29 +0000153 if (n >= 0)
154 return x << n;
155 else
156 return x >> (-n);
sewardj118b23e2005-01-29 02:14:44 +0000157}
158
sewardj1fa7b802005-03-25 14:39:37 +0000159/* identity on ULong */
160static inline ULong idULong ( ULong x )
161{
162 return x;
163}
164
sewardj118b23e2005-01-29 02:14:44 +0000165
sewardjf8c37f72005-02-07 18:55:29 +0000166#define PREAMBLE(__data_bits) \
167 /* const */ ULong DATA_MASK \
168 = __data_bits==8 \
169 ? 0xFFULL \
170 : (__data_bits==16 \
171 ? 0xFFFFULL \
172 : (__data_bits==32 \
173 ? 0xFFFFFFFFULL \
174 : 0xFFFFFFFFFFFFFFFFULL)); \
175 /* const */ ULong SIGN_MASK = 1ULL << (__data_bits - 1); \
176 /* const */ ULong CC_DEP1 = cc_dep1_formal; \
177 /* const */ ULong CC_DEP2 = cc_dep2_formal; \
178 /* const */ ULong CC_NDEP = cc_ndep_formal; \
179 /* Four bogus assignments, which hopefully gcc can */ \
180 /* optimise away, and which stop it complaining about */ \
181 /* unused variables. */ \
182 SIGN_MASK = SIGN_MASK; \
183 DATA_MASK = DATA_MASK; \
184 CC_DEP2 = CC_DEP2; \
185 CC_NDEP = CC_NDEP;
186
187
188/*-------------------------------------------------------------*/
189
190#define ACTIONS_ADD(DATA_BITS,DATA_UTYPE) \
191{ \
192 PREAMBLE(DATA_BITS); \
193 { Long cf, pf, af, zf, sf, of; \
194 Long argL, argR, res; \
195 argL = CC_DEP1; \
196 argR = CC_DEP2; \
197 res = argL + argR; \
198 cf = (DATA_UTYPE)res < (DATA_UTYPE)argL; \
199 pf = parity_table[(UChar)res]; \
200 af = (res ^ argL ^ argR) & 0x10; \
201 zf = ((DATA_UTYPE)res == 0) << 6; \
202 sf = lshift(res, 8 - DATA_BITS) & 0x80; \
203 of = lshift((argL ^ argR ^ -1) & (argL ^ res), \
204 12 - DATA_BITS) & AMD64G_CC_MASK_O; \
205 return cf | pf | af | zf | sf | of; \
206 } \
sewardjdf0e0022005-01-25 15:48:43 +0000207}
sewardj44d494d2005-01-20 20:26:33 +0000208
sewardjf8c37f72005-02-07 18:55:29 +0000209/*-------------------------------------------------------------*/
210
211#define ACTIONS_SUB(DATA_BITS,DATA_UTYPE) \
212{ \
213 PREAMBLE(DATA_BITS); \
214 { Long cf, pf, af, zf, sf, of; \
215 Long argL, argR, res; \
216 argL = CC_DEP1; \
217 argR = CC_DEP2; \
218 res = argL - argR; \
219 cf = (DATA_UTYPE)argL < (DATA_UTYPE)argR; \
220 pf = parity_table[(UChar)res]; \
221 af = (res ^ argL ^ argR) & 0x10; \
222 zf = ((DATA_UTYPE)res == 0) << 6; \
223 sf = lshift(res, 8 - DATA_BITS) & 0x80; \
224 of = lshift((argL ^ argR) & (argL ^ res), \
225 12 - DATA_BITS) & AMD64G_CC_MASK_O; \
226 return cf | pf | af | zf | sf | of; \
227 } \
sewardj354e5c62005-01-27 20:12:52 +0000228}
229
sewardjf8c37f72005-02-07 18:55:29 +0000230/*-------------------------------------------------------------*/
231
232#define ACTIONS_ADC(DATA_BITS,DATA_UTYPE) \
233{ \
234 PREAMBLE(DATA_BITS); \
235 { Long cf, pf, af, zf, sf, of; \
236 Long argL, argR, oldC, res; \
237 oldC = CC_NDEP & AMD64G_CC_MASK_C; \
238 argL = CC_DEP1; \
239 argR = CC_DEP2 ^ oldC; \
240 res = (argL + argR) + oldC; \
241 if (oldC) \
242 cf = (DATA_UTYPE)res <= (DATA_UTYPE)argL; \
243 else \
244 cf = (DATA_UTYPE)res < (DATA_UTYPE)argL; \
245 pf = parity_table[(UChar)res]; \
246 af = (res ^ argL ^ argR) & 0x10; \
247 zf = ((DATA_UTYPE)res == 0) << 6; \
248 sf = lshift(res, 8 - DATA_BITS) & 0x80; \
249 of = lshift((argL ^ argR ^ -1) & (argL ^ res), \
250 12 - DATA_BITS) & AMD64G_CC_MASK_O; \
251 return cf | pf | af | zf | sf | of; \
252 } \
253}
254
255/*-------------------------------------------------------------*/
256
257#define ACTIONS_SBB(DATA_BITS,DATA_UTYPE) \
258{ \
259 PREAMBLE(DATA_BITS); \
260 { Long cf, pf, af, zf, sf, of; \
261 Long argL, argR, oldC, res; \
262 oldC = CC_NDEP & AMD64G_CC_MASK_C; \
263 argL = CC_DEP1; \
264 argR = CC_DEP2 ^ oldC; \
265 res = (argL - argR) - oldC; \
266 if (oldC) \
267 cf = (DATA_UTYPE)argL <= (DATA_UTYPE)argR; \
268 else \
269 cf = (DATA_UTYPE)argL < (DATA_UTYPE)argR; \
270 pf = parity_table[(UChar)res]; \
271 af = (res ^ argL ^ argR) & 0x10; \
272 zf = ((DATA_UTYPE)res == 0) << 6; \
273 sf = lshift(res, 8 - DATA_BITS) & 0x80; \
274 of = lshift((argL ^ argR) & (argL ^ res), \
275 12 - DATA_BITS) & AMD64G_CC_MASK_O; \
276 return cf | pf | af | zf | sf | of; \
277 } \
278}
279
280/*-------------------------------------------------------------*/
281
282#define ACTIONS_LOGIC(DATA_BITS,DATA_UTYPE) \
283{ \
284 PREAMBLE(DATA_BITS); \
285 { Long cf, pf, af, zf, sf, of; \
286 cf = 0; \
287 pf = parity_table[(UChar)CC_DEP1]; \
288 af = 0; \
289 zf = ((DATA_UTYPE)CC_DEP1 == 0) << 6; \
290 sf = lshift(CC_DEP1, 8 - DATA_BITS) & 0x80; \
291 of = 0; \
292 return cf | pf | af | zf | sf | of; \
293 } \
294}
295
296/*-------------------------------------------------------------*/
297
298#define ACTIONS_INC(DATA_BITS,DATA_UTYPE) \
299{ \
300 PREAMBLE(DATA_BITS); \
301 { Long cf, pf, af, zf, sf, of; \
302 Long argL, argR, res; \
303 res = CC_DEP1; \
304 argL = res - 1; \
305 argR = 1; \
306 cf = CC_NDEP & AMD64G_CC_MASK_C; \
307 pf = parity_table[(UChar)res]; \
308 af = (res ^ argL ^ argR) & 0x10; \
309 zf = ((DATA_UTYPE)res == 0) << 6; \
310 sf = lshift(res, 8 - DATA_BITS) & 0x80; \
311 of = ((res & DATA_MASK) == SIGN_MASK) << 11; \
312 return cf | pf | af | zf | sf | of; \
313 } \
314}
315
316/*-------------------------------------------------------------*/
317
318#define ACTIONS_DEC(DATA_BITS,DATA_UTYPE) \
319{ \
320 PREAMBLE(DATA_BITS); \
321 { Long cf, pf, af, zf, sf, of; \
322 Long argL, argR, res; \
323 res = CC_DEP1; \
324 argL = res + 1; \
325 argR = 1; \
326 cf = CC_NDEP & AMD64G_CC_MASK_C; \
327 pf = parity_table[(UChar)res]; \
328 af = (res ^ argL ^ argR) & 0x10; \
329 zf = ((DATA_UTYPE)res == 0) << 6; \
330 sf = lshift(res, 8 - DATA_BITS) & 0x80; \
331 of = ((res & DATA_MASK) \
332 == ((ULong)SIGN_MASK - 1)) << 11; \
333 return cf | pf | af | zf | sf | of; \
334 } \
335}
336
337/*-------------------------------------------------------------*/
338
339#define ACTIONS_SHL(DATA_BITS,DATA_UTYPE) \
340{ \
341 PREAMBLE(DATA_BITS); \
342 { Long cf, pf, af, zf, sf, of; \
343 cf = (CC_DEP2 >> (DATA_BITS - 1)) & AMD64G_CC_MASK_C; \
344 pf = parity_table[(UChar)CC_DEP1]; \
345 af = 0; /* undefined */ \
346 zf = ((DATA_UTYPE)CC_DEP1 == 0) << 6; \
347 sf = lshift(CC_DEP1, 8 - DATA_BITS) & 0x80; \
348 /* of is defined if shift count == 1 */ \
349 of = lshift(CC_DEP2 ^ CC_DEP1, 12 - DATA_BITS) \
350 & AMD64G_CC_MASK_O; \
351 return cf | pf | af | zf | sf | of; \
352 } \
353}
354
355/*-------------------------------------------------------------*/
356
357#define ACTIONS_SHR(DATA_BITS,DATA_UTYPE) \
358{ \
359 PREAMBLE(DATA_BITS); \
360 { Long cf, pf, af, zf, sf, of; \
361 cf = CC_DEP2 & 1; \
362 pf = parity_table[(UChar)CC_DEP1]; \
363 af = 0; /* undefined */ \
364 zf = ((DATA_UTYPE)CC_DEP1 == 0) << 6; \
365 sf = lshift(CC_DEP1, 8 - DATA_BITS) & 0x80; \
366 /* of is defined if shift count == 1 */ \
367 of = lshift(CC_DEP2 ^ CC_DEP1, 12 - DATA_BITS) \
368 & AMD64G_CC_MASK_O; \
369 return cf | pf | af | zf | sf | of; \
370 } \
371}
372
373/*-------------------------------------------------------------*/
374
375/* ROL: cf' = lsb(result). of' = msb(result) ^ lsb(result). */
376/* DEP1 = result, NDEP = old flags */
377#define ACTIONS_ROL(DATA_BITS,DATA_UTYPE) \
378{ \
379 PREAMBLE(DATA_BITS); \
380 { Long fl \
381 = (CC_NDEP & ~(AMD64G_CC_MASK_O | AMD64G_CC_MASK_C)) \
sewardj7de0d3c2005-02-13 02:26:41 +0000382 | (AMD64G_CC_MASK_C & CC_DEP1) \
sewardjf8c37f72005-02-07 18:55:29 +0000383 | (AMD64G_CC_MASK_O & (lshift(CC_DEP1, \
384 11-(DATA_BITS-1)) \
385 ^ lshift(CC_DEP1, 11))); \
386 return fl; \
387 } \
388}
389
390/*-------------------------------------------------------------*/
391
392/* ROR: cf' = msb(result). of' = msb(result) ^ msb-1(result). */
393/* DEP1 = result, NDEP = old flags */
394#define ACTIONS_ROR(DATA_BITS,DATA_UTYPE) \
395{ \
396 PREAMBLE(DATA_BITS); \
397 { Long fl \
398 = (CC_NDEP & ~(AMD64G_CC_MASK_O | AMD64G_CC_MASK_C)) \
399 | (AMD64G_CC_MASK_C & (CC_DEP1 >> (DATA_BITS-1))) \
400 | (AMD64G_CC_MASK_O & (lshift(CC_DEP1, \
401 11-(DATA_BITS-1)) \
402 ^ lshift(CC_DEP1, 11-(DATA_BITS-1)+1))); \
403 return fl; \
404 } \
405}
406
407/*-------------------------------------------------------------*/
408
sewardj1fa7b802005-03-25 14:39:37 +0000409#define ACTIONS_UMUL(DATA_BITS, DATA_UTYPE, NARROWtoU, \
410 DATA_U2TYPE, NARROWto2U) \
sewardjf8c37f72005-02-07 18:55:29 +0000411{ \
412 PREAMBLE(DATA_BITS); \
413 { Long cf, pf, af, zf, sf, of; \
414 DATA_UTYPE hi; \
sewardj1fa7b802005-03-25 14:39:37 +0000415 DATA_UTYPE lo \
416 = NARROWtoU( ((DATA_UTYPE)CC_DEP1) \
417 * ((DATA_UTYPE)CC_DEP2) ); \
418 DATA_U2TYPE rr \
419 = NARROWto2U( \
420 ((DATA_U2TYPE)((DATA_UTYPE)CC_DEP1)) \
421 * ((DATA_U2TYPE)((DATA_UTYPE)CC_DEP2)) ); \
422 hi = NARROWtoU(rr >>/*u*/ DATA_BITS); \
sewardjf8c37f72005-02-07 18:55:29 +0000423 cf = (hi != 0); \
424 pf = parity_table[(UChar)lo]; \
425 af = 0; /* undefined */ \
426 zf = (lo == 0) << 6; \
427 sf = lshift(lo, 8 - DATA_BITS) & 0x80; \
428 of = cf << 11; \
429 return cf | pf | af | zf | sf | of; \
430 } \
431}
432
433/*-------------------------------------------------------------*/
434
sewardj1fa7b802005-03-25 14:39:37 +0000435#define ACTIONS_SMUL(DATA_BITS, DATA_STYPE, NARROWtoS, \
436 DATA_S2TYPE, NARROWto2S) \
sewardjf8c37f72005-02-07 18:55:29 +0000437{ \
438 PREAMBLE(DATA_BITS); \
439 { Long cf, pf, af, zf, sf, of; \
440 DATA_STYPE hi; \
sewardj1fa7b802005-03-25 14:39:37 +0000441 DATA_STYPE lo \
442 = NARROWtoS( ((DATA_STYPE)CC_DEP1) \
443 * ((DATA_STYPE)CC_DEP2) ); \
444 DATA_S2TYPE rr \
445 = NARROWto2S( \
446 ((DATA_S2TYPE)((DATA_STYPE)CC_DEP1)) \
447 * ((DATA_S2TYPE)((DATA_STYPE)CC_DEP2)) ); \
448 hi = NARROWtoS(rr >>/*s*/ DATA_BITS); \
sewardjf8c37f72005-02-07 18:55:29 +0000449 cf = (hi != (lo >>/*s*/ (DATA_BITS-1))); \
450 pf = parity_table[(UChar)lo]; \
451 af = 0; /* undefined */ \
452 zf = (lo == 0) << 6; \
453 sf = lshift(lo, 8 - DATA_BITS) & 0x80; \
454 of = cf << 11; \
455 return cf | pf | af | zf | sf | of; \
456 } \
457}
458
sewardj1a01e652005-02-23 11:39:21 +0000459/*-------------------------------------------------------------*/
460
461#define ACTIONS_UMULQ \
462{ \
463 PREAMBLE(64); \
464 { Long cf, pf, af, zf, sf, of; \
465 ULong lo, hi; \
466 mullU64( (ULong)CC_DEP1, (ULong)CC_DEP2, &hi, &lo ); \
467 cf = (hi != 0); \
468 pf = parity_table[(UChar)lo]; \
469 af = 0; /* undefined */ \
470 zf = (lo == 0) << 6; \
471 sf = lshift(lo, 8 - 64) & 0x80; \
472 of = cf << 11; \
473 return cf | pf | af | zf | sf | of; \
474 } \
475}
476
477/*-------------------------------------------------------------*/
478
479#define ACTIONS_SMULQ \
480{ \
481 PREAMBLE(64); \
482 { Long cf, pf, af, zf, sf, of; \
483 Long lo, hi; \
484 mullS64( (Long)CC_DEP1, (Long)CC_DEP2, &hi, &lo ); \
485 cf = (hi != (lo >>/*s*/ (64-1))); \
486 pf = parity_table[(UChar)lo]; \
487 af = 0; /* undefined */ \
488 zf = (lo == 0) << 6; \
489 sf = lshift(lo, 8 - 64) & 0x80; \
490 of = cf << 11; \
491 return cf | pf | af | zf | sf | of; \
492 } \
493}
494
sewardjcc3d2192013-03-27 11:37:33 +0000495/*-------------------------------------------------------------*/
496
497#define ACTIONS_ANDN(DATA_BITS,DATA_UTYPE) \
498{ \
499 PREAMBLE(DATA_BITS); \
500 { Long cf, pf, af, zf, sf, of; \
501 cf = 0; \
502 pf = 0; \
503 af = 0; \
504 zf = ((DATA_UTYPE)CC_DEP1 == 0) << 6; \
505 sf = lshift(CC_DEP1, 8 - DATA_BITS) & 0x80; \
506 of = 0; \
507 return cf | pf | af | zf | sf | of; \
508 } \
509}
510
511/*-------------------------------------------------------------*/
512
513#define ACTIONS_BLSI(DATA_BITS,DATA_UTYPE) \
514{ \
515 PREAMBLE(DATA_BITS); \
516 { Long cf, pf, af, zf, sf, of; \
517 cf = ((DATA_UTYPE)CC_DEP2 != 0); \
518 pf = 0; \
519 af = 0; \
520 zf = ((DATA_UTYPE)CC_DEP1 == 0) << 6; \
521 sf = lshift(CC_DEP1, 8 - DATA_BITS) & 0x80; \
522 of = 0; \
523 return cf | pf | af | zf | sf | of; \
524 } \
525}
526
527/*-------------------------------------------------------------*/
528
529#define ACTIONS_BLSMSK(DATA_BITS,DATA_UTYPE) \
530{ \
531 PREAMBLE(DATA_BITS); \
532 { Long cf, pf, af, zf, sf, of; \
533 cf = ((DATA_UTYPE)CC_DEP2 == 0); \
534 pf = 0; \
535 af = 0; \
536 zf = 0; \
537 sf = lshift(CC_DEP1, 8 - DATA_BITS) & 0x80; \
538 of = 0; \
539 return cf | pf | af | zf | sf | of; \
540 } \
541}
542
543/*-------------------------------------------------------------*/
544
545#define ACTIONS_BLSR(DATA_BITS,DATA_UTYPE) \
546{ \
547 PREAMBLE(DATA_BITS); \
548 { Long cf, pf, af, zf, sf, of; \
549 cf = ((DATA_UTYPE)CC_DEP2 == 0); \
550 pf = 0; \
551 af = 0; \
552 zf = ((DATA_UTYPE)CC_DEP1 == 0) << 6; \
553 sf = lshift(CC_DEP1, 8 - DATA_BITS) & 0x80; \
554 of = 0; \
555 return cf | pf | af | zf | sf | of; \
556 } \
557}
558
559/*-------------------------------------------------------------*/
560
sewardjf8c37f72005-02-07 18:55:29 +0000561
sewardj1fa7b802005-03-25 14:39:37 +0000562#if PROFILE_RFLAGS
sewardjf8c37f72005-02-07 18:55:29 +0000563
564static Bool initted = False;
565
566/* C flag, fast route */
567static UInt tabc_fast[AMD64G_CC_OP_NUMBER];
568/* C flag, slow route */
569static UInt tabc_slow[AMD64G_CC_OP_NUMBER];
570/* table for calculate_cond */
571static UInt tab_cond[AMD64G_CC_OP_NUMBER][16];
572/* total entry counts for calc_all, calc_c, calc_cond. */
573static UInt n_calc_all = 0;
574static UInt n_calc_c = 0;
575static UInt n_calc_cond = 0;
576
577#define SHOW_COUNTS_NOW (0 == (0x3FFFFF & (n_calc_all+n_calc_c+n_calc_cond)))
578
579
580static void showCounts ( void )
581{
582 Int op, co;
florian5df8ab02012-10-13 19:34:19 +0000583 HChar ch;
sewardj1fa7b802005-03-25 14:39:37 +0000584 vex_printf("\nTotal calls: calc_all=%u calc_cond=%u calc_c=%u\n",
sewardjf8c37f72005-02-07 18:55:29 +0000585 n_calc_all, n_calc_cond, n_calc_c);
586
587 vex_printf(" cSLOW cFAST O NO B NB Z NZ BE NBE"
588 " S NS P NP L NL LE NLE\n");
589 vex_printf(" -----------------------------------------------------"
590 "----------------------------------------\n");
591 for (op = 0; op < AMD64G_CC_OP_NUMBER; op++) {
592
593 ch = ' ';
sewardj03540352005-04-26 01:53:48 +0000594 if (op > 0 && (op-1) % 4 == 0)
sewardjf8c37f72005-02-07 18:55:29 +0000595 ch = 'B';
sewardj03540352005-04-26 01:53:48 +0000596 if (op > 0 && (op-1) % 4 == 1)
sewardjf8c37f72005-02-07 18:55:29 +0000597 ch = 'W';
sewardj03540352005-04-26 01:53:48 +0000598 if (op > 0 && (op-1) % 4 == 2)
sewardjf8c37f72005-02-07 18:55:29 +0000599 ch = 'L';
sewardj03540352005-04-26 01:53:48 +0000600 if (op > 0 && (op-1) % 4 == 3)
601 ch = 'Q';
sewardjf8c37f72005-02-07 18:55:29 +0000602
603 vex_printf("%2d%c: ", op, ch);
sewardj1fa7b802005-03-25 14:39:37 +0000604 vex_printf("%6u ", tabc_slow[op]);
605 vex_printf("%6u ", tabc_fast[op]);
sewardjf8c37f72005-02-07 18:55:29 +0000606 for (co = 0; co < 16; co++) {
607 Int n = tab_cond[op][co];
608 if (n >= 1000) {
609 vex_printf(" %3dK", n / 1000);
610 } else
611 if (n >= 0) {
612 vex_printf(" %3d ", n );
613 } else {
614 vex_printf(" ");
615 }
616 }
617 vex_printf("\n");
618 }
619 vex_printf("\n");
620}
621
622static void initCounts ( void )
623{
624 Int op, co;
625 initted = True;
626 for (op = 0; op < AMD64G_CC_OP_NUMBER; op++) {
627 tabc_fast[op] = tabc_slow[op] = 0;
628 for (co = 0; co < 16; co++)
629 tab_cond[op][co] = 0;
630 }
631}
632
sewardj1fa7b802005-03-25 14:39:37 +0000633#endif /* PROFILE_RFLAGS */
sewardjf8c37f72005-02-07 18:55:29 +0000634
635
636/* CALLED FROM GENERATED CODE: CLEAN HELPER */
637/* Calculate all the 6 flags from the supplied thunk parameters.
638 Worker function, not directly called from generated code. */
639static
640ULong amd64g_calculate_rflags_all_WRK ( ULong cc_op,
641 ULong cc_dep1_formal,
642 ULong cc_dep2_formal,
643 ULong cc_ndep_formal )
644{
645 switch (cc_op) {
646 case AMD64G_CC_OP_COPY:
647 return cc_dep1_formal
648 & (AMD64G_CC_MASK_O | AMD64G_CC_MASK_S | AMD64G_CC_MASK_Z
649 | AMD64G_CC_MASK_A | AMD64G_CC_MASK_C | AMD64G_CC_MASK_P);
650
651 case AMD64G_CC_OP_ADDB: ACTIONS_ADD( 8, UChar );
652 case AMD64G_CC_OP_ADDW: ACTIONS_ADD( 16, UShort );
653 case AMD64G_CC_OP_ADDL: ACTIONS_ADD( 32, UInt );
sewardjd0a12df2005-02-10 02:07:43 +0000654 case AMD64G_CC_OP_ADDQ: ACTIONS_ADD( 64, ULong );
sewardjf8c37f72005-02-07 18:55:29 +0000655
656 case AMD64G_CC_OP_ADCB: ACTIONS_ADC( 8, UChar );
657 case AMD64G_CC_OP_ADCW: ACTIONS_ADC( 16, UShort );
658 case AMD64G_CC_OP_ADCL: ACTIONS_ADC( 32, UInt );
sewardj85520e42005-02-19 15:22:38 +0000659 case AMD64G_CC_OP_ADCQ: ACTIONS_ADC( 64, ULong );
sewardjf8c37f72005-02-07 18:55:29 +0000660
661 case AMD64G_CC_OP_SUBB: ACTIONS_SUB( 8, UChar );
662 case AMD64G_CC_OP_SUBW: ACTIONS_SUB( 16, UShort );
663 case AMD64G_CC_OP_SUBL: ACTIONS_SUB( 32, UInt );
664 case AMD64G_CC_OP_SUBQ: ACTIONS_SUB( 64, ULong );
665
666 case AMD64G_CC_OP_SBBB: ACTIONS_SBB( 8, UChar );
667 case AMD64G_CC_OP_SBBW: ACTIONS_SBB( 16, UShort );
668 case AMD64G_CC_OP_SBBL: ACTIONS_SBB( 32, UInt );
sewardj85520e42005-02-19 15:22:38 +0000669 case AMD64G_CC_OP_SBBQ: ACTIONS_SBB( 64, ULong );
sewardjf8c37f72005-02-07 18:55:29 +0000670
671 case AMD64G_CC_OP_LOGICB: ACTIONS_LOGIC( 8, UChar );
672 case AMD64G_CC_OP_LOGICW: ACTIONS_LOGIC( 16, UShort );
673 case AMD64G_CC_OP_LOGICL: ACTIONS_LOGIC( 32, UInt );
674 case AMD64G_CC_OP_LOGICQ: ACTIONS_LOGIC( 64, ULong );
675
676 case AMD64G_CC_OP_INCB: ACTIONS_INC( 8, UChar );
677 case AMD64G_CC_OP_INCW: ACTIONS_INC( 16, UShort );
678 case AMD64G_CC_OP_INCL: ACTIONS_INC( 32, UInt );
sewardj7de0d3c2005-02-13 02:26:41 +0000679 case AMD64G_CC_OP_INCQ: ACTIONS_INC( 64, ULong );
sewardjf8c37f72005-02-07 18:55:29 +0000680
681 case AMD64G_CC_OP_DECB: ACTIONS_DEC( 8, UChar );
682 case AMD64G_CC_OP_DECW: ACTIONS_DEC( 16, UShort );
683 case AMD64G_CC_OP_DECL: ACTIONS_DEC( 32, UInt );
sewardj7de0d3c2005-02-13 02:26:41 +0000684 case AMD64G_CC_OP_DECQ: ACTIONS_DEC( 64, ULong );
sewardjf8c37f72005-02-07 18:55:29 +0000685
686 case AMD64G_CC_OP_SHLB: ACTIONS_SHL( 8, UChar );
687 case AMD64G_CC_OP_SHLW: ACTIONS_SHL( 16, UShort );
688 case AMD64G_CC_OP_SHLL: ACTIONS_SHL( 32, UInt );
sewardj7de0d3c2005-02-13 02:26:41 +0000689 case AMD64G_CC_OP_SHLQ: ACTIONS_SHL( 64, ULong );
sewardjf8c37f72005-02-07 18:55:29 +0000690
691 case AMD64G_CC_OP_SHRB: ACTIONS_SHR( 8, UChar );
692 case AMD64G_CC_OP_SHRW: ACTIONS_SHR( 16, UShort );
693 case AMD64G_CC_OP_SHRL: ACTIONS_SHR( 32, UInt );
sewardja6b93d12005-02-17 09:28:28 +0000694 case AMD64G_CC_OP_SHRQ: ACTIONS_SHR( 64, ULong );
sewardjf8c37f72005-02-07 18:55:29 +0000695
696 case AMD64G_CC_OP_ROLB: ACTIONS_ROL( 8, UChar );
697 case AMD64G_CC_OP_ROLW: ACTIONS_ROL( 16, UShort );
698 case AMD64G_CC_OP_ROLL: ACTIONS_ROL( 32, UInt );
sewardj85520e42005-02-19 15:22:38 +0000699 case AMD64G_CC_OP_ROLQ: ACTIONS_ROL( 64, ULong );
sewardjf8c37f72005-02-07 18:55:29 +0000700
701 case AMD64G_CC_OP_RORB: ACTIONS_ROR( 8, UChar );
702 case AMD64G_CC_OP_RORW: ACTIONS_ROR( 16, UShort );
703 case AMD64G_CC_OP_RORL: ACTIONS_ROR( 32, UInt );
sewardj85520e42005-02-19 15:22:38 +0000704 case AMD64G_CC_OP_RORQ: ACTIONS_ROR( 64, ULong );
sewardjf8c37f72005-02-07 18:55:29 +0000705
sewardj1fa7b802005-03-25 14:39:37 +0000706 case AMD64G_CC_OP_UMULB: ACTIONS_UMUL( 8, UChar, toUChar,
707 UShort, toUShort );
708 case AMD64G_CC_OP_UMULW: ACTIONS_UMUL( 16, UShort, toUShort,
709 UInt, toUInt );
710 case AMD64G_CC_OP_UMULL: ACTIONS_UMUL( 32, UInt, toUInt,
711 ULong, idULong );
sewardjf8c37f72005-02-07 18:55:29 +0000712
sewardj8bdb89a2005-05-05 21:46:50 +0000713 case AMD64G_CC_OP_UMULQ: ACTIONS_UMULQ;
714
sewardj1fa7b802005-03-25 14:39:37 +0000715 case AMD64G_CC_OP_SMULB: ACTIONS_SMUL( 8, Char, toUChar,
716 Short, toUShort );
717 case AMD64G_CC_OP_SMULW: ACTIONS_SMUL( 16, Short, toUShort,
718 Int, toUInt );
719 case AMD64G_CC_OP_SMULL: ACTIONS_SMUL( 32, Int, toUInt,
720 Long, idULong );
721
sewardj1a01e652005-02-23 11:39:21 +0000722 case AMD64G_CC_OP_SMULQ: ACTIONS_SMULQ;
sewardjf8c37f72005-02-07 18:55:29 +0000723
sewardjcc3d2192013-03-27 11:37:33 +0000724 case AMD64G_CC_OP_ANDN32: ACTIONS_ANDN( 32, UInt );
725 case AMD64G_CC_OP_ANDN64: ACTIONS_ANDN( 64, ULong );
726
727 case AMD64G_CC_OP_BLSI32: ACTIONS_BLSI( 32, UInt );
728 case AMD64G_CC_OP_BLSI64: ACTIONS_BLSI( 64, ULong );
729
730 case AMD64G_CC_OP_BLSMSK32: ACTIONS_BLSMSK( 32, UInt );
731 case AMD64G_CC_OP_BLSMSK64: ACTIONS_BLSMSK( 64, ULong );
732
733 case AMD64G_CC_OP_BLSR32: ACTIONS_BLSR( 32, UInt );
734 case AMD64G_CC_OP_BLSR64: ACTIONS_BLSR( 64, ULong );
735
sewardjf8c37f72005-02-07 18:55:29 +0000736 default:
737 /* shouldn't really make these calls from generated code */
738 vex_printf("amd64g_calculate_rflags_all_WRK(AMD64)"
sewardj1fa7b802005-03-25 14:39:37 +0000739 "( %llu, 0x%llx, 0x%llx, 0x%llx )\n",
sewardjf8c37f72005-02-07 18:55:29 +0000740 cc_op, cc_dep1_formal, cc_dep2_formal, cc_ndep_formal );
741 vpanic("amd64g_calculate_rflags_all_WRK(AMD64)");
742 }
743}
744
745
746/* CALLED FROM GENERATED CODE: CLEAN HELPER */
747/* Calculate all the 6 flags from the supplied thunk parameters. */
748ULong amd64g_calculate_rflags_all ( ULong cc_op,
749 ULong cc_dep1,
750 ULong cc_dep2,
751 ULong cc_ndep )
752{
sewardj1fa7b802005-03-25 14:39:37 +0000753# if PROFILE_RFLAGS
sewardjf8c37f72005-02-07 18:55:29 +0000754 if (!initted) initCounts();
755 n_calc_all++;
756 if (SHOW_COUNTS_NOW) showCounts();
757# endif
758 return
759 amd64g_calculate_rflags_all_WRK ( cc_op, cc_dep1, cc_dep2, cc_ndep );
760}
761
762
763/* CALLED FROM GENERATED CODE: CLEAN HELPER */
764/* Calculate just the carry flag from the supplied thunk parameters. */
765ULong amd64g_calculate_rflags_c ( ULong cc_op,
766 ULong cc_dep1,
767 ULong cc_dep2,
768 ULong cc_ndep )
769{
sewardj1fa7b802005-03-25 14:39:37 +0000770# if PROFILE_RFLAGS
sewardjf8c37f72005-02-07 18:55:29 +0000771 if (!initted) initCounts();
772 n_calc_c++;
773 tabc_fast[cc_op]++;
774 if (SHOW_COUNTS_NOW) showCounts();
775# endif
776
777 /* Fast-case some common ones. */
778 switch (cc_op) {
sewardj7fc494b2005-05-05 12:05:11 +0000779 case AMD64G_CC_OP_COPY:
780 return (cc_dep1 >> AMD64G_CC_SHIFT_C) & 1;
sewardj03540352005-04-26 01:53:48 +0000781 case AMD64G_CC_OP_LOGICQ:
sewardjf8c37f72005-02-07 18:55:29 +0000782 case AMD64G_CC_OP_LOGICL:
783 case AMD64G_CC_OP_LOGICW:
784 case AMD64G_CC_OP_LOGICB:
785 return 0;
sewardj03540352005-04-26 01:53:48 +0000786 // case AMD64G_CC_OP_SUBL:
787 // return ((UInt)cc_dep1) < ((UInt)cc_dep2)
788 // ? AMD64G_CC_MASK_C : 0;
789 // case AMD64G_CC_OP_SUBW:
790 // return ((UInt)(cc_dep1 & 0xFFFF)) < ((UInt)(cc_dep2 & 0xFFFF))
791 // ? AMD64G_CC_MASK_C : 0;
792 // case AMD64G_CC_OP_SUBB:
793 // return ((UInt)(cc_dep1 & 0xFF)) < ((UInt)(cc_dep2 & 0xFF))
794 // ? AMD64G_CC_MASK_C : 0;
795 // case AMD64G_CC_OP_INCL:
796 // case AMD64G_CC_OP_DECL:
797 // return cc_ndep & AMD64G_CC_MASK_C;
sewardjf8c37f72005-02-07 18:55:29 +0000798 default:
799 break;
800 }
801
sewardj1fa7b802005-03-25 14:39:37 +0000802# if PROFILE_RFLAGS
sewardjf8c37f72005-02-07 18:55:29 +0000803 tabc_fast[cc_op]--;
804 tabc_slow[cc_op]++;
805# endif
806
807 return amd64g_calculate_rflags_all_WRK(cc_op,cc_dep1,cc_dep2,cc_ndep)
808 & AMD64G_CC_MASK_C;
809}
810
811
812/* CALLED FROM GENERATED CODE: CLEAN HELPER */
813/* returns 1 or 0 */
814ULong amd64g_calculate_condition ( ULong/*AMD64Condcode*/ cond,
815 ULong cc_op,
816 ULong cc_dep1,
817 ULong cc_dep2,
818 ULong cc_ndep )
819{
820 ULong rflags = amd64g_calculate_rflags_all_WRK(cc_op, cc_dep1,
821 cc_dep2, cc_ndep);
822 ULong of,sf,zf,cf,pf;
823 ULong inv = cond & 1;
824
sewardj1fa7b802005-03-25 14:39:37 +0000825# if PROFILE_RFLAGS
sewardjf8c37f72005-02-07 18:55:29 +0000826 if (!initted) initCounts();
827 tab_cond[cc_op][cond]++;
828 n_calc_cond++;
829 if (SHOW_COUNTS_NOW) showCounts();
830# endif
831
832 switch (cond) {
833 case AMD64CondNO:
834 case AMD64CondO: /* OF == 1 */
835 of = rflags >> AMD64G_CC_SHIFT_O;
836 return 1 & (inv ^ of);
837
838 case AMD64CondNZ:
839 case AMD64CondZ: /* ZF == 1 */
840 zf = rflags >> AMD64G_CC_SHIFT_Z;
841 return 1 & (inv ^ zf);
842
843 case AMD64CondNB:
844 case AMD64CondB: /* CF == 1 */
845 cf = rflags >> AMD64G_CC_SHIFT_C;
846 return 1 & (inv ^ cf);
847 break;
848
849 case AMD64CondNBE:
850 case AMD64CondBE: /* (CF or ZF) == 1 */
851 cf = rflags >> AMD64G_CC_SHIFT_C;
852 zf = rflags >> AMD64G_CC_SHIFT_Z;
853 return 1 & (inv ^ (cf | zf));
854 break;
855
856 case AMD64CondNS:
857 case AMD64CondS: /* SF == 1 */
858 sf = rflags >> AMD64G_CC_SHIFT_S;
859 return 1 & (inv ^ sf);
860
861 case AMD64CondNP:
862 case AMD64CondP: /* PF == 1 */
863 pf = rflags >> AMD64G_CC_SHIFT_P;
864 return 1 & (inv ^ pf);
865
866 case AMD64CondNL:
867 case AMD64CondL: /* (SF xor OF) == 1 */
868 sf = rflags >> AMD64G_CC_SHIFT_S;
869 of = rflags >> AMD64G_CC_SHIFT_O;
870 return 1 & (inv ^ (sf ^ of));
871 break;
872
873 case AMD64CondNLE:
874 case AMD64CondLE: /* ((SF xor OF) or ZF) == 1 */
875 sf = rflags >> AMD64G_CC_SHIFT_S;
876 of = rflags >> AMD64G_CC_SHIFT_O;
877 zf = rflags >> AMD64G_CC_SHIFT_Z;
878 return 1 & (inv ^ ((sf ^ of) | zf));
879 break;
880
881 default:
882 /* shouldn't really make these calls from generated code */
883 vex_printf("amd64g_calculate_condition"
sewardj1fa7b802005-03-25 14:39:37 +0000884 "( %llu, %llu, 0x%llx, 0x%llx, 0x%llx )\n",
sewardjf8c37f72005-02-07 18:55:29 +0000885 cond, cc_op, cc_dep1, cc_dep2, cc_ndep );
886 vpanic("amd64g_calculate_condition");
887 }
888}
889
890
891/* VISIBLE TO LIBVEX CLIENT */
florianefa834a2012-11-24 21:07:14 +0000892ULong LibVEX_GuestAMD64_get_rflags ( /*IN*/const VexGuestAMD64State* vex_state )
sewardjf8c37f72005-02-07 18:55:29 +0000893{
894 ULong rflags = amd64g_calculate_rflags_all_WRK(
895 vex_state->guest_CC_OP,
896 vex_state->guest_CC_DEP1,
897 vex_state->guest_CC_DEP2,
898 vex_state->guest_CC_NDEP
899 );
sewardj7de0d3c2005-02-13 02:26:41 +0000900 Long dflag = vex_state->guest_DFLAG;
901 vassert(dflag == 1 || dflag == -1);
902 if (dflag == -1)
sewardjf8c37f72005-02-07 18:55:29 +0000903 rflags |= (1<<10);
sewardj85520e42005-02-19 15:22:38 +0000904 if (vex_state->guest_IDFLAG == 1)
905 rflags |= (1<<21);
sewardj5e120aa2010-09-28 15:59:04 +0000906 if (vex_state->guest_ACFLAG == 1)
907 rflags |= (1<<18);
908
sewardjf8c37f72005-02-07 18:55:29 +0000909 return rflags;
910}
sewardjf8c37f72005-02-07 18:55:29 +0000911
sewardjd660d412008-12-03 21:29:59 +0000912/* VISIBLE TO LIBVEX CLIENT */
913void
914LibVEX_GuestAMD64_put_rflag_c ( ULong new_carry_flag,
915 /*MOD*/VexGuestAMD64State* vex_state )
916{
917 ULong oszacp = amd64g_calculate_rflags_all_WRK(
918 vex_state->guest_CC_OP,
919 vex_state->guest_CC_DEP1,
920 vex_state->guest_CC_DEP2,
921 vex_state->guest_CC_NDEP
922 );
923 if (new_carry_flag & 1) {
924 oszacp |= AMD64G_CC_MASK_C;
925 } else {
926 oszacp &= ~AMD64G_CC_MASK_C;
927 }
928 vex_state->guest_CC_OP = AMD64G_CC_OP_COPY;
929 vex_state->guest_CC_DEP1 = oszacp;
930 vex_state->guest_CC_DEP2 = 0;
931 vex_state->guest_CC_NDEP = 0;
932}
933
sewardjf8c37f72005-02-07 18:55:29 +0000934
935/*---------------------------------------------------------------*/
936/*--- %rflags translation-time function specialisers. ---*/
937/*--- These help iropt specialise calls the above run-time ---*/
938/*--- %rflags functions. ---*/
939/*---------------------------------------------------------------*/
940
sewardj03540352005-04-26 01:53:48 +0000941/* Used by the optimiser to try specialisations. Returns an
942 equivalent expression, or NULL if none. */
943
944static Bool isU64 ( IRExpr* e, ULong n )
945{
sewardj65b17c62005-05-02 15:52:44 +0000946 return toBool( e->tag == Iex_Const
947 && e->Iex.Const.con->tag == Ico_U64
948 && e->Iex.Const.con->Ico.U64 == n );
sewardj03540352005-04-26 01:53:48 +0000949}
sewardj354e5c62005-01-27 20:12:52 +0000950
florian1ff47562012-10-21 02:09:51 +0000951IRExpr* guest_amd64_spechelper ( const HChar* function_name,
sewardjbe917912010-08-22 12:38:53 +0000952 IRExpr** args,
953 IRStmt** precedingStmts,
954 Int n_precedingStmts )
sewardj44d494d2005-01-20 20:26:33 +0000955{
sewardj03540352005-04-26 01:53:48 +0000956# define unop(_op,_a1) IRExpr_Unop((_op),(_a1))
957# define binop(_op,_a1,_a2) IRExpr_Binop((_op),(_a1),(_a2))
958# define mkU64(_n) IRExpr_Const(IRConst_U64(_n))
sewardj9cc2bbf2011-06-05 17:56:03 +0000959# define mkU32(_n) IRExpr_Const(IRConst_U32(_n))
sewardj03540352005-04-26 01:53:48 +0000960# define mkU8(_n) IRExpr_Const(IRConst_U8(_n))
961
962 Int i, arity = 0;
963 for (i = 0; args[i]; i++)
964 arity++;
965# if 0
966 vex_printf("spec request:\n");
967 vex_printf(" %s ", function_name);
968 for (i = 0; i < arity; i++) {
969 vex_printf(" ");
970 ppIRExpr(args[i]);
971 }
972 vex_printf("\n");
973# endif
974
975 /* --------- specialising "amd64g_calculate_condition" --------- */
976
977 if (vex_streq(function_name, "amd64g_calculate_condition")) {
978 /* specialise calls to above "calculate condition" function */
979 IRExpr *cond, *cc_op, *cc_dep1, *cc_dep2;
980 vassert(arity == 5);
981 cond = args[0];
982 cc_op = args[1];
983 cc_dep1 = args[2];
984 cc_dep2 = args[3];
985
sewardjdb261e42005-05-11 23:16:43 +0000986 /*---------------- ADDQ ----------------*/
987
988 if (isU64(cc_op, AMD64G_CC_OP_ADDQ) && isU64(cond, AMD64CondZ)) {
989 /* long long add, then Z --> test (dst+src == 0) */
990 return unop(Iop_1Uto64,
991 binop(Iop_CmpEQ64,
992 binop(Iop_Add64, cc_dep1, cc_dep2),
993 mkU64(0)));
994 }
sewardj03540352005-04-26 01:53:48 +0000995
sewardjaedb8592014-10-02 16:15:30 +0000996 /*---------------- ADDL ----------------*/
997
998 if (isU64(cc_op, AMD64G_CC_OP_ADDL) && isU64(cond, AMD64CondO)) {
999 /* This is very commonly generated by Javascript JITs, for
1000 the idiom "do a 32-bit add and jump to out-of-line code if
1001 an overflow occurs". */
1002 /* long add, then O (overflow)
1003 --> ((dep1 ^ dep2 ^ -1) & (dep1 ^ (dep1 + dep2)))[31]
1004 --> (((dep1 ^ dep2 ^ -1) & (dep1 ^ (dep1 +64 dep2))) >>u 31) & 1
1005 --> (((not(dep1 ^ dep2)) & (dep1 ^ (dep1 +64 dep2))) >>u 31) & 1
1006 */
1007 vassert(isIRAtom(cc_dep1));
1008 vassert(isIRAtom(cc_dep2));
1009 return
1010 binop(Iop_And64,
1011 binop(Iop_Shr64,
1012 binop(Iop_And64,
1013 unop(Iop_Not64,
1014 binop(Iop_Xor64, cc_dep1, cc_dep2)),
1015 binop(Iop_Xor64,
1016 cc_dep1,
1017 binop(Iop_Add64, cc_dep1, cc_dep2))),
1018 mkU8(31)),
1019 mkU64(1));
1020
1021 }
1022
sewardj4b06a0b2005-11-13 19:51:04 +00001023 /*---------------- SUBQ ----------------*/
1024
sewardjaedb8592014-10-02 16:15:30 +00001025 /* 0, */
1026 if (isU64(cc_op, AMD64G_CC_OP_SUBQ) && isU64(cond, AMD64CondO)) {
1027 /* long long sub/cmp, then O (overflow)
1028 --> ((dep1 ^ dep2) & (dep1 ^ (dep1 - dep2)))[63]
1029 --> ((dep1 ^ dep2) & (dep1 ^ (dep1 - dep2))) >>u 63
1030 */
1031 vassert(isIRAtom(cc_dep1));
1032 vassert(isIRAtom(cc_dep2));
1033 return binop(Iop_Shr64,
1034 binop(Iop_And64,
1035 binop(Iop_Xor64, cc_dep1, cc_dep2),
1036 binop(Iop_Xor64,
1037 cc_dep1,
1038 binop(Iop_Sub64, cc_dep1, cc_dep2))),
1039 mkU8(64));
1040 }
1041 if (isU64(cc_op, AMD64G_CC_OP_SUBQ) && isU64(cond, AMD64CondNO)) {
1042 /* No action. Never yet found a test case. */
1043 }
1044
sewardjedccb442014-10-02 11:32:39 +00001045 /* 2, 3 */
sewardj4b06a0b2005-11-13 19:51:04 +00001046 if (isU64(cc_op, AMD64G_CC_OP_SUBQ) && isU64(cond, AMD64CondB)) {
1047 /* long long sub/cmp, then B (unsigned less than)
1048 --> test dst <u src */
1049 return unop(Iop_1Uto64,
1050 binop(Iop_CmpLT64U, cc_dep1, cc_dep2));
1051 }
sewardja9e4a802005-12-26 19:33:55 +00001052 if (isU64(cc_op, AMD64G_CC_OP_SUBQ) && isU64(cond, AMD64CondNB)) {
1053 /* long long sub/cmp, then NB (unsigned greater than or equal)
1054 --> test src <=u dst */
1055 /* Note, args are opposite way round from the usual */
1056 return unop(Iop_1Uto64,
1057 binop(Iop_CmpLE64U, cc_dep2, cc_dep1));
1058 }
1059
sewardjedccb442014-10-02 11:32:39 +00001060 /* 4, 5 */
1061 if (isU64(cc_op, AMD64G_CC_OP_SUBQ) && isU64(cond, AMD64CondZ)) {
1062 /* long long sub/cmp, then Z --> test dst==src */
sewardj3cfd1f02013-08-07 09:45:08 +00001063 return unop(Iop_1Uto64,
sewardjedccb442014-10-02 11:32:39 +00001064 binop(Iop_CmpEQ64,cc_dep1,cc_dep2));
1065 }
1066 if (isU64(cc_op, AMD64G_CC_OP_SUBQ) && isU64(cond, AMD64CondNZ)) {
1067 /* long long sub/cmp, then NZ --> test dst!=src */
1068 return unop(Iop_1Uto64,
1069 binop(Iop_CmpNE64,cc_dep1,cc_dep2));
sewardj3cfd1f02013-08-07 09:45:08 +00001070 }
1071
sewardjedccb442014-10-02 11:32:39 +00001072 /* 6, 7 */
sewardja9e4a802005-12-26 19:33:55 +00001073 if (isU64(cc_op, AMD64G_CC_OP_SUBQ) && isU64(cond, AMD64CondBE)) {
1074 /* long long sub/cmp, then BE (unsigned less than or equal)
1075 --> test dst <=u src */
1076 return unop(Iop_1Uto64,
1077 binop(Iop_CmpLE64U, cc_dep1, cc_dep2));
1078 }
sewardj3a05a152012-02-23 07:36:43 +00001079 if (isU64(cc_op, AMD64G_CC_OP_SUBQ) && isU64(cond, AMD64CondNBE)) {
1080 /* long long sub/cmp, then NBE (unsigned greater than)
1081 --> test !(dst <=u src) */
1082 return binop(Iop_Xor64,
1083 unop(Iop_1Uto64,
1084 binop(Iop_CmpLE64U, cc_dep1, cc_dep2)),
1085 mkU64(1));
1086 }
sewardja9e4a802005-12-26 19:33:55 +00001087
sewardjaedb8592014-10-02 16:15:30 +00001088 /* 8, 9 */
1089 if (isU64(cc_op, AMD64G_CC_OP_SUBQ) && isU64(cond, AMD64CondS)) {
1090 /* long long sub/cmp, then S (negative)
1091 --> (dst-src)[63]
1092 --> (dst-src) >>u 63 */
1093 return binop(Iop_Shr64,
1094 binop(Iop_Sub64, cc_dep1, cc_dep2),
1095 mkU8(63));
1096 }
1097 if (isU64(cc_op, AMD64G_CC_OP_SUBQ) && isU64(cond, AMD64CondNS)) {
1098 /* long long sub/cmp, then NS (not negative)
1099 --> (dst-src)[63] ^ 1
1100 --> ((dst-src) >>u 63) ^ 1 */
1101 return binop(Iop_Xor64,
1102 binop(Iop_Shr64,
1103 binop(Iop_Sub64, cc_dep1, cc_dep2),
1104 mkU8(63)),
1105 mkU64(1));
1106 }
1107
1108 /* 12, 13 */
sewardjedccb442014-10-02 11:32:39 +00001109 if (isU64(cc_op, AMD64G_CC_OP_SUBQ) && isU64(cond, AMD64CondL)) {
1110 /* long long sub/cmp, then L (signed less than)
1111 --> test dst <s src */
1112 return unop(Iop_1Uto64,
1113 binop(Iop_CmpLT64S, cc_dep1, cc_dep2));
1114 }
sewardjaedb8592014-10-02 16:15:30 +00001115 if (isU64(cc_op, AMD64G_CC_OP_SUBQ) && isU64(cond, AMD64CondNL)) {
1116 /* long long sub/cmp, then NL (signed greater than or equal)
1117 --> test dst >=s src
1118 --> test src <=s dst */
1119 return unop(Iop_1Uto64,
1120 binop(Iop_CmpLE64S, cc_dep2, cc_dep1));
1121 }
sewardjedccb442014-10-02 11:32:39 +00001122
sewardjaedb8592014-10-02 16:15:30 +00001123 /* 14, 15 */
1124 if (isU64(cc_op, AMD64G_CC_OP_SUBQ) && isU64(cond, AMD64CondLE)) {
1125 /* long long sub/cmp, then LE (signed less than or equal)
1126 --> test dst <=s src */
1127 return unop(Iop_1Uto64,
1128 binop(Iop_CmpLE64S, cc_dep1, cc_dep2));
1129 }
sewardjedccb442014-10-02 11:32:39 +00001130 if (isU64(cc_op, AMD64G_CC_OP_SUBQ) && isU64(cond, AMD64CondNLE)) {
1131 /* long sub/cmp, then NLE (signed greater than)
1132 --> test !(dst <=s src)
1133 --> test (dst >s src)
1134 --> test (src <s dst) */
1135 return unop(Iop_1Uto64,
1136 binop(Iop_CmpLT64S, cc_dep2, cc_dep1));
1137
1138 }
1139
sewardj03540352005-04-26 01:53:48 +00001140 /*---------------- SUBL ----------------*/
1141
sewardjaedb8592014-10-02 16:15:30 +00001142 /* 0, */
1143 if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondO)) {
1144 /* This is very commonly generated by Javascript JITs, for
1145 the idiom "do a 32-bit subtract and jump to out-of-line
1146 code if an overflow occurs". */
1147 /* long sub/cmp, then O (overflow)
1148 --> ((dep1 ^ dep2) & (dep1 ^ (dep1 - dep2)))[31]
1149 --> (((dep1 ^ dep2) & (dep1 ^ (dep1 -64 dep2))) >>u 31) & 1
1150 */
1151 vassert(isIRAtom(cc_dep1));
1152 vassert(isIRAtom(cc_dep2));
1153 return
1154 binop(Iop_And64,
1155 binop(Iop_Shr64,
1156 binop(Iop_And64,
1157 binop(Iop_Xor64, cc_dep1, cc_dep2),
1158 binop(Iop_Xor64,
1159 cc_dep1,
1160 binop(Iop_Sub64, cc_dep1, cc_dep2))),
1161 mkU8(31)),
1162 mkU64(1));
1163 }
1164 if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondNO)) {
1165 /* No action. Never yet found a test case. */
1166 }
1167
1168 /* 2, 3 */
sewardjedccb442014-10-02 11:32:39 +00001169 if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondB)) {
1170 /* long sub/cmp, then B (unsigned less than)
1171 --> test dst <u src */
1172 return unop(Iop_1Uto64,
1173 binop(Iop_CmpLT32U,
1174 unop(Iop_64to32, cc_dep1),
1175 unop(Iop_64to32, cc_dep2)));
1176 }
sewardjaedb8592014-10-02 16:15:30 +00001177 if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondNB)) {
1178 /* long sub/cmp, then NB (unsigned greater than or equal)
1179 --> test src <=u dst */
1180 /* Note, args are opposite way round from the usual */
1181 return unop(Iop_1Uto64,
1182 binop(Iop_CmpLE32U,
1183 unop(Iop_64to32, cc_dep2),
1184 unop(Iop_64to32, cc_dep1)));
1185 }
sewardjedccb442014-10-02 11:32:39 +00001186
1187 /* 4, 5 */
sewardjdb261e42005-05-11 23:16:43 +00001188 if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondZ)) {
1189 /* long sub/cmp, then Z --> test dst==src */
1190 return unop(Iop_1Uto64,
sewardj9cc2bbf2011-06-05 17:56:03 +00001191 binop(Iop_CmpEQ32,
1192 unop(Iop_64to32, cc_dep1),
1193 unop(Iop_64to32, cc_dep2)));
sewardja9e4a802005-12-26 19:33:55 +00001194 }
sewardja9e4a802005-12-26 19:33:55 +00001195 if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondNZ)) {
1196 /* long sub/cmp, then NZ --> test dst!=src */
1197 return unop(Iop_1Uto64,
sewardj9cc2bbf2011-06-05 17:56:03 +00001198 binop(Iop_CmpNE32,
1199 unop(Iop_64to32, cc_dep1),
1200 unop(Iop_64to32, cc_dep2)));
sewardjdb261e42005-05-11 23:16:43 +00001201 }
1202
sewardjedccb442014-10-02 11:32:39 +00001203 /* 6, 7 */
1204 if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondBE)) {
1205 /* long sub/cmp, then BE (unsigned less than or equal)
1206 --> test dst <=u src */
1207 return unop(Iop_1Uto64,
1208 binop(Iop_CmpLE32U,
1209 unop(Iop_64to32, cc_dep1),
1210 unop(Iop_64to32, cc_dep2)));
1211 }
1212 if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondNBE)) {
1213 /* long sub/cmp, then NBE (unsigned greater than)
1214 --> test src <u dst */
1215 /* Note, args are opposite way round from the usual */
1216 return unop(Iop_1Uto64,
1217 binop(Iop_CmpLT32U,
1218 unop(Iop_64to32, cc_dep2),
1219 unop(Iop_64to32, cc_dep1)));
1220 }
1221
sewardjaedb8592014-10-02 16:15:30 +00001222 /* 8, 9 */
sewardjedccb442014-10-02 11:32:39 +00001223 if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondS)) {
sewardjaedb8592014-10-02 16:15:30 +00001224 /* long sub/cmp, then S (negative)
1225 --> (dst-src)[31]
1226 --> ((dst -64 src) >>u 31) & 1
1227 Pointless to narrow the args to 32 bit before the subtract. */
1228 return binop(Iop_And64,
1229 binop(Iop_Shr64,
1230 binop(Iop_Sub64, cc_dep1, cc_dep2),
1231 mkU8(31)),
1232 mkU64(1));
1233 }
1234 if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondNS)) {
1235 /* long sub/cmp, then NS (not negative)
1236 --> (dst-src)[31] ^ 1
1237 --> (((dst -64 src) >>u 31) & 1) ^ 1
1238 Pointless to narrow the args to 32 bit before the subtract. */
1239 return binop(Iop_Xor64,
1240 binop(Iop_And64,
1241 binop(Iop_Shr64,
1242 binop(Iop_Sub64, cc_dep1, cc_dep2),
1243 mkU8(31)),
1244 mkU64(1)),
1245 mkU64(1));
sewardjedccb442014-10-02 11:32:39 +00001246 }
1247
sewardjaedb8592014-10-02 16:15:30 +00001248 /* 12, 13 */
sewardj03540352005-04-26 01:53:48 +00001249 if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondL)) {
1250 /* long sub/cmp, then L (signed less than)
1251 --> test dst <s src */
sewardj6d709a92005-04-27 11:52:40 +00001252 return unop(Iop_1Uto64,
sewardj9cc2bbf2011-06-05 17:56:03 +00001253 binop(Iop_CmpLT32S,
1254 unop(Iop_64to32, cc_dep1),
1255 unop(Iop_64to32, cc_dep2)));
sewardj03540352005-04-26 01:53:48 +00001256 }
sewardjaedb8592014-10-02 16:15:30 +00001257 if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondNL)) {
1258 /* long sub/cmp, then NL (signed greater than or equal)
1259 --> test dst >=s src
1260 --> test src <=s dst */
1261 return unop(Iop_1Uto64,
1262 binop(Iop_CmpLE32S,
1263 unop(Iop_64to32, cc_dep2),
1264 unop(Iop_64to32, cc_dep1)));
1265 }
sewardj03540352005-04-26 01:53:48 +00001266
sewardjedccb442014-10-02 11:32:39 +00001267 /* 14, 15 */
sewardj03540352005-04-26 01:53:48 +00001268 if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondLE)) {
sewardj3f81c4e2005-07-20 00:30:37 +00001269 /* long sub/cmp, then LE (signed less than or equal)
1270 --> test dst <=s src */
sewardj6d709a92005-04-27 11:52:40 +00001271 return unop(Iop_1Uto64,
sewardj9cc2bbf2011-06-05 17:56:03 +00001272 binop(Iop_CmpLE32S,
1273 unop(Iop_64to32, cc_dep1),
1274 unop(Iop_64to32, cc_dep2)));
sewardj03540352005-04-26 01:53:48 +00001275
1276 }
sewardjff6b34a2010-01-15 09:54:55 +00001277 if (isU64(cc_op, AMD64G_CC_OP_SUBL) && isU64(cond, AMD64CondNLE)) {
1278 /* long sub/cmp, then NLE (signed greater than)
1279 --> test !(dst <=s src)
1280 --> test (dst >s src)
1281 --> test (src <s dst) */
1282 return unop(Iop_1Uto64,
sewardj9cc2bbf2011-06-05 17:56:03 +00001283 binop(Iop_CmpLT32S,
1284 unop(Iop_64to32, cc_dep2),
1285 unop(Iop_64to32, cc_dep1)));
sewardjff6b34a2010-01-15 09:54:55 +00001286
1287 }
sewardj03540352005-04-26 01:53:48 +00001288
sewardj03540352005-04-26 01:53:48 +00001289 /*---------------- SUBW ----------------*/
1290
sewardja82b4762005-05-06 16:30:21 +00001291 if (isU64(cc_op, AMD64G_CC_OP_SUBW) && isU64(cond, AMD64CondZ)) {
1292 /* word sub/cmp, then Z --> test dst==src */
1293 return unop(Iop_1Uto64,
1294 binop(Iop_CmpEQ16,
1295 unop(Iop_64to16,cc_dep1),
1296 unop(Iop_64to16,cc_dep2)));
1297 }
sewardjbeb52912008-05-02 22:15:12 +00001298 if (isU64(cc_op, AMD64G_CC_OP_SUBW) && isU64(cond, AMD64CondNZ)) {
1299 /* word sub/cmp, then NZ --> test dst!=src */
1300 return unop(Iop_1Uto64,
1301 binop(Iop_CmpNE16,
1302 unop(Iop_64to16,cc_dep1),
1303 unop(Iop_64to16,cc_dep2)));
1304 }
sewardj03540352005-04-26 01:53:48 +00001305
sewardjaedb8592014-10-02 16:15:30 +00001306 if (isU64(cc_op, AMD64G_CC_OP_SUBW) && isU64(cond, AMD64CondBE)) {
1307 /* word sub/cmp, then BE (unsigned less than or equal)
1308 --> test dst <=u src */
1309 return unop(Iop_1Uto64,
1310 binop(Iop_CmpLE64U,
1311 binop(Iop_Shl64, cc_dep1, mkU8(48)),
1312 binop(Iop_Shl64, cc_dep2, mkU8(48))));
1313 }
1314
sewardj3f81c4e2005-07-20 00:30:37 +00001315 if (isU64(cc_op, AMD64G_CC_OP_SUBW) && isU64(cond, AMD64CondLE)) {
sewardj3be608d2006-05-25 18:48:12 +00001316 /* word sub/cmp, then LE (signed less than or equal)
sewardj3f81c4e2005-07-20 00:30:37 +00001317 --> test dst <=s src */
1318 return unop(Iop_1Uto64,
1319 binop(Iop_CmpLE64S,
1320 binop(Iop_Shl64,cc_dep1,mkU8(48)),
1321 binop(Iop_Shl64,cc_dep2,mkU8(48))));
1322
1323 }
1324
sewardj03540352005-04-26 01:53:48 +00001325 /*---------------- SUBB ----------------*/
1326
1327 if (isU64(cc_op, AMD64G_CC_OP_SUBB) && isU64(cond, AMD64CondZ)) {
1328 /* byte sub/cmp, then Z --> test dst==src */
sewardj6d709a92005-04-27 11:52:40 +00001329 return unop(Iop_1Uto64,
sewardj03540352005-04-26 01:53:48 +00001330 binop(Iop_CmpEQ8,
sewardj6d709a92005-04-27 11:52:40 +00001331 unop(Iop_64to8,cc_dep1),
1332 unop(Iop_64to8,cc_dep2)));
sewardj03540352005-04-26 01:53:48 +00001333 }
sewardj32d615b2006-08-25 12:52:19 +00001334 if (isU64(cc_op, AMD64G_CC_OP_SUBB) && isU64(cond, AMD64CondNZ)) {
1335 /* byte sub/cmp, then NZ --> test dst!=src */
1336 return unop(Iop_1Uto64,
1337 binop(Iop_CmpNE8,
1338 unop(Iop_64to8,cc_dep1),
1339 unop(Iop_64to8,cc_dep2)));
1340 }
1341
sewardje4304182011-06-06 10:17:46 +00001342 if (isU64(cc_op, AMD64G_CC_OP_SUBB) && isU64(cond, AMD64CondBE)) {
1343 /* byte sub/cmp, then BE (unsigned less than or equal)
1344 --> test dst <=u src */
1345 return unop(Iop_1Uto64,
1346 binop(Iop_CmpLE64U,
1347 binop(Iop_And64, cc_dep1, mkU64(0xFF)),
1348 binop(Iop_And64, cc_dep2, mkU64(0xFF))));
1349 }
1350
sewardj3be608d2006-05-25 18:48:12 +00001351 if (isU64(cc_op, AMD64G_CC_OP_SUBB) && isU64(cond, AMD64CondS)
1352 && isU64(cc_dep2, 0)) {
1353 /* byte sub/cmp of zero, then S --> test (dst-0 <s 0)
1354 --> test dst <s 0
1355 --> (ULong)dst[7]
1356 This is yet another scheme by which gcc figures out if the
1357 top bit of a byte is 1 or 0. See also LOGICB/CondS below. */
1358 /* Note: isU64(cc_dep2, 0) is correct, even though this is
1359 for an 8-bit comparison, since the args to the helper
1360 function are always U64s. */
1361 return binop(Iop_And64,
1362 binop(Iop_Shr64,cc_dep1,mkU8(7)),
1363 mkU64(1));
1364 }
sewardjcd538b42008-03-31 21:57:17 +00001365 if (isU64(cc_op, AMD64G_CC_OP_SUBB) && isU64(cond, AMD64CondNS)
1366 && isU64(cc_dep2, 0)) {
1367 /* byte sub/cmp of zero, then NS --> test !(dst-0 <s 0)
1368 --> test !(dst <s 0)
1369 --> (ULong) !dst[7]
1370 */
1371 return binop(Iop_Xor64,
1372 binop(Iop_And64,
1373 binop(Iop_Shr64,cc_dep1,mkU8(7)),
1374 mkU64(1)),
1375 mkU64(1));
1376 }
sewardj3be608d2006-05-25 18:48:12 +00001377
sewardj4b06a0b2005-11-13 19:51:04 +00001378 /*---------------- LOGICQ ----------------*/
1379
1380 if (isU64(cc_op, AMD64G_CC_OP_LOGICQ) && isU64(cond, AMD64CondZ)) {
1381 /* long long and/or/xor, then Z --> test dst==0 */
1382 return unop(Iop_1Uto64,
1383 binop(Iop_CmpEQ64, cc_dep1, mkU64(0)));
1384 }
sewardj0cd74732011-07-07 13:58:10 +00001385 if (isU64(cc_op, AMD64G_CC_OP_LOGICQ) && isU64(cond, AMD64CondNZ)) {
1386 /* long long and/or/xor, then NZ --> test dst!=0 */
1387 return unop(Iop_1Uto64,
1388 binop(Iop_CmpNE64, cc_dep1, mkU64(0)));
1389 }
sewardj4b06a0b2005-11-13 19:51:04 +00001390
sewardj77fd8462005-11-13 20:30:24 +00001391 if (isU64(cc_op, AMD64G_CC_OP_LOGICQ) && isU64(cond, AMD64CondL)) {
1392 /* long long and/or/xor, then L
1393 LOGIC sets SF and ZF according to the
1394 result and makes OF be zero. L computes SF ^ OF, but
1395 OF is zero, so this reduces to SF -- which will be 1 iff
1396 the result is < signed 0. Hence ...
1397 */
1398 return unop(Iop_1Uto64,
1399 binop(Iop_CmpLT64S,
1400 cc_dep1,
1401 mkU64(0)));
1402 }
1403
sewardj03540352005-04-26 01:53:48 +00001404 /*---------------- LOGICL ----------------*/
1405
1406 if (isU64(cc_op, AMD64G_CC_OP_LOGICL) && isU64(cond, AMD64CondZ)) {
1407 /* long and/or/xor, then Z --> test dst==0 */
sewardj6d709a92005-04-27 11:52:40 +00001408 return unop(Iop_1Uto64,
sewardj9cc2bbf2011-06-05 17:56:03 +00001409 binop(Iop_CmpEQ32,
1410 unop(Iop_64to32, cc_dep1),
1411 mkU32(0)));
sewardj03540352005-04-26 01:53:48 +00001412 }
sewardj005b4ef2005-07-20 01:12:48 +00001413 if (isU64(cc_op, AMD64G_CC_OP_LOGICL) && isU64(cond, AMD64CondNZ)) {
1414 /* long and/or/xor, then NZ --> test dst!=0 */
1415 return unop(Iop_1Uto64,
sewardj9cc2bbf2011-06-05 17:56:03 +00001416 binop(Iop_CmpNE32,
1417 unop(Iop_64to32, cc_dep1),
1418 mkU32(0)));
sewardj005b4ef2005-07-20 01:12:48 +00001419 }
1420
sewardj03540352005-04-26 01:53:48 +00001421 if (isU64(cc_op, AMD64G_CC_OP_LOGICL) && isU64(cond, AMD64CondLE)) {
1422 /* long and/or/xor, then LE
1423 This is pretty subtle. LOGIC sets SF and ZF according to the
sewardj77fd8462005-11-13 20:30:24 +00001424 result and makes OF be zero. LE computes (SF ^ OF) | ZF, but
1425 OF is zero, so this reduces to SF | ZF -- which will be 1 iff
sewardj03540352005-04-26 01:53:48 +00001426 the result is <=signed 0. Hence ...
1427 */
sewardj6d709a92005-04-27 11:52:40 +00001428 return unop(Iop_1Uto64,
sewardj9cc2bbf2011-06-05 17:56:03 +00001429 binop(Iop_CmpLE32S,
1430 unop(Iop_64to32, cc_dep1),
1431 mkU32(0)));
sewardj03540352005-04-26 01:53:48 +00001432 }
1433
sewardje4304182011-06-06 10:17:46 +00001434 if (isU64(cc_op, AMD64G_CC_OP_LOGICL) && isU64(cond, AMD64CondS)) {
1435 /* long and/or/xor, then S --> (ULong)result[31] */
1436 return binop(Iop_And64,
1437 binop(Iop_Shr64, cc_dep1, mkU8(31)),
1438 mkU64(1));
1439 }
1440 if (isU64(cc_op, AMD64G_CC_OP_LOGICL) && isU64(cond, AMD64CondNS)) {
1441 /* long and/or/xor, then S --> (ULong) ~ result[31] */
1442 return binop(Iop_Xor64,
1443 binop(Iop_And64,
1444 binop(Iop_Shr64, cc_dep1, mkU8(31)),
1445 mkU64(1)),
1446 mkU64(1));
1447 }
1448
sewardj61acf4c2012-04-25 14:33:03 +00001449 /*---------------- LOGICW ----------------*/
1450
1451 if (isU64(cc_op, AMD64G_CC_OP_LOGICW) && isU64(cond, AMD64CondZ)) {
1452 /* word and/or/xor, then Z --> test dst==0 */
1453 return unop(Iop_1Uto64,
1454 binop(Iop_CmpEQ64,
1455 binop(Iop_And64, cc_dep1, mkU64(0xFFFF)),
1456 mkU64(0)));
1457 }
1458 if (isU64(cc_op, AMD64G_CC_OP_LOGICW) && isU64(cond, AMD64CondNZ)) {
1459 /* word and/or/xor, then NZ --> test dst!=0 */
1460 return unop(Iop_1Uto64,
1461 binop(Iop_CmpNE64,
1462 binop(Iop_And64, cc_dep1, mkU64(0xFFFF)),
1463 mkU64(0)));
1464 }
1465
sewardj4b06a0b2005-11-13 19:51:04 +00001466 /*---------------- LOGICB ----------------*/
1467
1468 if (isU64(cc_op, AMD64G_CC_OP_LOGICB) && isU64(cond, AMD64CondZ)) {
1469 /* byte and/or/xor, then Z --> test dst==0 */
1470 return unop(Iop_1Uto64,
1471 binop(Iop_CmpEQ64, binop(Iop_And64,cc_dep1,mkU64(255)),
1472 mkU64(0)));
1473 }
sewardjff6b34a2010-01-15 09:54:55 +00001474 if (isU64(cc_op, AMD64G_CC_OP_LOGICB) && isU64(cond, AMD64CondNZ)) {
1475 /* byte and/or/xor, then NZ --> test dst!=0 */
1476 return unop(Iop_1Uto64,
1477 binop(Iop_CmpNE64, binop(Iop_And64,cc_dep1,mkU64(255)),
1478 mkU64(0)));
1479 }
sewardj3f81c4e2005-07-20 00:30:37 +00001480
sewardj346d9a12006-05-21 01:02:31 +00001481 if (isU64(cc_op, AMD64G_CC_OP_LOGICB) && isU64(cond, AMD64CondS)) {
1482 /* this is an idiom gcc sometimes uses to find out if the top
1483 bit of a byte register is set: eg testb %al,%al; js ..
1484 Since it just depends on the top bit of the byte, extract
1485 that bit and explicitly get rid of all the rest. This
1486 helps memcheck avoid false positives in the case where any
1487 of the other bits in the byte are undefined. */
1488 /* byte and/or/xor, then S --> (UInt)result[7] */
1489 return binop(Iop_And64,
1490 binop(Iop_Shr64,cc_dep1,mkU8(7)),
1491 mkU64(1));
1492 }
sewardja6d08092011-03-27 22:16:08 +00001493 if (isU64(cc_op, AMD64G_CC_OP_LOGICB) && isU64(cond, AMD64CondNS)) {
1494 /* byte and/or/xor, then NS --> (UInt)!result[7] */
1495 return binop(Iop_Xor64,
1496 binop(Iop_And64,
1497 binop(Iop_Shr64,cc_dep1,mkU8(7)),
1498 mkU64(1)),
1499 mkU64(1));
1500 }
sewardj346d9a12006-05-21 01:02:31 +00001501
sewardj3f81c4e2005-07-20 00:30:37 +00001502 /*---------------- INCB ----------------*/
1503
1504 if (isU64(cc_op, AMD64G_CC_OP_INCB) && isU64(cond, AMD64CondLE)) {
sewardj4df975f2010-02-28 04:51:02 +00001505 /* 8-bit inc, then LE --> sign bit of the arg */
1506 return binop(Iop_And64,
1507 binop(Iop_Shr64,
1508 binop(Iop_Sub64, cc_dep1, mkU64(1)),
1509 mkU8(7)),
1510 mkU64(1));
sewardj3f81c4e2005-07-20 00:30:37 +00001511 }
1512
sewardj7784bd22006-12-29 01:54:36 +00001513 /*---------------- INCW ----------------*/
1514
1515 if (isU64(cc_op, AMD64G_CC_OP_INCW) && isU64(cond, AMD64CondZ)) {
1516 /* 16-bit inc, then Z --> test dst == 0 */
1517 return unop(Iop_1Uto64,
1518 binop(Iop_CmpEQ64,
1519 binop(Iop_Shl64,cc_dep1,mkU8(48)),
1520 mkU64(0)));
1521 }
1522
sewardj77fd8462005-11-13 20:30:24 +00001523 /*---------------- DECL ----------------*/
1524
1525 if (isU64(cc_op, AMD64G_CC_OP_DECL) && isU64(cond, AMD64CondZ)) {
1526 /* dec L, then Z --> test dst == 0 */
1527 return unop(Iop_1Uto64,
sewardj9cc2bbf2011-06-05 17:56:03 +00001528 binop(Iop_CmpEQ32,
1529 unop(Iop_64to32, cc_dep1),
1530 mkU32(0)));
sewardj77fd8462005-11-13 20:30:24 +00001531 }
1532
sewardjb6d02ea2005-08-01 13:35:18 +00001533 /*---------------- DECW ----------------*/
1534
1535 if (isU64(cc_op, AMD64G_CC_OP_DECW) && isU64(cond, AMD64CondNZ)) {
1536 /* 16-bit dec, then NZ --> test dst != 0 */
1537 return unop(Iop_1Uto64,
1538 binop(Iop_CmpNE64,
1539 binop(Iop_Shl64,cc_dep1,mkU8(48)),
1540 mkU64(0)));
1541 }
1542
sewardj7fc494b2005-05-05 12:05:11 +00001543 /*---------------- COPY ----------------*/
1544 /* This can happen, as a result of amd64 FP compares: "comisd ... ;
1545 jbe" for example. */
1546
1547 if (isU64(cc_op, AMD64G_CC_OP_COPY) &&
1548 (isU64(cond, AMD64CondBE) || isU64(cond, AMD64CondNBE))) {
1549 /* COPY, then BE --> extract C and Z from dep1, and test (C
1550 or Z == 1). */
1551 /* COPY, then NBE --> extract C and Z from dep1, and test (C
1552 or Z == 0). */
1553 ULong nnn = isU64(cond, AMD64CondBE) ? 1 : 0;
1554 return
1555 unop(
1556 Iop_1Uto64,
1557 binop(
1558 Iop_CmpEQ64,
1559 binop(
1560 Iop_And64,
1561 binop(
1562 Iop_Or64,
1563 binop(Iop_Shr64, cc_dep1, mkU8(AMD64G_CC_SHIFT_C)),
1564 binop(Iop_Shr64, cc_dep1, mkU8(AMD64G_CC_SHIFT_Z))
1565 ),
1566 mkU64(1)
1567 ),
1568 mkU64(nnn)
1569 )
1570 );
1571 }
1572
sewardj9f05a642005-05-12 02:14:52 +00001573 if (isU64(cc_op, AMD64G_CC_OP_COPY) && isU64(cond, AMD64CondB)) {
1574 /* COPY, then B --> extract C dep1, and test (C == 1). */
1575 return
1576 unop(
1577 Iop_1Uto64,
1578 binop(
1579 Iop_CmpNE64,
1580 binop(
1581 Iop_And64,
1582 binop(Iop_Shr64, cc_dep1, mkU8(AMD64G_CC_SHIFT_C)),
1583 mkU64(1)
1584 ),
1585 mkU64(0)
1586 )
1587 );
1588 }
sewardj03540352005-04-26 01:53:48 +00001589
sewardjb235e5b2006-11-27 04:09:52 +00001590 if (isU64(cc_op, AMD64G_CC_OP_COPY)
1591 && (isU64(cond, AMD64CondZ) || isU64(cond, AMD64CondNZ))) {
1592 /* COPY, then Z --> extract Z from dep1, and test (Z == 1). */
1593 /* COPY, then NZ --> extract Z from dep1, and test (Z == 0). */
1594 UInt nnn = isU64(cond, AMD64CondZ) ? 1 : 0;
1595 return
1596 unop(
1597 Iop_1Uto64,
1598 binop(
1599 Iop_CmpEQ64,
1600 binop(
1601 Iop_And64,
1602 binop(Iop_Shr64, cc_dep1, mkU8(AMD64G_CC_SHIFT_Z)),
1603 mkU64(1)
1604 ),
1605 mkU64(nnn)
1606 )
1607 );
1608 }
1609
1610 if (isU64(cc_op, AMD64G_CC_OP_COPY) && isU64(cond, AMD64CondP)) {
1611 /* COPY, then P --> extract P from dep1, and test (P == 1). */
1612 return
1613 unop(
1614 Iop_1Uto64,
1615 binop(
1616 Iop_CmpNE64,
1617 binop(
1618 Iop_And64,
1619 binop(Iop_Shr64, cc_dep1, mkU8(AMD64G_CC_SHIFT_P)),
1620 mkU64(1)
1621 ),
1622 mkU64(0)
1623 )
1624 );
1625 }
1626
sewardj03540352005-04-26 01:53:48 +00001627 return NULL;
1628 }
1629
1630 /* --------- specialising "amd64g_calculate_rflags_c" --------- */
1631
1632 if (vex_streq(function_name, "amd64g_calculate_rflags_c")) {
1633 /* specialise calls to above "calculate_rflags_c" function */
1634 IRExpr *cc_op, *cc_dep1, *cc_dep2, *cc_ndep;
1635 vassert(arity == 4);
1636 cc_op = args[0];
1637 cc_dep1 = args[1];
1638 cc_dep2 = args[2];
1639 cc_ndep = args[3];
1640
sewardj77fd8462005-11-13 20:30:24 +00001641 if (isU64(cc_op, AMD64G_CC_OP_SUBQ)) {
1642 /* C after sub denotes unsigned less than */
1643 return unop(Iop_1Uto64,
1644 binop(Iop_CmpLT64U,
1645 cc_dep1,
1646 cc_dep2));
1647 }
sewardj03540352005-04-26 01:53:48 +00001648 if (isU64(cc_op, AMD64G_CC_OP_SUBL)) {
1649 /* C after sub denotes unsigned less than */
sewardj6d709a92005-04-27 11:52:40 +00001650 return unop(Iop_1Uto64,
sewardj9cc2bbf2011-06-05 17:56:03 +00001651 binop(Iop_CmpLT32U,
1652 unop(Iop_64to32, cc_dep1),
1653 unop(Iop_64to32, cc_dep2)));
sewardj03540352005-04-26 01:53:48 +00001654 }
1655 if (isU64(cc_op, AMD64G_CC_OP_SUBB)) {
1656 /* C after sub denotes unsigned less than */
sewardj6d709a92005-04-27 11:52:40 +00001657 return unop(Iop_1Uto64,
sewardj03540352005-04-26 01:53:48 +00001658 binop(Iop_CmpLT64U,
1659 binop(Iop_And64,cc_dep1,mkU64(0xFF)),
sewardj6d709a92005-04-27 11:52:40 +00001660 binop(Iop_And64,cc_dep2,mkU64(0xFF))));
sewardj03540352005-04-26 01:53:48 +00001661 }
1662 if (isU64(cc_op, AMD64G_CC_OP_LOGICQ)
1663 || isU64(cc_op, AMD64G_CC_OP_LOGICL)
1664 || isU64(cc_op, AMD64G_CC_OP_LOGICW)
1665 || isU64(cc_op, AMD64G_CC_OP_LOGICB)) {
1666 /* cflag after logic is zero */
1667 return mkU64(0);
1668 }
1669 if (isU64(cc_op, AMD64G_CC_OP_DECL) || isU64(cc_op, AMD64G_CC_OP_INCL)
1670 || isU64(cc_op, AMD64G_CC_OP_DECQ) || isU64(cc_op, AMD64G_CC_OP_INCQ)) {
1671 /* If the thunk is dec or inc, the cflag is supplied as CC_NDEP. */
1672 return cc_ndep;
1673 }
sewardj7784bd22006-12-29 01:54:36 +00001674
1675# if 0
1676 if (cc_op->tag == Iex_Const) {
1677 vex_printf("CFLAG "); ppIRExpr(cc_op); vex_printf("\n");
1678 }
1679# endif
sewardj03540352005-04-26 01:53:48 +00001680
1681 return NULL;
1682 }
1683
sewardjf8c37f72005-02-07 18:55:29 +00001684# undef unop
1685# undef binop
sewardj03540352005-04-26 01:53:48 +00001686# undef mkU64
sewardj9cc2bbf2011-06-05 17:56:03 +00001687# undef mkU32
sewardjf8c37f72005-02-07 18:55:29 +00001688# undef mkU8
1689
1690 return NULL;
sewardj44d494d2005-01-20 20:26:33 +00001691}
1692
sewardjf8c37f72005-02-07 18:55:29 +00001693
sewardj8d965312005-02-25 02:48:47 +00001694/*---------------------------------------------------------------*/
1695/*--- Supporting functions for x87 FPU activities. ---*/
1696/*---------------------------------------------------------------*/
1697
sewardj4f9847d2005-07-25 11:58:34 +00001698static inline Bool host_is_little_endian ( void )
1699{
1700 UInt x = 0x76543210;
1701 UChar* p = (UChar*)(&x);
1702 return toBool(*p == 0x10);
1703}
1704
1705/* Inspect a value and its tag, as per the x87 'FXAM' instruction. */
1706/* CALLED FROM GENERATED CODE: CLEAN HELPER */
1707ULong amd64g_calculate_FXAM ( ULong tag, ULong dbl )
1708{
1709 Bool mantissaIsZero;
1710 Int bexp;
1711 UChar sign;
1712 UChar* f64;
1713
1714 vassert(host_is_little_endian());
1715
1716 /* vex_printf("calculate_FXAM ( %d, %llx ) .. ", tag, dbl ); */
1717
1718 f64 = (UChar*)(&dbl);
1719 sign = toUChar( (f64[7] >> 7) & 1 );
1720
1721 /* First off, if the tag indicates the register was empty,
1722 return 1,0,sign,1 */
1723 if (tag == 0) {
1724 /* vex_printf("Empty\n"); */
1725 return AMD64G_FC_MASK_C3 | 0 | (sign << AMD64G_FC_SHIFT_C1)
1726 | AMD64G_FC_MASK_C0;
1727 }
1728
1729 bexp = (f64[7] << 4) | ((f64[6] >> 4) & 0x0F);
1730 bexp &= 0x7FF;
1731
1732 mantissaIsZero
1733 = toBool(
1734 (f64[6] & 0x0F) == 0
1735 && (f64[5] | f64[4] | f64[3] | f64[2] | f64[1] | f64[0]) == 0
1736 );
1737
1738 /* If both exponent and mantissa are zero, the value is zero.
1739 Return 1,0,sign,0. */
1740 if (bexp == 0 && mantissaIsZero) {
1741 /* vex_printf("Zero\n"); */
1742 return AMD64G_FC_MASK_C3 | 0
1743 | (sign << AMD64G_FC_SHIFT_C1) | 0;
1744 }
1745
1746 /* If exponent is zero but mantissa isn't, it's a denormal.
1747 Return 1,1,sign,0. */
1748 if (bexp == 0 && !mantissaIsZero) {
1749 /* vex_printf("Denormal\n"); */
1750 return AMD64G_FC_MASK_C3 | AMD64G_FC_MASK_C2
1751 | (sign << AMD64G_FC_SHIFT_C1) | 0;
1752 }
1753
1754 /* If the exponent is 7FF and the mantissa is zero, this is an infinity.
1755 Return 0,1,sign,1. */
1756 if (bexp == 0x7FF && mantissaIsZero) {
1757 /* vex_printf("Inf\n"); */
1758 return 0 | AMD64G_FC_MASK_C2 | (sign << AMD64G_FC_SHIFT_C1)
1759 | AMD64G_FC_MASK_C0;
1760 }
1761
1762 /* If the exponent is 7FF and the mantissa isn't zero, this is a NaN.
1763 Return 0,0,sign,1. */
1764 if (bexp == 0x7FF && !mantissaIsZero) {
1765 /* vex_printf("NaN\n"); */
1766 return 0 | 0 | (sign << AMD64G_FC_SHIFT_C1) | AMD64G_FC_MASK_C0;
1767 }
1768
1769 /* Uh, ok, we give up. It must be a normal finite number.
1770 Return 0,1,sign,0.
1771 */
1772 /* vex_printf("normal\n"); */
1773 return 0 | AMD64G_FC_MASK_C2 | (sign << AMD64G_FC_SHIFT_C1) | 0;
1774}
1775
1776
sewardj5556e5e2011-01-21 18:05:19 +00001777/* This is used to implement both 'frstor' and 'fldenv'. The latter
1778 appears to differ from the former only in that the 8 FP registers
1779 themselves are not transferred into the guest state. */
1780static
florian6ef84be2012-08-26 03:20:07 +00001781VexEmNote do_put_x87 ( Bool moveRegs,
sewardj5556e5e2011-01-21 18:05:19 +00001782 /*IN*/UChar* x87_state,
1783 /*OUT*/VexGuestAMD64State* vex_state )
1784{
1785 Int stno, preg;
1786 UInt tag;
1787 ULong* vexRegs = (ULong*)(&vex_state->guest_FPREG[0]);
1788 UChar* vexTags = (UChar*)(&vex_state->guest_FPTAG[0]);
1789 Fpu_State* x87 = (Fpu_State*)x87_state;
1790 UInt ftop = (x87->env[FP_ENV_STAT] >> 11) & 7;
1791 UInt tagw = x87->env[FP_ENV_TAG];
1792 UInt fpucw = x87->env[FP_ENV_CTRL];
1793 UInt c3210 = x87->env[FP_ENV_STAT] & 0x4700;
florian6ef84be2012-08-26 03:20:07 +00001794 VexEmNote ew;
sewardj5556e5e2011-01-21 18:05:19 +00001795 UInt fpround;
1796 ULong pair;
1797
1798 /* Copy registers and tags */
1799 for (stno = 0; stno < 8; stno++) {
1800 preg = (stno + ftop) & 7;
1801 tag = (tagw >> (2*preg)) & 3;
1802 if (tag == 3) {
1803 /* register is empty */
1804 /* hmm, if it's empty, does it still get written? Probably
1805 safer to say it does. If we don't, memcheck could get out
1806 of sync, in that it thinks all FP registers are defined by
1807 this helper, but in reality some have not been updated. */
1808 if (moveRegs)
1809 vexRegs[preg] = 0; /* IEEE754 64-bit zero */
1810 vexTags[preg] = 0;
1811 } else {
1812 /* register is non-empty */
1813 if (moveRegs)
1814 convert_f80le_to_f64le( &x87->reg[10*stno],
1815 (UChar*)&vexRegs[preg] );
1816 vexTags[preg] = 1;
1817 }
1818 }
1819
1820 /* stack pointer */
1821 vex_state->guest_FTOP = ftop;
1822
1823 /* status word */
1824 vex_state->guest_FC3210 = c3210;
1825
1826 /* handle the control word, setting FPROUND and detecting any
1827 emulation warnings. */
1828 pair = amd64g_check_fldcw ( (ULong)fpucw );
sewardj9ae42a72012-02-16 14:18:56 +00001829 fpround = (UInt)pair & 0xFFFFFFFFULL;
florian6ef84be2012-08-26 03:20:07 +00001830 ew = (VexEmNote)(pair >> 32);
sewardj5556e5e2011-01-21 18:05:19 +00001831
1832 vex_state->guest_FPROUND = fpround & 3;
1833
1834 /* emulation warnings --> caller */
1835 return ew;
1836}
1837
1838
sewardj5abcfe62007-01-10 04:59:33 +00001839/* Create an x87 FPU state from the guest state, as close as
1840 we can approximate it. */
1841static
1842void do_get_x87 ( /*IN*/VexGuestAMD64State* vex_state,
1843 /*OUT*/UChar* x87_state )
1844{
1845 Int i, stno, preg;
1846 UInt tagw;
1847 ULong* vexRegs = (ULong*)(&vex_state->guest_FPREG[0]);
1848 UChar* vexTags = (UChar*)(&vex_state->guest_FPTAG[0]);
1849 Fpu_State* x87 = (Fpu_State*)x87_state;
1850 UInt ftop = vex_state->guest_FTOP;
1851 UInt c3210 = vex_state->guest_FC3210;
1852
1853 for (i = 0; i < 14; i++)
1854 x87->env[i] = 0;
1855
1856 x87->env[1] = x87->env[3] = x87->env[5] = x87->env[13] = 0xFFFF;
1857 x87->env[FP_ENV_STAT]
1858 = toUShort(((ftop & 7) << 11) | (c3210 & 0x4700));
1859 x87->env[FP_ENV_CTRL]
1860 = toUShort(amd64g_create_fpucw( vex_state->guest_FPROUND ));
1861
1862 /* Dump the register stack in ST order. */
1863 tagw = 0;
1864 for (stno = 0; stno < 8; stno++) {
1865 preg = (stno + ftop) & 7;
1866 if (vexTags[preg] == 0) {
1867 /* register is empty */
1868 tagw |= (3 << (2*preg));
1869 convert_f64le_to_f80le( (UChar*)&vexRegs[preg],
1870 &x87->reg[10*stno] );
1871 } else {
1872 /* register is full. */
1873 tagw |= (0 << (2*preg));
1874 convert_f64le_to_f80le( (UChar*)&vexRegs[preg],
1875 &x87->reg[10*stno] );
1876 }
1877 }
1878 x87->env[FP_ENV_TAG] = toUShort(tagw);
1879}
1880
1881
1882/* CALLED FROM GENERATED CODE */
1883/* DIRTY HELPER (reads guest state, writes guest mem) */
1884/* NOTE: only handles 32-bit format (no REX.W on the insn) */
sewardj28d71ed2014-09-07 23:23:17 +00001885void amd64g_dirtyhelper_FXSAVE_ALL_EXCEPT_XMM ( VexGuestAMD64State* gst,
1886 HWord addr )
sewardj5abcfe62007-01-10 04:59:33 +00001887{
1888 /* Derived from values obtained from
1889 vendor_id : AuthenticAMD
1890 cpu family : 15
1891 model : 12
1892 model name : AMD Athlon(tm) 64 Processor 3200+
1893 stepping : 0
1894 cpu MHz : 2200.000
1895 cache size : 512 KB
1896 */
1897 /* Somewhat roundabout, but at least it's simple. */
1898 Fpu_State tmp;
1899 UShort* addrS = (UShort*)addr;
1900 UChar* addrC = (UChar*)addr;
sewardj5abcfe62007-01-10 04:59:33 +00001901 UInt mxcsr;
1902 UShort fp_tags;
1903 UInt summary_tags;
1904 Int r, stno;
1905 UShort *srcS, *dstS;
1906
1907 do_get_x87( gst, (UChar*)&tmp );
1908 mxcsr = amd64g_create_mxcsr( gst->guest_SSEROUND );
1909
1910 /* Now build the proper fxsave image from the x87 image we just
1911 made. */
1912
1913 addrS[0] = tmp.env[FP_ENV_CTRL]; /* FCW: fpu control word */
1914 addrS[1] = tmp.env[FP_ENV_STAT]; /* FCW: fpu status word */
1915
1916 /* set addrS[2] in an endian-independent way */
1917 summary_tags = 0;
1918 fp_tags = tmp.env[FP_ENV_TAG];
1919 for (r = 0; r < 8; r++) {
1920 if ( ((fp_tags >> (2*r)) & 3) != 3 )
1921 summary_tags |= (1 << r);
1922 }
1923 addrC[4] = toUChar(summary_tags); /* FTW: tag summary byte */
1924 addrC[5] = 0; /* pad */
1925
1926 /* FOP: faulting fpu opcode. From experimentation, the real CPU
1927 does not write this field. (?!) */
1928 addrS[3] = 0; /* BOGUS */
1929
1930 /* RIP (Last x87 instruction pointer). From experimentation, the
1931 real CPU does not write this field. (?!) */
1932 addrS[4] = 0; /* BOGUS */
1933 addrS[5] = 0; /* BOGUS */
1934 addrS[6] = 0; /* BOGUS */
1935 addrS[7] = 0; /* BOGUS */
1936
1937 /* RDP (Last x87 data pointer). From experimentation, the real CPU
1938 does not write this field. (?!) */
1939 addrS[8] = 0; /* BOGUS */
1940 addrS[9] = 0; /* BOGUS */
1941 addrS[10] = 0; /* BOGUS */
1942 addrS[11] = 0; /* BOGUS */
1943
1944 addrS[12] = toUShort(mxcsr); /* MXCSR */
1945 addrS[13] = toUShort(mxcsr >> 16);
1946
1947 addrS[14] = 0xFFFF; /* MXCSR mask (lo16) */
1948 addrS[15] = 0x0000; /* MXCSR mask (hi16) */
1949
1950 /* Copy in the FP registers, in ST order. */
1951 for (stno = 0; stno < 8; stno++) {
1952 srcS = (UShort*)(&tmp.reg[10*stno]);
1953 dstS = (UShort*)(&addrS[16 + 8*stno]);
1954 dstS[0] = srcS[0];
1955 dstS[1] = srcS[1];
1956 dstS[2] = srcS[2];
1957 dstS[3] = srcS[3];
1958 dstS[4] = srcS[4];
1959 dstS[5] = 0;
1960 dstS[6] = 0;
1961 dstS[7] = 0;
1962 }
1963
1964 /* That's the first 160 bytes of the image done. Now only %xmm0
sewardj28d71ed2014-09-07 23:23:17 +00001965 .. %xmm15 remain to be copied, and we let the generated IR do
1966 that, so as to make Memcheck's definedness flow for the non-XMM
1967 parts independant from that of the all the other control and
1968 status words in the structure. This avoids the false positives
1969 shown in #291310. */
sewardj5abcfe62007-01-10 04:59:33 +00001970}
1971
1972
sewardj5556e5e2011-01-21 18:05:19 +00001973/* CALLED FROM GENERATED CODE */
1974/* DIRTY HELPER (writes guest state, reads guest mem) */
sewardj28d71ed2014-09-07 23:23:17 +00001975VexEmNote amd64g_dirtyhelper_FXRSTOR_ALL_EXCEPT_XMM ( VexGuestAMD64State* gst,
1976 HWord addr )
sewardj5556e5e2011-01-21 18:05:19 +00001977{
1978 Fpu_State tmp;
florian6ef84be2012-08-26 03:20:07 +00001979 VexEmNote warnX87 = EmNote_NONE;
1980 VexEmNote warnXMM = EmNote_NONE;
sewardj5556e5e2011-01-21 18:05:19 +00001981 UShort* addrS = (UShort*)addr;
1982 UChar* addrC = (UChar*)addr;
sewardj5556e5e2011-01-21 18:05:19 +00001983 UShort fp_tags;
1984 Int r, stno, i;
1985
sewardj28d71ed2014-09-07 23:23:17 +00001986 /* Don't restore %xmm0 .. %xmm15, for the same reasons that
1987 amd64g_dirtyhelper_FXSAVE_ALL_EXCEPT_XMM doesn't save them. See
1988 comment in that function for details. */
sewardj5556e5e2011-01-21 18:05:19 +00001989
1990 /* Copy the x87 registers out of the image, into a temporary
1991 Fpu_State struct. */
1992 for (i = 0; i < 14; i++) tmp.env[i] = 0;
1993 for (i = 0; i < 80; i++) tmp.reg[i] = 0;
1994 /* fill in tmp.reg[0..7] */
1995 for (stno = 0; stno < 8; stno++) {
1996 UShort* dstS = (UShort*)(&tmp.reg[10*stno]);
1997 UShort* srcS = (UShort*)(&addrS[16 + 8*stno]);
1998 dstS[0] = srcS[0];
1999 dstS[1] = srcS[1];
2000 dstS[2] = srcS[2];
2001 dstS[3] = srcS[3];
2002 dstS[4] = srcS[4];
2003 }
2004 /* fill in tmp.env[0..13] */
2005 tmp.env[FP_ENV_CTRL] = addrS[0]; /* FCW: fpu control word */
2006 tmp.env[FP_ENV_STAT] = addrS[1]; /* FCW: fpu status word */
2007
2008 fp_tags = 0;
2009 for (r = 0; r < 8; r++) {
2010 if (addrC[4] & (1<<r))
2011 fp_tags |= (0 << (2*r)); /* EMPTY */
2012 else
2013 fp_tags |= (3 << (2*r)); /* VALID -- not really precise enough. */
2014 }
2015 tmp.env[FP_ENV_TAG] = fp_tags;
2016
2017 /* Now write 'tmp' into the guest state. */
2018 warnX87 = do_put_x87( True/*moveRegs*/, (UChar*)&tmp, gst );
2019
2020 { UInt w32 = (((UInt)addrS[12]) & 0xFFFF)
2021 | ((((UInt)addrS[13]) & 0xFFFF) << 16);
2022 ULong w64 = amd64g_check_ldmxcsr( (ULong)w32 );
2023
florian6ef84be2012-08-26 03:20:07 +00002024 warnXMM = (VexEmNote)(w64 >> 32);
sewardj5556e5e2011-01-21 18:05:19 +00002025
2026 gst->guest_SSEROUND = w64 & 0xFFFFFFFFULL;
2027 }
2028
2029 /* Prefer an X87 emwarn over an XMM one, if both exist. */
florian6ef84be2012-08-26 03:20:07 +00002030 if (warnX87 != EmNote_NONE)
sewardj5556e5e2011-01-21 18:05:19 +00002031 return warnX87;
2032 else
2033 return warnXMM;
2034}
2035
2036
sewardj0585a032005-11-05 02:55:06 +00002037/* DIRTY HELPER (writes guest state) */
sewardj8d965312005-02-25 02:48:47 +00002038/* Initialise the x87 FPU state as per 'finit'. */
sewardj8d965312005-02-25 02:48:47 +00002039void amd64g_dirtyhelper_FINIT ( VexGuestAMD64State* gst )
2040{
2041 Int i;
2042 gst->guest_FTOP = 0;
2043 for (i = 0; i < 8; i++) {
2044 gst->guest_FPTAG[i] = 0; /* empty */
2045 gst->guest_FPREG[i] = 0; /* IEEE754 64-bit zero */
2046 }
2047 gst->guest_FPROUND = (ULong)Irrm_NEAREST;
2048 gst->guest_FC3210 = 0;
2049}
2050
sewardjd0a12df2005-02-10 02:07:43 +00002051
sewardj924215b2005-03-26 21:50:31 +00002052/* CALLED FROM GENERATED CODE */
2053/* DIRTY HELPER (reads guest memory) */
sewardj8707fef2005-08-23 23:26:37 +00002054ULong amd64g_dirtyhelper_loadF80le ( ULong addrU )
sewardj924215b2005-03-26 21:50:31 +00002055{
2056 ULong f64;
2057 convert_f80le_to_f64le ( (UChar*)ULong_to_Ptr(addrU), (UChar*)&f64 );
2058 return f64;
2059}
2060
2061/* CALLED FROM GENERATED CODE */
2062/* DIRTY HELPER (writes guest memory) */
sewardj8707fef2005-08-23 23:26:37 +00002063void amd64g_dirtyhelper_storeF80le ( ULong addrU, ULong f64 )
sewardj924215b2005-03-26 21:50:31 +00002064{
2065 convert_f64le_to_f80le( (UChar*)&f64, (UChar*)ULong_to_Ptr(addrU) );
2066}
2067
2068
sewardjbcbb9de2005-03-27 02:22:32 +00002069/* CALLED FROM GENERATED CODE */
2070/* CLEAN HELPER */
2071/* mxcsr[15:0] contains a SSE native format MXCSR value.
2072 Extract from it the required SSEROUND value and any resulting
2073 emulation warning, and return (warn << 32) | sseround value.
2074*/
2075ULong amd64g_check_ldmxcsr ( ULong mxcsr )
2076{
2077 /* Decide on a rounding mode. mxcsr[14:13] holds it. */
2078 /* NOTE, encoded exactly as per enum IRRoundingMode. */
2079 ULong rmode = (mxcsr >> 13) & 3;
2080
2081 /* Detect any required emulation warnings. */
florian6ef84be2012-08-26 03:20:07 +00002082 VexEmNote ew = EmNote_NONE;
sewardjbcbb9de2005-03-27 02:22:32 +00002083
2084 if ((mxcsr & 0x1F80) != 0x1F80) {
2085 /* unmasked exceptions! */
2086 ew = EmWarn_X86_sseExns;
2087 }
2088 else
2089 if (mxcsr & (1<<15)) {
2090 /* FZ is set */
2091 ew = EmWarn_X86_fz;
2092 }
2093 else
2094 if (mxcsr & (1<<6)) {
2095 /* DAZ is set */
2096 ew = EmWarn_X86_daz;
2097 }
2098
2099 return (((ULong)ew) << 32) | ((ULong)rmode);
2100}
2101
2102
2103/* CALLED FROM GENERATED CODE */
2104/* CLEAN HELPER */
2105/* Given sseround as an IRRoundingMode value, create a suitable SSE
2106 native format MXCSR value. */
2107ULong amd64g_create_mxcsr ( ULong sseround )
2108{
2109 sseround &= 3;
2110 return 0x1F80 | (sseround << 13);
2111}
2112
2113
sewardj5e205372005-05-09 02:57:08 +00002114/* CLEAN HELPER */
2115/* fpucw[15:0] contains a x87 native format FPU control word.
2116 Extract from it the required FPROUND value and any resulting
2117 emulation warning, and return (warn << 32) | fpround value.
2118*/
2119ULong amd64g_check_fldcw ( ULong fpucw )
2120{
2121 /* Decide on a rounding mode. fpucw[11:10] holds it. */
2122 /* NOTE, encoded exactly as per enum IRRoundingMode. */
2123 ULong rmode = (fpucw >> 10) & 3;
2124
2125 /* Detect any required emulation warnings. */
florian6ef84be2012-08-26 03:20:07 +00002126 VexEmNote ew = EmNote_NONE;
sewardj5e205372005-05-09 02:57:08 +00002127
2128 if ((fpucw & 0x3F) != 0x3F) {
2129 /* unmasked exceptions! */
2130 ew = EmWarn_X86_x87exns;
2131 }
2132 else
2133 if (((fpucw >> 8) & 3) != 3) {
2134 /* unsupported precision */
2135 ew = EmWarn_X86_x87precision;
2136 }
2137
2138 return (((ULong)ew) << 32) | ((ULong)rmode);
2139}
2140
2141
2142/* CLEAN HELPER */
2143/* Given fpround as an IRRoundingMode value, create a suitable x87
2144 native format FPU control word. */
2145ULong amd64g_create_fpucw ( ULong fpround )
2146{
2147 fpround &= 3;
2148 return 0x037F | (fpround << 10);
2149}
2150
sewardjbcbb9de2005-03-27 02:22:32 +00002151
sewardj4017a3b2005-06-13 12:17:27 +00002152/* This is used to implement 'fldenv'.
2153 Reads 28 bytes at x87_state[0 .. 27]. */
2154/* CALLED FROM GENERATED CODE */
2155/* DIRTY HELPER */
florian6ef84be2012-08-26 03:20:07 +00002156VexEmNote amd64g_dirtyhelper_FLDENV ( /*OUT*/VexGuestAMD64State* vex_state,
sewardj4017a3b2005-06-13 12:17:27 +00002157 /*IN*/HWord x87_state)
2158{
sewardj9ae42a72012-02-16 14:18:56 +00002159 return do_put_x87( False, (UChar*)x87_state, vex_state );
sewardj4017a3b2005-06-13 12:17:27 +00002160}
2161
2162
2163/* CALLED FROM GENERATED CODE */
2164/* DIRTY HELPER */
2165/* Create an x87 FPU env from the guest state, as close as we can
2166 approximate it. Writes 28 bytes at x87_state[0..27]. */
2167void amd64g_dirtyhelper_FSTENV ( /*IN*/VexGuestAMD64State* vex_state,
2168 /*OUT*/HWord x87_state )
2169{
2170 Int i, stno, preg;
2171 UInt tagw;
2172 UChar* vexTags = (UChar*)(&vex_state->guest_FPTAG[0]);
2173 Fpu_State* x87 = (Fpu_State*)x87_state;
2174 UInt ftop = vex_state->guest_FTOP;
2175 ULong c3210 = vex_state->guest_FC3210;
2176
2177 for (i = 0; i < 14; i++)
2178 x87->env[i] = 0;
2179
2180 x87->env[1] = x87->env[3] = x87->env[5] = x87->env[13] = 0xFFFF;
2181 x87->env[FP_ENV_STAT]
sewardj81d72ea2005-06-14 21:59:16 +00002182 = toUShort(toUInt( ((ftop & 7) << 11) | (c3210 & 0x4700) ));
sewardj4017a3b2005-06-13 12:17:27 +00002183 x87->env[FP_ENV_CTRL]
sewardj81d72ea2005-06-14 21:59:16 +00002184 = toUShort(toUInt( amd64g_create_fpucw( vex_state->guest_FPROUND ) ));
sewardj4017a3b2005-06-13 12:17:27 +00002185
2186 /* Compute the x87 tag word. */
2187 tagw = 0;
2188 for (stno = 0; stno < 8; stno++) {
2189 preg = (stno + ftop) & 7;
2190 if (vexTags[preg] == 0) {
2191 /* register is empty */
2192 tagw |= (3 << (2*preg));
2193 } else {
2194 /* register is full. */
2195 tagw |= (0 << (2*preg));
2196 }
2197 }
2198 x87->env[FP_ENV_TAG] = toUShort(tagw);
2199
2200 /* We don't dump the x87 registers, tho. */
2201}
2202
2203
sewardj9ae42a72012-02-16 14:18:56 +00002204/* This is used to implement 'fnsave'.
2205 Writes 108 bytes at x87_state[0 .. 107]. */
2206/* CALLED FROM GENERATED CODE */
2207/* DIRTY HELPER */
2208void amd64g_dirtyhelper_FNSAVE ( /*IN*/VexGuestAMD64State* vex_state,
2209 /*OUT*/HWord x87_state)
2210{
2211 do_get_x87( vex_state, (UChar*)x87_state );
2212}
2213
2214
2215/* This is used to implement 'fnsaves'.
2216 Writes 94 bytes at x87_state[0 .. 93]. */
2217/* CALLED FROM GENERATED CODE */
2218/* DIRTY HELPER */
2219void amd64g_dirtyhelper_FNSAVES ( /*IN*/VexGuestAMD64State* vex_state,
2220 /*OUT*/HWord x87_state)
2221{
2222 Int i, stno, preg;
2223 UInt tagw;
2224 ULong* vexRegs = (ULong*)(&vex_state->guest_FPREG[0]);
2225 UChar* vexTags = (UChar*)(&vex_state->guest_FPTAG[0]);
2226 Fpu_State_16* x87 = (Fpu_State_16*)x87_state;
2227 UInt ftop = vex_state->guest_FTOP;
2228 UInt c3210 = vex_state->guest_FC3210;
2229
2230 for (i = 0; i < 7; i++)
2231 x87->env[i] = 0;
2232
2233 x87->env[FPS_ENV_STAT]
2234 = toUShort(((ftop & 7) << 11) | (c3210 & 0x4700));
2235 x87->env[FPS_ENV_CTRL]
2236 = toUShort(amd64g_create_fpucw( vex_state->guest_FPROUND ));
2237
2238 /* Dump the register stack in ST order. */
2239 tagw = 0;
2240 for (stno = 0; stno < 8; stno++) {
2241 preg = (stno + ftop) & 7;
2242 if (vexTags[preg] == 0) {
2243 /* register is empty */
2244 tagw |= (3 << (2*preg));
2245 convert_f64le_to_f80le( (UChar*)&vexRegs[preg],
2246 &x87->reg[10*stno] );
2247 } else {
2248 /* register is full. */
2249 tagw |= (0 << (2*preg));
2250 convert_f64le_to_f80le( (UChar*)&vexRegs[preg],
2251 &x87->reg[10*stno] );
2252 }
2253 }
2254 x87->env[FPS_ENV_TAG] = toUShort(tagw);
2255}
2256
2257
2258/* This is used to implement 'frstor'.
2259 Reads 108 bytes at x87_state[0 .. 107]. */
2260/* CALLED FROM GENERATED CODE */
2261/* DIRTY HELPER */
florian6ef84be2012-08-26 03:20:07 +00002262VexEmNote amd64g_dirtyhelper_FRSTOR ( /*OUT*/VexGuestAMD64State* vex_state,
sewardj9ae42a72012-02-16 14:18:56 +00002263 /*IN*/HWord x87_state)
2264{
2265 return do_put_x87( True, (UChar*)x87_state, vex_state );
2266}
2267
2268
2269/* This is used to implement 'frstors'.
2270 Reads 94 bytes at x87_state[0 .. 93]. */
2271/* CALLED FROM GENERATED CODE */
2272/* DIRTY HELPER */
florian6ef84be2012-08-26 03:20:07 +00002273VexEmNote amd64g_dirtyhelper_FRSTORS ( /*OUT*/VexGuestAMD64State* vex_state,
sewardj9ae42a72012-02-16 14:18:56 +00002274 /*IN*/HWord x87_state)
2275{
2276 Int stno, preg;
2277 UInt tag;
2278 ULong* vexRegs = (ULong*)(&vex_state->guest_FPREG[0]);
2279 UChar* vexTags = (UChar*)(&vex_state->guest_FPTAG[0]);
2280 Fpu_State_16* x87 = (Fpu_State_16*)x87_state;
2281 UInt ftop = (x87->env[FPS_ENV_STAT] >> 11) & 7;
2282 UInt tagw = x87->env[FPS_ENV_TAG];
2283 UInt fpucw = x87->env[FPS_ENV_CTRL];
2284 UInt c3210 = x87->env[FPS_ENV_STAT] & 0x4700;
florian6ef84be2012-08-26 03:20:07 +00002285 VexEmNote ew;
sewardj9ae42a72012-02-16 14:18:56 +00002286 UInt fpround;
2287 ULong pair;
2288
2289 /* Copy registers and tags */
2290 for (stno = 0; stno < 8; stno++) {
2291 preg = (stno + ftop) & 7;
2292 tag = (tagw >> (2*preg)) & 3;
2293 if (tag == 3) {
2294 /* register is empty */
2295 /* hmm, if it's empty, does it still get written? Probably
2296 safer to say it does. If we don't, memcheck could get out
2297 of sync, in that it thinks all FP registers are defined by
2298 this helper, but in reality some have not been updated. */
2299 vexRegs[preg] = 0; /* IEEE754 64-bit zero */
2300 vexTags[preg] = 0;
2301 } else {
2302 /* register is non-empty */
2303 convert_f80le_to_f64le( &x87->reg[10*stno],
2304 (UChar*)&vexRegs[preg] );
2305 vexTags[preg] = 1;
2306 }
2307 }
2308
2309 /* stack pointer */
2310 vex_state->guest_FTOP = ftop;
2311
2312 /* status word */
2313 vex_state->guest_FC3210 = c3210;
2314
2315 /* handle the control word, setting FPROUND and detecting any
2316 emulation warnings. */
2317 pair = amd64g_check_fldcw ( (ULong)fpucw );
2318 fpround = (UInt)pair & 0xFFFFFFFFULL;
florian6ef84be2012-08-26 03:20:07 +00002319 ew = (VexEmNote)(pair >> 32);
sewardj9ae42a72012-02-16 14:18:56 +00002320
2321 vex_state->guest_FPROUND = fpround & 3;
2322
2323 /* emulation warnings --> caller */
2324 return ew;
2325}
2326
2327
sewardjd0a12df2005-02-10 02:07:43 +00002328/*---------------------------------------------------------------*/
2329/*--- Misc integer helpers, including rotates and CPUID. ---*/
2330/*---------------------------------------------------------------*/
2331
sewardje9d8a262009-07-01 08:06:34 +00002332/* Claim to be the following CPU, which is probably representative of
2333 the lowliest (earliest) amd64 offerings. It can do neither sse3
2334 nor cx16.
2335
2336 vendor_id : AuthenticAMD
2337 cpu family : 15
2338 model : 5
2339 model name : AMD Opteron (tm) Processor 848
2340 stepping : 10
2341 cpu MHz : 1797.682
2342 cache size : 1024 KB
2343 fpu : yes
2344 fpu_exception : yes
2345 cpuid level : 1
2346 wp : yes
2347 flags : fpu vme de pse tsc msr pae mce cx8 apic sep
2348 mtrr pge mca cmov pat pse36 clflush mmx fxsr
2349 sse sse2 syscall nx mmxext lm 3dnowext 3dnow
2350 bogomips : 3600.62
2351 TLB size : 1088 4K pages
2352 clflush size : 64
2353 cache_alignment : 64
2354 address sizes : 40 bits physical, 48 bits virtual
sewardj1aa3aef2012-02-21 08:53:54 +00002355 power management: ts fid vid ttp
2356
2357 2012-Feb-21: don't claim 3dnow or 3dnowext, since in fact
2358 we don't support them. See #291568. 3dnow is 80000001.EDX.31
2359 and 3dnowext is 80000001.EDX.30.
sewardje9d8a262009-07-01 08:06:34 +00002360*/
2361void amd64g_dirtyhelper_CPUID_baseline ( VexGuestAMD64State* st )
2362{
2363# define SET_ABCD(_a,_b,_c,_d) \
2364 do { st->guest_RAX = (ULong)(_a); \
2365 st->guest_RBX = (ULong)(_b); \
2366 st->guest_RCX = (ULong)(_c); \
2367 st->guest_RDX = (ULong)(_d); \
2368 } while (0)
2369
2370 switch (0xFFFFFFFF & st->guest_RAX) {
2371 case 0x00000000:
2372 SET_ABCD(0x00000001, 0x68747541, 0x444d4163, 0x69746e65);
2373 break;
2374 case 0x00000001:
2375 SET_ABCD(0x00000f5a, 0x01000800, 0x00000000, 0x078bfbff);
2376 break;
2377 case 0x80000000:
2378 SET_ABCD(0x80000018, 0x68747541, 0x444d4163, 0x69746e65);
2379 break;
2380 case 0x80000001:
sewardj1aa3aef2012-02-21 08:53:54 +00002381 /* Don't claim to support 3dnow or 3dnowext. 0xe1d3fbff is
2382 the original it-is-supported value that the h/w provides.
2383 See #291568. */
2384 SET_ABCD(0x00000f5a, 0x00000505, 0x00000000, /*0xe1d3fbff*/
2385 0x21d3fbff);
sewardje9d8a262009-07-01 08:06:34 +00002386 break;
2387 case 0x80000002:
2388 SET_ABCD(0x20444d41, 0x6574704f, 0x206e6f72, 0x296d7428);
2389 break;
2390 case 0x80000003:
2391 SET_ABCD(0x6f725020, 0x73736563, 0x3820726f, 0x00003834);
2392 break;
2393 case 0x80000004:
2394 SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2395 break;
2396 case 0x80000005:
2397 SET_ABCD(0xff08ff08, 0xff20ff20, 0x40020140, 0x40020140);
2398 break;
2399 case 0x80000006:
2400 SET_ABCD(0x00000000, 0x42004200, 0x04008140, 0x00000000);
2401 break;
2402 case 0x80000007:
2403 SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x0000000f);
2404 break;
2405 case 0x80000008:
2406 SET_ABCD(0x00003028, 0x00000000, 0x00000000, 0x00000000);
2407 break;
2408 default:
2409 SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2410 break;
2411 }
2412# undef SET_ABCD
2413}
2414
2415
2416/* Claim to be the following CPU (2 x ...), which is sse3 and cx16
2417 capable.
2418
sewardj150c9cd2008-02-09 01:16:02 +00002419 vendor_id : GenuineIntel
2420 cpu family : 6
2421 model : 15
2422 model name : Intel(R) Core(TM)2 CPU 6600 @ 2.40GHz
2423 stepping : 6
2424 cpu MHz : 2394.000
2425 cache size : 4096 KB
2426 physical id : 0
2427 siblings : 2
2428 core id : 0
2429 cpu cores : 2
sewardjd0a12df2005-02-10 02:07:43 +00002430 fpu : yes
2431 fpu_exception : yes
sewardj150c9cd2008-02-09 01:16:02 +00002432 cpuid level : 10
sewardjd0a12df2005-02-10 02:07:43 +00002433 wp : yes
sewardj150c9cd2008-02-09 01:16:02 +00002434 flags : fpu vme de pse tsc msr pae mce cx8 apic sep
2435 mtrr pge mca cmov pat pse36 clflush dts acpi
2436 mmx fxsr sse sse2 ss ht tm syscall nx lm
2437 constant_tsc pni monitor ds_cpl vmx est tm2
2438 cx16 xtpr lahf_lm
2439 bogomips : 4798.78
sewardjd0a12df2005-02-10 02:07:43 +00002440 clflush size : 64
2441 cache_alignment : 64
sewardj150c9cd2008-02-09 01:16:02 +00002442 address sizes : 36 bits physical, 48 bits virtual
2443 power management:
sewardjd0a12df2005-02-10 02:07:43 +00002444*/
sewardje9d8a262009-07-01 08:06:34 +00002445void amd64g_dirtyhelper_CPUID_sse3_and_cx16 ( VexGuestAMD64State* st )
sewardjd0a12df2005-02-10 02:07:43 +00002446{
2447# define SET_ABCD(_a,_b,_c,_d) \
2448 do { st->guest_RAX = (ULong)(_a); \
2449 st->guest_RBX = (ULong)(_b); \
2450 st->guest_RCX = (ULong)(_c); \
2451 st->guest_RDX = (ULong)(_d); \
2452 } while (0)
2453
2454 switch (0xFFFFFFFF & st->guest_RAX) {
sewardj150c9cd2008-02-09 01:16:02 +00002455 case 0x00000000:
2456 SET_ABCD(0x0000000a, 0x756e6547, 0x6c65746e, 0x49656e69);
sewardjd0a12df2005-02-10 02:07:43 +00002457 break;
sewardj150c9cd2008-02-09 01:16:02 +00002458 case 0x00000001:
2459 SET_ABCD(0x000006f6, 0x00020800, 0x0000e3bd, 0xbfebfbff);
sewardjd0a12df2005-02-10 02:07:43 +00002460 break;
sewardj150c9cd2008-02-09 01:16:02 +00002461 case 0x00000002:
2462 SET_ABCD(0x05b0b101, 0x005657f0, 0x00000000, 0x2cb43049);
sewardjd0a12df2005-02-10 02:07:43 +00002463 break;
sewardj150c9cd2008-02-09 01:16:02 +00002464 case 0x00000003:
2465 SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
sewardjd0a12df2005-02-10 02:07:43 +00002466 break;
sewardj32bfd3e2008-02-10 13:29:19 +00002467 case 0x00000004: {
2468 switch (0xFFFFFFFF & st->guest_RCX) {
2469 case 0x00000000: SET_ABCD(0x04000121, 0x01c0003f,
2470 0x0000003f, 0x00000001); break;
2471 case 0x00000001: SET_ABCD(0x04000122, 0x01c0003f,
2472 0x0000003f, 0x00000001); break;
2473 case 0x00000002: SET_ABCD(0x04004143, 0x03c0003f,
2474 0x00000fff, 0x00000001); break;
2475 default: SET_ABCD(0x00000000, 0x00000000,
2476 0x00000000, 0x00000000); break;
2477 }
sewardjd0a12df2005-02-10 02:07:43 +00002478 break;
sewardj32bfd3e2008-02-10 13:29:19 +00002479 }
sewardj150c9cd2008-02-09 01:16:02 +00002480 case 0x00000005:
2481 SET_ABCD(0x00000040, 0x00000040, 0x00000003, 0x00000020);
sewardjd0a12df2005-02-10 02:07:43 +00002482 break;
sewardj150c9cd2008-02-09 01:16:02 +00002483 case 0x00000006:
2484 SET_ABCD(0x00000001, 0x00000002, 0x00000001, 0x00000000);
sewardjd0a12df2005-02-10 02:07:43 +00002485 break;
sewardj150c9cd2008-02-09 01:16:02 +00002486 case 0x00000007:
2487 SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
sewardjd0a12df2005-02-10 02:07:43 +00002488 break;
sewardj150c9cd2008-02-09 01:16:02 +00002489 case 0x00000008:
2490 SET_ABCD(0x00000400, 0x00000000, 0x00000000, 0x00000000);
sewardjd0a12df2005-02-10 02:07:43 +00002491 break;
sewardj150c9cd2008-02-09 01:16:02 +00002492 case 0x00000009:
2493 SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
sewardjd0a12df2005-02-10 02:07:43 +00002494 break;
sewardj150c9cd2008-02-09 01:16:02 +00002495 case 0x0000000a:
sewardj32bfd3e2008-02-10 13:29:19 +00002496 unhandled_eax_value:
sewardj150c9cd2008-02-09 01:16:02 +00002497 SET_ABCD(0x07280202, 0x00000000, 0x00000000, 0x00000000);
2498 break;
2499 case 0x80000000:
2500 SET_ABCD(0x80000008, 0x00000000, 0x00000000, 0x00000000);
2501 break;
2502 case 0x80000001:
2503 SET_ABCD(0x00000000, 0x00000000, 0x00000001, 0x20100800);
2504 break;
2505 case 0x80000002:
2506 SET_ABCD(0x65746e49, 0x2952286c, 0x726f4320, 0x4d542865);
2507 break;
2508 case 0x80000003:
2509 SET_ABCD(0x43203229, 0x20205550, 0x20202020, 0x20202020);
2510 break;
2511 case 0x80000004:
2512 SET_ABCD(0x30303636, 0x20402020, 0x30342e32, 0x007a4847);
2513 break;
2514 case 0x80000005:
2515 SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2516 break;
2517 case 0x80000006:
2518 SET_ABCD(0x00000000, 0x00000000, 0x10008040, 0x00000000);
2519 break;
2520 case 0x80000007:
2521 SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2522 break;
2523 case 0x80000008:
2524 SET_ABCD(0x00003024, 0x00000000, 0x00000000, 0x00000000);
2525 break;
sewardjd0a12df2005-02-10 02:07:43 +00002526 default:
sewardj32bfd3e2008-02-10 13:29:19 +00002527 goto unhandled_eax_value;
sewardjd0a12df2005-02-10 02:07:43 +00002528 }
2529# undef SET_ABCD
2530}
2531
2532
sewardj0b2d3fe2010-08-06 07:59:38 +00002533/* Claim to be the following CPU (4 x ...), which is sse4.2 and cx16
2534 capable.
2535
2536 vendor_id : GenuineIntel
2537 cpu family : 6
2538 model : 37
2539 model name : Intel(R) Core(TM) i5 CPU 670 @ 3.47GHz
2540 stepping : 2
2541 cpu MHz : 3334.000
2542 cache size : 4096 KB
2543 physical id : 0
2544 siblings : 4
2545 core id : 0
2546 cpu cores : 2
2547 apicid : 0
2548 initial apicid : 0
2549 fpu : yes
2550 fpu_exception : yes
2551 cpuid level : 11
2552 wp : yes
2553 flags : fpu vme de pse tsc msr pae mce cx8 apic sep
2554 mtrr pge mca cmov pat pse36 clflush dts acpi
2555 mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp
2556 lm constant_tsc arch_perfmon pebs bts rep_good
2557 xtopology nonstop_tsc aperfmperf pni pclmulqdq
2558 dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16
2559 xtpr pdcm sse4_1 sse4_2 popcnt aes lahf_lm ida
2560 arat tpr_shadow vnmi flexpriority ept vpid
2561 bogomips : 6957.57
2562 clflush size : 64
2563 cache_alignment : 64
2564 address sizes : 36 bits physical, 48 bits virtual
2565 power management:
2566*/
2567void amd64g_dirtyhelper_CPUID_sse42_and_cx16 ( VexGuestAMD64State* st )
2568{
2569# define SET_ABCD(_a,_b,_c,_d) \
2570 do { st->guest_RAX = (ULong)(_a); \
2571 st->guest_RBX = (ULong)(_b); \
2572 st->guest_RCX = (ULong)(_c); \
2573 st->guest_RDX = (ULong)(_d); \
2574 } while (0)
2575
2576 UInt old_eax = (UInt)st->guest_RAX;
2577 UInt old_ecx = (UInt)st->guest_RCX;
2578
2579 switch (old_eax) {
2580 case 0x00000000:
2581 SET_ABCD(0x0000000b, 0x756e6547, 0x6c65746e, 0x49656e69);
2582 break;
2583 case 0x00000001:
philippeff4d6be2012-02-14 21:34:56 +00002584 SET_ABCD(0x00020652, 0x00100800, 0x0298e3ff, 0xbfebfbff);
sewardj0b2d3fe2010-08-06 07:59:38 +00002585 break;
2586 case 0x00000002:
2587 SET_ABCD(0x55035a01, 0x00f0b2e3, 0x00000000, 0x09ca212c);
2588 break;
2589 case 0x00000003:
2590 SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2591 break;
2592 case 0x00000004:
2593 switch (old_ecx) {
2594 case 0x00000000: SET_ABCD(0x1c004121, 0x01c0003f,
2595 0x0000003f, 0x00000000); break;
2596 case 0x00000001: SET_ABCD(0x1c004122, 0x00c0003f,
2597 0x0000007f, 0x00000000); break;
2598 case 0x00000002: SET_ABCD(0x1c004143, 0x01c0003f,
2599 0x000001ff, 0x00000000); break;
2600 case 0x00000003: SET_ABCD(0x1c03c163, 0x03c0003f,
2601 0x00000fff, 0x00000002); break;
2602 default: SET_ABCD(0x00000000, 0x00000000,
2603 0x00000000, 0x00000000); break;
2604 }
2605 break;
2606 case 0x00000005:
2607 SET_ABCD(0x00000040, 0x00000040, 0x00000003, 0x00001120);
2608 break;
2609 case 0x00000006:
2610 SET_ABCD(0x00000007, 0x00000002, 0x00000001, 0x00000000);
2611 break;
2612 case 0x00000007:
2613 SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2614 break;
2615 case 0x00000008:
2616 SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2617 break;
2618 case 0x00000009:
2619 SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2620 break;
2621 case 0x0000000a:
2622 SET_ABCD(0x07300403, 0x00000004, 0x00000000, 0x00000603);
2623 break;
2624 case 0x0000000b:
2625 switch (old_ecx) {
2626 case 0x00000000:
2627 SET_ABCD(0x00000001, 0x00000002,
2628 0x00000100, 0x00000000); break;
2629 case 0x00000001:
2630 SET_ABCD(0x00000004, 0x00000004,
2631 0x00000201, 0x00000000); break;
2632 default:
2633 SET_ABCD(0x00000000, 0x00000000,
2634 old_ecx, 0x00000000); break;
2635 }
2636 break;
2637 case 0x0000000c:
2638 SET_ABCD(0x00000001, 0x00000002, 0x00000100, 0x00000000);
2639 break;
2640 case 0x0000000d:
2641 switch (old_ecx) {
2642 case 0x00000000: SET_ABCD(0x00000001, 0x00000002,
2643 0x00000100, 0x00000000); break;
2644 case 0x00000001: SET_ABCD(0x00000004, 0x00000004,
2645 0x00000201, 0x00000000); break;
2646 default: SET_ABCD(0x00000000, 0x00000000,
2647 old_ecx, 0x00000000); break;
2648 }
2649 break;
2650 case 0x80000000:
2651 SET_ABCD(0x80000008, 0x00000000, 0x00000000, 0x00000000);
2652 break;
2653 case 0x80000001:
2654 SET_ABCD(0x00000000, 0x00000000, 0x00000001, 0x28100800);
2655 break;
2656 case 0x80000002:
2657 SET_ABCD(0x65746e49, 0x2952286c, 0x726f4320, 0x4d542865);
2658 break;
2659 case 0x80000003:
2660 SET_ABCD(0x35692029, 0x55504320, 0x20202020, 0x20202020);
2661 break;
2662 case 0x80000004:
2663 SET_ABCD(0x30373620, 0x20402020, 0x37342e33, 0x007a4847);
2664 break;
2665 case 0x80000005:
2666 SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2667 break;
2668 case 0x80000006:
2669 SET_ABCD(0x00000000, 0x00000000, 0x01006040, 0x00000000);
2670 break;
2671 case 0x80000007:
2672 SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000100);
2673 break;
2674 case 0x80000008:
2675 SET_ABCD(0x00003024, 0x00000000, 0x00000000, 0x00000000);
2676 break;
2677 default:
2678 SET_ABCD(0x00000001, 0x00000002, 0x00000100, 0x00000000);
2679 break;
2680 }
2681# undef SET_ABCD
2682}
2683
2684
sewardjfe0c5e72012-06-15 15:48:07 +00002685/* Claim to be the following CPU (4 x ...), which is AVX and cx16
sewardj9e4c3762013-09-27 15:03:58 +00002686 capable. Plus (kludge!) it "supports" HTM.
sewardjfe0c5e72012-06-15 15:48:07 +00002687
2688 vendor_id : GenuineIntel
2689 cpu family : 6
2690 model : 42
2691 model name : Intel(R) Core(TM) i5-2300 CPU @ 2.80GHz
2692 stepping : 7
2693 cpu MHz : 1600.000
2694 cache size : 6144 KB
2695 physical id : 0
2696 siblings : 4
2697 core id : 3
2698 cpu cores : 4
2699 apicid : 6
2700 initial apicid : 6
2701 fpu : yes
2702 fpu_exception : yes
2703 cpuid level : 13
2704 wp : yes
2705 flags : fpu vme de pse tsc msr pae mce cx8 apic sep
2706 mtrr pge mca cmov pat pse36 clflush dts acpi
2707 mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp
2708 lm constant_tsc arch_perfmon pebs bts rep_good
2709 nopl xtopology nonstop_tsc aperfmperf pni pclmulqdq
2710 dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16
2711 xtpr pdcm sse4_1 sse4_2 popcnt aes xsave avx
2712 lahf_lm ida arat epb xsaveopt pln pts dts
2713 tpr_shadow vnmi flexpriority ept vpid
2714
2715 bogomips : 5768.94
2716 clflush size : 64
2717 cache_alignment : 64
2718 address sizes : 36 bits physical, 48 bits virtual
2719 power management:
2720*/
2721void amd64g_dirtyhelper_CPUID_avx_and_cx16 ( VexGuestAMD64State* st )
2722{
2723# define SET_ABCD(_a,_b,_c,_d) \
2724 do { st->guest_RAX = (ULong)(_a); \
2725 st->guest_RBX = (ULong)(_b); \
2726 st->guest_RCX = (ULong)(_c); \
2727 st->guest_RDX = (ULong)(_d); \
2728 } while (0)
2729
2730 UInt old_eax = (UInt)st->guest_RAX;
2731 UInt old_ecx = (UInt)st->guest_RCX;
2732
2733 switch (old_eax) {
2734 case 0x00000000:
2735 SET_ABCD(0x0000000d, 0x756e6547, 0x6c65746e, 0x49656e69);
2736 break;
2737 case 0x00000001:
2738 SET_ABCD(0x000206a7, 0x00100800, 0x1f9ae3bf, 0xbfebfbff);
2739 break;
2740 case 0x00000002:
2741 SET_ABCD(0x76035a01, 0x00f0b0ff, 0x00000000, 0x00ca0000);
2742 break;
2743 case 0x00000003:
2744 SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2745 break;
2746 case 0x00000004:
2747 switch (old_ecx) {
2748 case 0x00000000: SET_ABCD(0x1c004121, 0x01c0003f,
2749 0x0000003f, 0x00000000); break;
2750 case 0x00000001: SET_ABCD(0x1c004122, 0x01c0003f,
2751 0x0000003f, 0x00000000); break;
2752 case 0x00000002: SET_ABCD(0x1c004143, 0x01c0003f,
2753 0x000001ff, 0x00000000); break;
2754 case 0x00000003: SET_ABCD(0x1c03c163, 0x02c0003f,
2755 0x00001fff, 0x00000006); break;
2756 default: SET_ABCD(0x00000000, 0x00000000,
2757 0x00000000, 0x00000000); break;
2758 }
2759 break;
2760 case 0x00000005:
2761 SET_ABCD(0x00000040, 0x00000040, 0x00000003, 0x00001120);
2762 break;
2763 case 0x00000006:
2764 SET_ABCD(0x00000077, 0x00000002, 0x00000009, 0x00000000);
2765 break;
2766 case 0x00000007:
sewardj9e4c3762013-09-27 15:03:58 +00002767 SET_ABCD(0x00000000, 0x00000800, 0x00000000, 0x00000000);
sewardjfe0c5e72012-06-15 15:48:07 +00002768 break;
2769 case 0x00000008:
2770 SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2771 break;
2772 case 0x00000009:
2773 SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2774 break;
2775 case 0x0000000a:
2776 SET_ABCD(0x07300803, 0x00000000, 0x00000000, 0x00000603);
2777 break;
2778 case 0x0000000b:
2779 switch (old_ecx) {
2780 case 0x00000000:
2781 SET_ABCD(0x00000001, 0x00000001,
2782 0x00000100, 0x00000000); break;
2783 case 0x00000001:
2784 SET_ABCD(0x00000004, 0x00000004,
2785 0x00000201, 0x00000000); break;
2786 default:
2787 SET_ABCD(0x00000000, 0x00000000,
2788 old_ecx, 0x00000000); break;
2789 }
2790 break;
2791 case 0x0000000c:
2792 SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2793 break;
2794 case 0x0000000d:
2795 switch (old_ecx) {
2796 case 0x00000000: SET_ABCD(0x00000007, 0x00000340,
2797 0x00000340, 0x00000000); break;
2798 case 0x00000001: SET_ABCD(0x00000001, 0x00000000,
2799 0x00000000, 0x00000000); break;
2800 case 0x00000002: SET_ABCD(0x00000100, 0x00000240,
2801 0x00000000, 0x00000000); break;
2802 default: SET_ABCD(0x00000000, 0x00000000,
2803 0x00000000, 0x00000000); break;
2804 }
2805 break;
2806 case 0x0000000e:
2807 SET_ABCD(0x00000007, 0x00000340, 0x00000340, 0x00000000);
2808 break;
2809 case 0x0000000f:
2810 SET_ABCD(0x00000007, 0x00000340, 0x00000340, 0x00000000);
2811 break;
2812 case 0x80000000:
2813 SET_ABCD(0x80000008, 0x00000000, 0x00000000, 0x00000000);
2814 break;
2815 case 0x80000001:
2816 SET_ABCD(0x00000000, 0x00000000, 0x00000001, 0x28100800);
2817 break;
2818 case 0x80000002:
2819 SET_ABCD(0x20202020, 0x20202020, 0x65746e49, 0x2952286c);
2820 break;
2821 case 0x80000003:
2822 SET_ABCD(0x726f4320, 0x4d542865, 0x35692029, 0x3033322d);
2823 break;
2824 case 0x80000004:
2825 SET_ABCD(0x50432030, 0x20402055, 0x30382e32, 0x007a4847);
2826 break;
2827 case 0x80000005:
2828 SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000);
2829 break;
2830 case 0x80000006:
2831 SET_ABCD(0x00000000, 0x00000000, 0x01006040, 0x00000000);
2832 break;
2833 case 0x80000007:
2834 SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000100);
2835 break;
2836 case 0x80000008:
2837 SET_ABCD(0x00003024, 0x00000000, 0x00000000, 0x00000000);
2838 break;
2839 default:
2840 SET_ABCD(0x00000007, 0x00000340, 0x00000340, 0x00000000);
2841 break;
2842 }
2843# undef SET_ABCD
2844}
2845
2846
sewardj112b0992005-07-23 13:19:32 +00002847ULong amd64g_calculate_RCR ( ULong arg,
2848 ULong rot_amt,
2849 ULong rflags_in,
2850 Long szIN )
2851{
2852 Bool wantRflags = toBool(szIN < 0);
2853 ULong sz = wantRflags ? (-szIN) : szIN;
2854 ULong tempCOUNT = rot_amt & (sz == 8 ? 0x3F : 0x1F);
2855 ULong cf=0, of=0, tempcf;
2856
2857 switch (sz) {
2858 case 8:
2859 cf = (rflags_in >> AMD64G_CC_SHIFT_C) & 1;
2860 of = ((arg >> 63) ^ cf) & 1;
2861 while (tempCOUNT > 0) {
2862 tempcf = arg & 1;
2863 arg = (arg >> 1) | (cf << 63);
2864 cf = tempcf;
2865 tempCOUNT--;
2866 }
2867 break;
2868 case 4:
2869 while (tempCOUNT >= 33) tempCOUNT -= 33;
2870 cf = (rflags_in >> AMD64G_CC_SHIFT_C) & 1;
2871 of = ((arg >> 31) ^ cf) & 1;
2872 while (tempCOUNT > 0) {
2873 tempcf = arg & 1;
2874 arg = ((arg >> 1) & 0x7FFFFFFFULL) | (cf << 31);
2875 cf = tempcf;
2876 tempCOUNT--;
2877 }
2878 break;
2879 case 2:
2880 while (tempCOUNT >= 17) tempCOUNT -= 17;
2881 cf = (rflags_in >> AMD64G_CC_SHIFT_C) & 1;
2882 of = ((arg >> 15) ^ cf) & 1;
2883 while (tempCOUNT > 0) {
2884 tempcf = arg & 1;
2885 arg = ((arg >> 1) & 0x7FFFULL) | (cf << 15);
2886 cf = tempcf;
2887 tempCOUNT--;
2888 }
2889 break;
2890 case 1:
2891 while (tempCOUNT >= 9) tempCOUNT -= 9;
2892 cf = (rflags_in >> AMD64G_CC_SHIFT_C) & 1;
2893 of = ((arg >> 7) ^ cf) & 1;
2894 while (tempCOUNT > 0) {
2895 tempcf = arg & 1;
2896 arg = ((arg >> 1) & 0x7FULL) | (cf << 7);
2897 cf = tempcf;
2898 tempCOUNT--;
2899 }
2900 break;
2901 default:
2902 vpanic("calculate_RCR(amd64g): invalid size");
2903 }
2904
2905 cf &= 1;
2906 of &= 1;
2907 rflags_in &= ~(AMD64G_CC_MASK_C | AMD64G_CC_MASK_O);
2908 rflags_in |= (cf << AMD64G_CC_SHIFT_C) | (of << AMD64G_CC_SHIFT_O);
2909
2910 /* caller can ask to have back either the resulting flags or
2911 resulting value, but not both */
2912 return wantRflags ? rflags_in : arg;
2913}
2914
sewardjb5e5c6d2007-01-12 20:29:01 +00002915ULong amd64g_calculate_RCL ( ULong arg,
2916 ULong rot_amt,
2917 ULong rflags_in,
2918 Long szIN )
2919{
2920 Bool wantRflags = toBool(szIN < 0);
2921 ULong sz = wantRflags ? (-szIN) : szIN;
2922 ULong tempCOUNT = rot_amt & (sz == 8 ? 0x3F : 0x1F);
2923 ULong cf=0, of=0, tempcf;
2924
2925 switch (sz) {
2926 case 8:
2927 cf = (rflags_in >> AMD64G_CC_SHIFT_C) & 1;
2928 while (tempCOUNT > 0) {
2929 tempcf = (arg >> 63) & 1;
2930 arg = (arg << 1) | (cf & 1);
2931 cf = tempcf;
2932 tempCOUNT--;
2933 }
2934 of = ((arg >> 63) ^ cf) & 1;
2935 break;
2936 case 4:
2937 while (tempCOUNT >= 33) tempCOUNT -= 33;
2938 cf = (rflags_in >> AMD64G_CC_SHIFT_C) & 1;
2939 while (tempCOUNT > 0) {
2940 tempcf = (arg >> 31) & 1;
2941 arg = 0xFFFFFFFFULL & ((arg << 1) | (cf & 1));
2942 cf = tempcf;
2943 tempCOUNT--;
2944 }
2945 of = ((arg >> 31) ^ cf) & 1;
2946 break;
2947 case 2:
2948 while (tempCOUNT >= 17) tempCOUNT -= 17;
2949 cf = (rflags_in >> AMD64G_CC_SHIFT_C) & 1;
2950 while (tempCOUNT > 0) {
2951 tempcf = (arg >> 15) & 1;
2952 arg = 0xFFFFULL & ((arg << 1) | (cf & 1));
2953 cf = tempcf;
2954 tempCOUNT--;
2955 }
2956 of = ((arg >> 15) ^ cf) & 1;
2957 break;
2958 case 1:
2959 while (tempCOUNT >= 9) tempCOUNT -= 9;
2960 cf = (rflags_in >> AMD64G_CC_SHIFT_C) & 1;
2961 while (tempCOUNT > 0) {
2962 tempcf = (arg >> 7) & 1;
2963 arg = 0xFFULL & ((arg << 1) | (cf & 1));
2964 cf = tempcf;
2965 tempCOUNT--;
2966 }
2967 of = ((arg >> 7) ^ cf) & 1;
2968 break;
2969 default:
2970 vpanic("calculate_RCL(amd64g): invalid size");
2971 }
2972
2973 cf &= 1;
2974 of &= 1;
2975 rflags_in &= ~(AMD64G_CC_MASK_C | AMD64G_CC_MASK_O);
2976 rflags_in |= (cf << AMD64G_CC_SHIFT_C) | (of << AMD64G_CC_SHIFT_O);
2977
2978 return wantRflags ? rflags_in : arg;
2979}
2980
sewardj1a179b52010-09-28 19:56:32 +00002981/* Taken from gf2x-0.9.5, released under GPLv2+ (later versions LGPLv2+)
2982 * svn://scm.gforge.inria.fr/svn/gf2x/trunk/hardware/opteron/gf2x_mul1.h@25
2983 */
2984ULong amd64g_calculate_pclmul(ULong a, ULong b, ULong which)
2985{
2986 ULong hi, lo, tmp, A[16];
2987
2988 A[0] = 0; A[1] = a;
2989 A[2] = A[1] << 1; A[3] = A[2] ^ a;
2990 A[4] = A[2] << 1; A[5] = A[4] ^ a;
2991 A[6] = A[3] << 1; A[7] = A[6] ^ a;
2992 A[8] = A[4] << 1; A[9] = A[8] ^ a;
2993 A[10] = A[5] << 1; A[11] = A[10] ^ a;
2994 A[12] = A[6] << 1; A[13] = A[12] ^ a;
2995 A[14] = A[7] << 1; A[15] = A[14] ^ a;
2996
2997 lo = (A[b >> 60] << 4) ^ A[(b >> 56) & 15];
2998 hi = lo >> 56;
2999 lo = (lo << 8) ^ (A[(b >> 52) & 15] << 4) ^ A[(b >> 48) & 15];
3000 hi = (hi << 8) | (lo >> 56);
3001 lo = (lo << 8) ^ (A[(b >> 44) & 15] << 4) ^ A[(b >> 40) & 15];
3002 hi = (hi << 8) | (lo >> 56);
3003 lo = (lo << 8) ^ (A[(b >> 36) & 15] << 4) ^ A[(b >> 32) & 15];
3004 hi = (hi << 8) | (lo >> 56);
3005 lo = (lo << 8) ^ (A[(b >> 28) & 15] << 4) ^ A[(b >> 24) & 15];
3006 hi = (hi << 8) | (lo >> 56);
3007 lo = (lo << 8) ^ (A[(b >> 20) & 15] << 4) ^ A[(b >> 16) & 15];
3008 hi = (hi << 8) | (lo >> 56);
3009 lo = (lo << 8) ^ (A[(b >> 12) & 15] << 4) ^ A[(b >> 8) & 15];
3010 hi = (hi << 8) | (lo >> 56);
3011 lo = (lo << 8) ^ (A[(b >> 4) & 15] << 4) ^ A[b & 15];
3012
3013 ULong m0 = -1;
3014 m0 /= 255;
3015 tmp = -((a >> 63) & 1); tmp &= ((b & (m0 * 0xfe)) >> 1); hi = hi ^ tmp;
3016 tmp = -((a >> 62) & 1); tmp &= ((b & (m0 * 0xfc)) >> 2); hi = hi ^ tmp;
3017 tmp = -((a >> 61) & 1); tmp &= ((b & (m0 * 0xf8)) >> 3); hi = hi ^ tmp;
3018 tmp = -((a >> 60) & 1); tmp &= ((b & (m0 * 0xf0)) >> 4); hi = hi ^ tmp;
3019 tmp = -((a >> 59) & 1); tmp &= ((b & (m0 * 0xe0)) >> 5); hi = hi ^ tmp;
3020 tmp = -((a >> 58) & 1); tmp &= ((b & (m0 * 0xc0)) >> 6); hi = hi ^ tmp;
3021 tmp = -((a >> 57) & 1); tmp &= ((b & (m0 * 0x80)) >> 7); hi = hi ^ tmp;
3022
3023 return which ? hi : lo;
3024}
3025
sewardj112b0992005-07-23 13:19:32 +00003026
sewardjbc6af532005-08-23 23:16:51 +00003027/* CALLED FROM GENERATED CODE */
3028/* DIRTY HELPER (non-referentially-transparent) */
3029/* Horrible hack. On non-amd64 platforms, return 1. */
3030ULong amd64g_dirtyhelper_RDTSC ( void )
3031{
3032# if defined(__x86_64__)
3033 UInt eax, edx;
3034 __asm__ __volatile__("rdtsc" : "=a" (eax), "=d" (edx));
3035 return (((ULong)edx) << 32) | ((ULong)eax);
3036# else
3037 return 1ULL;
3038# endif
3039}
3040
sewardj818c7302013-03-26 13:53:18 +00003041/* CALLED FROM GENERATED CODE */
3042/* DIRTY HELPER (non-referentially-transparent) */
3043/* Horrible hack. On non-amd64 platforms, return 1. */
3044/* This uses a different calling convention from _RDTSC just above
3045 only because of the difficulty of returning 96 bits from a C
3046 function -- RDTSC returns 64 bits and so is simple by comparison,
3047 on amd64. */
3048void amd64g_dirtyhelper_RDTSCP ( VexGuestAMD64State* st )
3049{
3050# if defined(__x86_64__)
3051 UInt eax, ecx, edx;
3052 __asm__ __volatile__("rdtscp" : "=a" (eax), "=d" (edx), "=c" (ecx));
3053 st->guest_RAX = (ULong)eax;
3054 st->guest_RCX = (ULong)ecx;
3055 st->guest_RDX = (ULong)edx;
3056# else
3057 /* Do nothing. */
3058# endif
3059}
sewardjbc6af532005-08-23 23:16:51 +00003060
sewardjbb4396c2007-11-20 17:29:08 +00003061/* CALLED FROM GENERATED CODE */
3062/* DIRTY HELPER (non-referentially-transparent) */
3063/* Horrible hack. On non-amd64 platforms, return 0. */
3064ULong amd64g_dirtyhelper_IN ( ULong portno, ULong sz/*1,2 or 4*/ )
3065{
3066# if defined(__x86_64__)
3067 ULong r = 0;
3068 portno &= 0xFFFF;
3069 switch (sz) {
3070 case 4:
3071 __asm__ __volatile__("movq $0,%%rax; inl %w1,%%eax; movq %%rax,%0"
3072 : "=a" (r) : "Nd" (portno));
3073 break;
3074 case 2:
3075 __asm__ __volatile__("movq $0,%%rax; inw %w1,%w0"
3076 : "=a" (r) : "Nd" (portno));
3077 break;
3078 case 1:
3079 __asm__ __volatile__("movq $0,%%rax; inb %w1,%b0"
3080 : "=a" (r) : "Nd" (portno));
3081 break;
3082 default:
3083 break; /* note: no 64-bit version of insn exists */
3084 }
3085 return r;
3086# else
3087 return 0;
3088# endif
3089}
3090
3091
3092/* CALLED FROM GENERATED CODE */
3093/* DIRTY HELPER (non-referentially-transparent) */
3094/* Horrible hack. On non-amd64 platforms, do nothing. */
3095void amd64g_dirtyhelper_OUT ( ULong portno, ULong data, ULong sz/*1,2 or 4*/ )
3096{
3097# if defined(__x86_64__)
3098 portno &= 0xFFFF;
3099 switch (sz) {
3100 case 4:
3101 __asm__ __volatile__("movq %0,%%rax; outl %%eax, %w1"
3102 : : "a" (data), "Nd" (portno));
3103 break;
3104 case 2:
3105 __asm__ __volatile__("outw %w0, %w1"
3106 : : "a" (data), "Nd" (portno));
3107 break;
3108 case 1:
3109 __asm__ __volatile__("outb %b0, %w1"
3110 : : "a" (data), "Nd" (portno));
3111 break;
3112 default:
3113 break; /* note: no 64-bit version of insn exists */
3114 }
3115# else
3116 /* do nothing */
3117# endif
3118}
3119
sewardjb9dc2432010-06-07 16:22:22 +00003120/* CALLED FROM GENERATED CODE */
3121/* DIRTY HELPER (non-referentially-transparent) */
3122/* Horrible hack. On non-amd64 platforms, do nothing. */
3123/* op = 0: call the native SGDT instruction.
3124 op = 1: call the native SIDT instruction.
3125*/
3126void amd64g_dirtyhelper_SxDT ( void *address, ULong op ) {
3127# if defined(__x86_64__)
3128 switch (op) {
3129 case 0:
3130 __asm__ __volatile__("sgdt (%0)" : : "r" (address) : "memory");
3131 break;
3132 case 1:
3133 __asm__ __volatile__("sidt (%0)" : : "r" (address) : "memory");
3134 break;
3135 default:
3136 vpanic("amd64g_dirtyhelper_SxDT");
3137 }
3138# else
3139 /* do nothing */
3140 UChar* p = (UChar*)address;
3141 p[0] = p[1] = p[2] = p[3] = p[4] = p[5] = 0;
3142 p[6] = p[7] = p[8] = p[9] = 0;
3143# endif
3144}
sewardjbb4396c2007-11-20 17:29:08 +00003145
sewardj8711f662005-05-09 17:52:56 +00003146/*---------------------------------------------------------------*/
3147/*--- Helpers for MMX/SSE/SSE2. ---*/
3148/*---------------------------------------------------------------*/
3149
sewardja7ba8c42005-05-10 20:08:34 +00003150static inline UChar abdU8 ( UChar xx, UChar yy ) {
3151 return toUChar(xx>yy ? xx-yy : yy-xx);
3152}
3153
sewardj8711f662005-05-09 17:52:56 +00003154static inline ULong mk32x2 ( UInt w1, UInt w0 ) {
3155 return (((ULong)w1) << 32) | ((ULong)w0);
3156}
3157
3158static inline UShort sel16x4_3 ( ULong w64 ) {
3159 UInt hi32 = toUInt(w64 >> 32);
3160 return toUShort(hi32 >> 16);
3161}
3162static inline UShort sel16x4_2 ( ULong w64 ) {
3163 UInt hi32 = toUInt(w64 >> 32);
3164 return toUShort(hi32);
3165}
3166static inline UShort sel16x4_1 ( ULong w64 ) {
3167 UInt lo32 = toUInt(w64);
3168 return toUShort(lo32 >> 16);
3169}
3170static inline UShort sel16x4_0 ( ULong w64 ) {
3171 UInt lo32 = toUInt(w64);
3172 return toUShort(lo32);
3173}
3174
sewardja7ba8c42005-05-10 20:08:34 +00003175static inline UChar sel8x8_7 ( ULong w64 ) {
3176 UInt hi32 = toUInt(w64 >> 32);
3177 return toUChar(hi32 >> 24);
3178}
3179static inline UChar sel8x8_6 ( ULong w64 ) {
3180 UInt hi32 = toUInt(w64 >> 32);
3181 return toUChar(hi32 >> 16);
3182}
3183static inline UChar sel8x8_5 ( ULong w64 ) {
3184 UInt hi32 = toUInt(w64 >> 32);
3185 return toUChar(hi32 >> 8);
3186}
3187static inline UChar sel8x8_4 ( ULong w64 ) {
3188 UInt hi32 = toUInt(w64 >> 32);
3189 return toUChar(hi32 >> 0);
3190}
3191static inline UChar sel8x8_3 ( ULong w64 ) {
3192 UInt lo32 = toUInt(w64);
3193 return toUChar(lo32 >> 24);
3194}
3195static inline UChar sel8x8_2 ( ULong w64 ) {
3196 UInt lo32 = toUInt(w64);
3197 return toUChar(lo32 >> 16);
3198}
3199static inline UChar sel8x8_1 ( ULong w64 ) {
3200 UInt lo32 = toUInt(w64);
3201 return toUChar(lo32 >> 8);
3202}
3203static inline UChar sel8x8_0 ( ULong w64 ) {
3204 UInt lo32 = toUInt(w64);
3205 return toUChar(lo32 >> 0);
3206}
3207
sewardj8711f662005-05-09 17:52:56 +00003208/* CALLED FROM GENERATED CODE: CLEAN HELPER */
3209ULong amd64g_calculate_mmx_pmaddwd ( ULong xx, ULong yy )
3210{
3211 return
3212 mk32x2(
3213 (((Int)(Short)sel16x4_3(xx)) * ((Int)(Short)sel16x4_3(yy)))
3214 + (((Int)(Short)sel16x4_2(xx)) * ((Int)(Short)sel16x4_2(yy))),
3215 (((Int)(Short)sel16x4_1(xx)) * ((Int)(Short)sel16x4_1(yy)))
3216 + (((Int)(Short)sel16x4_0(xx)) * ((Int)(Short)sel16x4_0(yy)))
3217 );
3218}
3219
sewardja7ba8c42005-05-10 20:08:34 +00003220/* CALLED FROM GENERATED CODE: CLEAN HELPER */
sewardja7ba8c42005-05-10 20:08:34 +00003221ULong amd64g_calculate_mmx_psadbw ( ULong xx, ULong yy )
3222{
3223 UInt t = 0;
3224 t += (UInt)abdU8( sel8x8_7(xx), sel8x8_7(yy) );
3225 t += (UInt)abdU8( sel8x8_6(xx), sel8x8_6(yy) );
3226 t += (UInt)abdU8( sel8x8_5(xx), sel8x8_5(yy) );
3227 t += (UInt)abdU8( sel8x8_4(xx), sel8x8_4(yy) );
3228 t += (UInt)abdU8( sel8x8_3(xx), sel8x8_3(yy) );
3229 t += (UInt)abdU8( sel8x8_2(xx), sel8x8_2(yy) );
3230 t += (UInt)abdU8( sel8x8_1(xx), sel8x8_1(yy) );
3231 t += (UInt)abdU8( sel8x8_0(xx), sel8x8_0(yy) );
3232 t &= 0xFFFF;
3233 return (ULong)t;
3234}
3235
sewardjadffcef2005-05-11 00:03:06 +00003236/* CALLED FROM GENERATED CODE: CLEAN HELPER */
sewardj8cb931e2012-02-16 22:02:14 +00003237ULong amd64g_calculate_sse_phminposuw ( ULong sLo, ULong sHi )
3238{
3239 UShort t, min;
3240 UInt idx;
3241 t = sel16x4_0(sLo); if (True) { min = t; idx = 0; }
3242 t = sel16x4_1(sLo); if (t < min) { min = t; idx = 1; }
3243 t = sel16x4_2(sLo); if (t < min) { min = t; idx = 2; }
3244 t = sel16x4_3(sLo); if (t < min) { min = t; idx = 3; }
3245 t = sel16x4_0(sHi); if (t < min) { min = t; idx = 4; }
3246 t = sel16x4_1(sHi); if (t < min) { min = t; idx = 5; }
3247 t = sel16x4_2(sHi); if (t < min) { min = t; idx = 6; }
3248 t = sel16x4_3(sHi); if (t < min) { min = t; idx = 7; }
3249 return ((ULong)(idx << 16)) | ((ULong)min);
3250}
3251
3252/* CALLED FROM GENERATED CODE: CLEAN HELPER */
sewardj186f8692011-01-21 17:51:44 +00003253ULong amd64g_calc_crc32b ( ULong crcIn, ULong b )
3254{
3255 UInt i;
3256 ULong crc = (b & 0xFFULL) ^ crcIn;
3257 for (i = 0; i < 8; i++)
3258 crc = (crc >> 1) ^ ((crc & 1) ? 0x82f63b78ULL : 0);
3259 return crc;
3260}
3261
3262/* CALLED FROM GENERATED CODE: CLEAN HELPER */
3263ULong amd64g_calc_crc32w ( ULong crcIn, ULong w )
3264{
3265 UInt i;
3266 ULong crc = (w & 0xFFFFULL) ^ crcIn;
3267 for (i = 0; i < 16; i++)
3268 crc = (crc >> 1) ^ ((crc & 1) ? 0x82f63b78ULL : 0);
3269 return crc;
3270}
3271
3272/* CALLED FROM GENERATED CODE: CLEAN HELPER */
3273ULong amd64g_calc_crc32l ( ULong crcIn, ULong l )
3274{
3275 UInt i;
3276 ULong crc = (l & 0xFFFFFFFFULL) ^ crcIn;
3277 for (i = 0; i < 32; i++)
3278 crc = (crc >> 1) ^ ((crc & 1) ? 0x82f63b78ULL : 0);
3279 return crc;
3280}
3281
3282/* CALLED FROM GENERATED CODE: CLEAN HELPER */
3283ULong amd64g_calc_crc32q ( ULong crcIn, ULong q )
3284{
3285 ULong crc = amd64g_calc_crc32l(crcIn, q);
3286 return amd64g_calc_crc32l(crc, q >> 32);
3287}
3288
sewardjd0a12df2005-02-10 02:07:43 +00003289
sewardj4d5bce22012-02-21 11:02:44 +00003290/* .. helper for next fn .. */
3291static inline ULong sad_8x4 ( ULong xx, ULong yy )
3292{
3293 UInt t = 0;
3294 t += (UInt)abdU8( sel8x8_3(xx), sel8x8_3(yy) );
3295 t += (UInt)abdU8( sel8x8_2(xx), sel8x8_2(yy) );
3296 t += (UInt)abdU8( sel8x8_1(xx), sel8x8_1(yy) );
3297 t += (UInt)abdU8( sel8x8_0(xx), sel8x8_0(yy) );
3298 return (ULong)t;
3299}
3300
3301/* CALLED FROM GENERATED CODE: CLEAN HELPER */
3302ULong amd64g_calc_mpsadbw ( ULong sHi, ULong sLo,
3303 ULong dHi, ULong dLo,
3304 ULong imm_and_return_control_bit )
3305{
3306 UInt imm8 = imm_and_return_control_bit & 7;
3307 Bool calcHi = (imm_and_return_control_bit >> 7) & 1;
3308 UInt srcOffsL = imm8 & 3; /* src offs in 32-bit (L) chunks */
3309 UInt dstOffsL = (imm8 >> 2) & 1; /* dst offs in ditto chunks */
3310 /* For src we only need 32 bits, so get them into the
3311 lower half of a 64 bit word. */
3312 ULong src = ((srcOffsL & 2) ? sHi : sLo) >> (32 * (srcOffsL & 1));
3313 /* For dst we need to get hold of 56 bits (7 bytes) from a total of
3314 11 bytes. If calculating the low part of the result, need bytes
3315 dstOffsL * 4 + (0 .. 6); if calculating the high part,
3316 dstOffsL * 4 + (4 .. 10). */
3317 ULong dst;
3318 /* dstOffL = 0, Lo -> 0 .. 6
3319 dstOffL = 1, Lo -> 4 .. 10
3320 dstOffL = 0, Hi -> 4 .. 10
3321 dstOffL = 1, Hi -> 8 .. 14
3322 */
3323 if (calcHi && dstOffsL) {
3324 /* 8 .. 14 */
3325 dst = dHi & 0x00FFFFFFFFFFFFFFULL;
3326 }
3327 else if (!calcHi && !dstOffsL) {
3328 /* 0 .. 6 */
3329 dst = dLo & 0x00FFFFFFFFFFFFFFULL;
3330 }
3331 else {
3332 /* 4 .. 10 */
3333 dst = (dLo >> 32) | ((dHi & 0x00FFFFFFULL) << 32);
3334 }
3335 ULong r0 = sad_8x4( dst >> 0, src );
3336 ULong r1 = sad_8x4( dst >> 8, src );
3337 ULong r2 = sad_8x4( dst >> 16, src );
3338 ULong r3 = sad_8x4( dst >> 24, src );
3339 ULong res = (r3 << 48) | (r2 << 32) | (r1 << 16) | r0;
3340 return res;
3341}
3342
sewardjcc3d2192013-03-27 11:37:33 +00003343/* CALLED FROM GENERATED CODE: CLEAN HELPER */
3344ULong amd64g_calculate_pext ( ULong src_masked, ULong mask )
3345{
3346 ULong dst = 0;
3347 ULong src_bit;
3348 ULong dst_bit = 1;
3349 for (src_bit = 1; src_bit; src_bit <<= 1) {
3350 if (mask & src_bit) {
3351 if (src_masked & src_bit) dst |= dst_bit;
3352 dst_bit <<= 1;
3353 }
3354 }
3355 return dst;
3356}
3357
3358/* CALLED FROM GENERATED CODE: CLEAN HELPER */
3359ULong amd64g_calculate_pdep ( ULong src, ULong mask )
3360{
3361 ULong dst = 0;
3362 ULong dst_bit;
3363 ULong src_bit = 1;
3364 for (dst_bit = 1; dst_bit; dst_bit <<= 1) {
3365 if (mask & dst_bit) {
3366 if (src & src_bit) dst |= dst_bit;
3367 src_bit <<= 1;
3368 }
3369 }
3370 return dst;
3371}
3372
sewardjf8c37f72005-02-07 18:55:29 +00003373/*---------------------------------------------------------------*/
sewardj0b2d3fe2010-08-06 07:59:38 +00003374/*--- Helpers for SSE4.2 PCMP{E,I}STR{I,M} ---*/
3375/*---------------------------------------------------------------*/
3376
sewardjacfbd7d2010-08-17 22:52:08 +00003377static UInt zmask_from_V128 ( V128* arg )
3378{
3379 UInt i, res = 0;
3380 for (i = 0; i < 16; i++) {
3381 res |= ((arg->w8[i] == 0) ? 1 : 0) << i;
3382 }
3383 return res;
3384}
3385
sewardj3c3d6d62012-02-16 15:21:08 +00003386static UInt zmask_from_V128_wide ( V128* arg )
3387{
3388 UInt i, res = 0;
3389 for (i = 0; i < 8; i++) {
3390 res |= ((arg->w16[i] == 0) ? 1 : 0) << i;
3391 }
3392 return res;
3393}
3394
sewardjacfbd7d2010-08-17 22:52:08 +00003395/* Helps with PCMP{I,E}STR{I,M}.
3396
3397 CALLED FROM GENERATED CODE: DIRTY HELPER(s). (But not really,
sewardj0b2d3fe2010-08-06 07:59:38 +00003398 actually it could be a clean helper, but for the fact that we can't
sewardjacfbd7d2010-08-17 22:52:08 +00003399 pass by value 2 x V128 to a clean helper, nor have one returned.)
3400 Reads guest state, writes to guest state for the xSTRM cases, no
3401 accesses of memory, is a pure function.
3402
3403 opc_and_imm contains (4th byte of opcode << 8) | the-imm8-byte so
3404 the callee knows which I/E and I/M variant it is dealing with and
3405 what the specific operation is. 4th byte of opcode is in the range
3406 0x60 to 0x63:
3407 istri 66 0F 3A 63
3408 istrm 66 0F 3A 62
3409 estri 66 0F 3A 61
3410 estrm 66 0F 3A 60
3411
3412 gstOffL and gstOffR are the guest state offsets for the two XMM
3413 register inputs. We never have to deal with the memory case since
3414 that is handled by pre-loading the relevant value into the fake
3415 XMM16 register.
3416
3417 For ESTRx variants, edxIN and eaxIN hold the values of those two
3418 registers.
3419
3420 In all cases, the bottom 16 bits of the result contain the new
3421 OSZACP %rflags values. For xSTRI variants, bits[31:16] of the
3422 result hold the new %ecx value. For xSTRM variants, the helper
3423 writes the result directly to the guest XMM0.
3424
3425 Declarable side effects: in all cases, reads guest state at
3426 [gstOffL, +16) and [gstOffR, +16). For xSTRM variants, also writes
3427 guest_XMM0.
3428
3429 Is expected to be called with opc_and_imm combinations which have
3430 actually been validated, and will assert if otherwise. The front
3431 end should ensure we're only called with verified values.
sewardj0b2d3fe2010-08-06 07:59:38 +00003432*/
sewardjacfbd7d2010-08-17 22:52:08 +00003433ULong amd64g_dirtyhelper_PCMPxSTRx (
3434 VexGuestAMD64State* gst,
3435 HWord opc4_and_imm,
3436 HWord gstOffL, HWord gstOffR,
3437 HWord edxIN, HWord eaxIN
3438 )
sewardj0b2d3fe2010-08-06 07:59:38 +00003439{
sewardjacfbd7d2010-08-17 22:52:08 +00003440 HWord opc4 = (opc4_and_imm >> 8) & 0xFF;
3441 HWord imm8 = opc4_and_imm & 0xFF;
3442 HWord isISTRx = opc4 & 2;
3443 HWord isxSTRM = (opc4 & 1) ^ 1;
3444 vassert((opc4 & 0xFC) == 0x60); /* 0x60 .. 0x63 */
sewardj3c3d6d62012-02-16 15:21:08 +00003445 HWord wide = (imm8 & 1);
sewardj0b2d3fe2010-08-06 07:59:38 +00003446
sewardjacfbd7d2010-08-17 22:52:08 +00003447 // where the args are
3448 V128* argL = (V128*)( ((UChar*)gst) + gstOffL );
3449 V128* argR = (V128*)( ((UChar*)gst) + gstOffR );
sewardj0b2d3fe2010-08-06 07:59:38 +00003450
sewardjacfbd7d2010-08-17 22:52:08 +00003451 /* Create the arg validity masks, either from the vectors
3452 themselves or from the supplied edx/eax values. */
3453 // FIXME: this is only right for the 8-bit data cases.
3454 // At least that is asserted above.
3455 UInt zmaskL, zmaskR;
sewardj0b2d3fe2010-08-06 07:59:38 +00003456
sewardjacfbd7d2010-08-17 22:52:08 +00003457 // temp spot for the resulting flags and vector.
3458 V128 resV;
3459 UInt resOSZACP;
3460
sewardj3c3d6d62012-02-16 15:21:08 +00003461 // for checking whether case was handled
3462 Bool ok = False;
3463
3464 if (wide) {
3465 if (isISTRx) {
3466 zmaskL = zmask_from_V128_wide(argL);
3467 zmaskR = zmask_from_V128_wide(argR);
3468 } else {
3469 Int tmp;
3470 tmp = edxIN & 0xFFFFFFFF;
3471 if (tmp < -8) tmp = -8;
3472 if (tmp > 8) tmp = 8;
3473 if (tmp < 0) tmp = -tmp;
3474 vassert(tmp >= 0 && tmp <= 8);
3475 zmaskL = (1 << tmp) & 0xFF;
3476 tmp = eaxIN & 0xFFFFFFFF;
3477 if (tmp < -8) tmp = -8;
3478 if (tmp > 8) tmp = 8;
3479 if (tmp < 0) tmp = -tmp;
3480 vassert(tmp >= 0 && tmp <= 8);
3481 zmaskR = (1 << tmp) & 0xFF;
3482 }
3483 // do the meyaath
3484 ok = compute_PCMPxSTRx_wide (
3485 &resV, &resOSZACP, argL, argR,
3486 zmaskL, zmaskR, imm8, (Bool)isxSTRM
3487 );
3488 } else {
3489 if (isISTRx) {
3490 zmaskL = zmask_from_V128(argL);
3491 zmaskR = zmask_from_V128(argR);
3492 } else {
3493 Int tmp;
3494 tmp = edxIN & 0xFFFFFFFF;
3495 if (tmp < -16) tmp = -16;
3496 if (tmp > 16) tmp = 16;
3497 if (tmp < 0) tmp = -tmp;
3498 vassert(tmp >= 0 && tmp <= 16);
3499 zmaskL = (1 << tmp) & 0xFFFF;
3500 tmp = eaxIN & 0xFFFFFFFF;
3501 if (tmp < -16) tmp = -16;
3502 if (tmp > 16) tmp = 16;
3503 if (tmp < 0) tmp = -tmp;
3504 vassert(tmp >= 0 && tmp <= 16);
3505 zmaskR = (1 << tmp) & 0xFFFF;
3506 }
3507 // do the meyaath
3508 ok = compute_PCMPxSTRx (
3509 &resV, &resOSZACP, argL, argR,
3510 zmaskL, zmaskR, imm8, (Bool)isxSTRM
3511 );
3512 }
sewardjacfbd7d2010-08-17 22:52:08 +00003513
3514 // front end shouldn't pass us any imm8 variants we can't
3515 // handle. Hence:
3516 vassert(ok);
3517
3518 // So, finally we need to get the results back to the caller.
3519 // In all cases, the new OSZACP value is the lowest 16 of
3520 // the return value.
3521 if (isxSTRM) {
sewardjc4530ae2012-05-21 10:18:49 +00003522 gst->guest_YMM0[0] = resV.w32[0];
3523 gst->guest_YMM0[1] = resV.w32[1];
3524 gst->guest_YMM0[2] = resV.w32[2];
3525 gst->guest_YMM0[3] = resV.w32[3];
sewardjacfbd7d2010-08-17 22:52:08 +00003526 return resOSZACP & 0x8D5;
3527 } else {
3528 UInt newECX = resV.w32[0] & 0xFFFF;
3529 return (newECX << 16) | (resOSZACP & 0x8D5);
3530 }
sewardj0b2d3fe2010-08-06 07:59:38 +00003531}
3532
philippeff4d6be2012-02-14 21:34:56 +00003533/*---------------------------------------------------------------*/
3534/*--- AES primitives and helpers ---*/
3535/*---------------------------------------------------------------*/
3536/* a 16 x 16 matrix */
3537static const UChar sbox[256] = { // row nr
3538 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, // 1
3539 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
3540 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, // 2
3541 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
3542 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, // 3
3543 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
3544 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, // 4
3545 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
3546 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, // 5
3547 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
3548 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, // 6
3549 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
3550 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, // 7
3551 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
3552 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, // 8
3553 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
3554 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, // 9
3555 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
3556 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, //10
3557 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
3558 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, //11
3559 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
3560 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, //12
3561 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
3562 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, //13
3563 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
3564 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, //14
3565 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
3566 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, //15
3567 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
3568 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, //16
3569 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
3570};
3571static void SubBytes (V128* v)
3572{
3573 V128 r;
3574 UInt i;
3575 for (i = 0; i < 16; i++)
3576 r.w8[i] = sbox[v->w8[i]];
3577 *v = r;
3578}
3579
3580/* a 16 x 16 matrix */
3581static const UChar invsbox[256] = { // row nr
3582 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, // 1
3583 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
3584 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, // 2
3585 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
3586 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, // 3
3587 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
3588 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, // 4
3589 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
3590 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, // 5
3591 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
3592 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, // 6
3593 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
3594 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, // 7
3595 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
3596 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, // 8
3597 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
3598 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, // 9
3599 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
3600 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, //10
3601 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
3602 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, //11
3603 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
3604 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, //12
3605 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
3606 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, //13
3607 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
3608 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, //14
3609 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
3610 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, //15
3611 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
3612 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, //16
3613 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
3614};
3615static void InvSubBytes (V128* v)
3616{
3617 V128 r;
3618 UInt i;
3619 for (i = 0; i < 16; i++)
3620 r.w8[i] = invsbox[v->w8[i]];
3621 *v = r;
3622}
3623
3624static const UChar ShiftRows_op[16] =
3625 {11, 6, 1, 12, 7, 2, 13, 8, 3, 14, 9, 4, 15, 10, 5, 0};
3626static void ShiftRows (V128* v)
3627{
3628 V128 r;
3629 UInt i;
3630 for (i = 0; i < 16; i++)
3631 r.w8[i] = v->w8[ShiftRows_op[15-i]];
3632 *v = r;
3633}
3634
3635static const UChar InvShiftRows_op[16] =
3636 {3, 6, 9, 12, 15, 2, 5, 8, 11, 14, 1, 4, 7, 10, 13, 0};
3637static void InvShiftRows (V128* v)
3638{
3639 V128 r;
3640 UInt i;
3641 for (i = 0; i < 16; i++)
3642 r.w8[i] = v->w8[InvShiftRows_op[15-i]];
3643 *v = r;
3644}
3645
3646/* Multiplication of the finite fields elements of AES.
3647 See "A Specification for The AES Algorithm Rijndael
3648 (by Joan Daemen & Vincent Rijmen)"
3649 Dr. Brian Gladman, v3.1, 3rd March 2001. */
3650/* N values so that (hex) xy = 0x03^N.
3651 0x00 cannot be used. We put 0xff for this value.*/
3652/* a 16 x 16 matrix */
3653static const UChar Nxy[256] = { // row nr
3654 0xff, 0x00, 0x19, 0x01, 0x32, 0x02, 0x1a, 0xc6, // 1
3655 0x4b, 0xc7, 0x1b, 0x68, 0x33, 0xee, 0xdf, 0x03,
3656 0x64, 0x04, 0xe0, 0x0e, 0x34, 0x8d, 0x81, 0xef, // 2
3657 0x4c, 0x71, 0x08, 0xc8, 0xf8, 0x69, 0x1c, 0xc1,
3658 0x7d, 0xc2, 0x1d, 0xb5, 0xf9, 0xb9, 0x27, 0x6a, // 3
3659 0x4d, 0xe4, 0xa6, 0x72, 0x9a, 0xc9, 0x09, 0x78,
3660 0x65, 0x2f, 0x8a, 0x05, 0x21, 0x0f, 0xe1, 0x24, // 4
3661 0x12, 0xf0, 0x82, 0x45, 0x35, 0x93, 0xda, 0x8e,
3662 0x96, 0x8f, 0xdb, 0xbd, 0x36, 0xd0, 0xce, 0x94, // 5
3663 0x13, 0x5c, 0xd2, 0xf1, 0x40, 0x46, 0x83, 0x38,
3664 0x66, 0xdd, 0xfd, 0x30, 0xbf, 0x06, 0x8b, 0x62, // 6
3665 0xb3, 0x25, 0xe2, 0x98, 0x22, 0x88, 0x91, 0x10,
3666 0x7e, 0x6e, 0x48, 0xc3, 0xa3, 0xb6, 0x1e, 0x42, // 7
3667 0x3a, 0x6b, 0x28, 0x54, 0xfa, 0x85, 0x3d, 0xba,
3668 0x2b, 0x79, 0x0a, 0x15, 0x9b, 0x9f, 0x5e, 0xca, // 8
3669 0x4e, 0xd4, 0xac, 0xe5, 0xf3, 0x73, 0xa7, 0x57,
3670 0xaf, 0x58, 0xa8, 0x50, 0xf4, 0xea, 0xd6, 0x74, // 9
3671 0x4f, 0xae, 0xe9, 0xd5, 0xe7, 0xe6, 0xad, 0xe8,
3672 0x2c, 0xd7, 0x75, 0x7a, 0xeb, 0x16, 0x0b, 0xf5, //10
3673 0x59, 0xcb, 0x5f, 0xb0, 0x9c, 0xa9, 0x51, 0xa0,
3674 0x7f, 0x0c, 0xf6, 0x6f, 0x17, 0xc4, 0x49, 0xec, //11
3675 0xd8, 0x43, 0x1f, 0x2d, 0xa4, 0x76, 0x7b, 0xb7,
3676 0xcc, 0xbb, 0x3e, 0x5a, 0xfb, 0x60, 0xb1, 0x86, //12
3677 0x3b, 0x52, 0xa1, 0x6c, 0xaa, 0x55, 0x29, 0x9d,
3678 0x97, 0xb2, 0x87, 0x90, 0x61, 0xbe, 0xdc, 0xfc, //13
3679 0xbc, 0x95, 0xcf, 0xcd, 0x37, 0x3f, 0x5b, 0xd1,
3680 0x53, 0x39, 0x84, 0x3c, 0x41, 0xa2, 0x6d, 0x47, //14
3681 0x14, 0x2a, 0x9e, 0x5d, 0x56, 0xf2, 0xd3, 0xab,
3682 0x44, 0x11, 0x92, 0xd9, 0x23, 0x20, 0x2e, 0x89, //15
3683 0xb4, 0x7c, 0xb8, 0x26, 0x77, 0x99, 0xe3, 0xa5,
3684 0x67, 0x4a, 0xed, 0xde, 0xc5, 0x31, 0xfe, 0x18, //16
3685 0x0d, 0x63, 0x8c, 0x80, 0xc0, 0xf7, 0x70, 0x07
3686};
3687
3688/* E values so that E = 0x03^xy. */
3689static const UChar Exy[256] = { // row nr
3690 0x01, 0x03, 0x05, 0x0f, 0x11, 0x33, 0x55, 0xff, // 1
3691 0x1a, 0x2e, 0x72, 0x96, 0xa1, 0xf8, 0x13, 0x35,
3692 0x5f, 0xe1, 0x38, 0x48, 0xd8, 0x73, 0x95, 0xa4, // 2
3693 0xf7, 0x02, 0x06, 0x0a, 0x1e, 0x22, 0x66, 0xaa,
3694 0xe5, 0x34, 0x5c, 0xe4, 0x37, 0x59, 0xeb, 0x26, // 3
3695 0x6a, 0xbe, 0xd9, 0x70, 0x90, 0xab, 0xe6, 0x31,
3696 0x53, 0xf5, 0x04, 0x0c, 0x14, 0x3c, 0x44, 0xcc, // 4
3697 0x4f, 0xd1, 0x68, 0xb8, 0xd3, 0x6e, 0xb2, 0xcd,
3698 0x4c, 0xd4, 0x67, 0xa9, 0xe0, 0x3b, 0x4d, 0xd7, // 5
3699 0x62, 0xa6, 0xf1, 0x08, 0x18, 0x28, 0x78, 0x88,
3700 0x83, 0x9e, 0xb9, 0xd0, 0x6b, 0xbd, 0xdc, 0x7f, // 6
3701 0x81, 0x98, 0xb3, 0xce, 0x49, 0xdb, 0x76, 0x9a,
3702 0xb5, 0xc4, 0x57, 0xf9, 0x10, 0x30, 0x50, 0xf0, // 7
3703 0x0b, 0x1d, 0x27, 0x69, 0xbb, 0xd6, 0x61, 0xa3,
3704 0xfe, 0x19, 0x2b, 0x7d, 0x87, 0x92, 0xad, 0xec, // 8
3705 0x2f, 0x71, 0x93, 0xae, 0xe9, 0x20, 0x60, 0xa0,
3706 0xfb, 0x16, 0x3a, 0x4e, 0xd2, 0x6d, 0xb7, 0xc2, // 9
3707 0x5d, 0xe7, 0x32, 0x56, 0xfa, 0x15, 0x3f, 0x41,
3708 0xc3, 0x5e, 0xe2, 0x3d, 0x47, 0xc9, 0x40, 0xc0, //10
3709 0x5b, 0xed, 0x2c, 0x74, 0x9c, 0xbf, 0xda, 0x75,
3710 0x9f, 0xba, 0xd5, 0x64, 0xac, 0xef, 0x2a, 0x7e, //11
3711 0x82, 0x9d, 0xbc, 0xdf, 0x7a, 0x8e, 0x89, 0x80,
3712 0x9b, 0xb6, 0xc1, 0x58, 0xe8, 0x23, 0x65, 0xaf, //12
3713 0xea, 0x25, 0x6f, 0xb1, 0xc8, 0x43, 0xc5, 0x54,
3714 0xfc, 0x1f, 0x21, 0x63, 0xa5, 0xf4, 0x07, 0x09, //13
3715 0x1b, 0x2d, 0x77, 0x99, 0xb0, 0xcb, 0x46, 0xca,
3716 0x45, 0xcf, 0x4a, 0xde, 0x79, 0x8b, 0x86, 0x91, //14
3717 0xa8, 0xe3, 0x3e, 0x42, 0xc6, 0x51, 0xf3, 0x0e,
3718 0x12, 0x36, 0x5a, 0xee, 0x29, 0x7b, 0x8d, 0x8c, //15
3719 0x8f, 0x8a, 0x85, 0x94, 0xa7, 0xf2, 0x0d, 0x17,
3720 0x39, 0x4b, 0xdd, 0x7c, 0x84, 0x97, 0xa2, 0xfd, //16
3721 0x1c, 0x24, 0x6c, 0xb4, 0xc7, 0x52, 0xf6, 0x01};
3722
3723static inline UChar ff_mul(UChar u1, UChar u2)
3724{
3725 if ((u1 > 0) && (u2 > 0)) {
3726 UInt ui = Nxy[u1] + Nxy[u2];
3727 if (ui >= 255)
3728 ui = ui - 255;
3729 return Exy[ui];
3730 } else {
3731 return 0;
3732 };
3733}
3734
3735static void MixColumns (V128* v)
3736{
3737 V128 r;
3738 Int j;
3739#define P(x,row,col) (x)->w8[((row)*4+(col))]
3740 for (j = 0; j < 4; j++) {
3741 P(&r,j,0) = ff_mul(0x02, P(v,j,0)) ^ ff_mul(0x03, P(v,j,1))
3742 ^ P(v,j,2) ^ P(v,j,3);
3743 P(&r,j,1) = P(v,j,0) ^ ff_mul( 0x02, P(v,j,1) )
3744 ^ ff_mul(0x03, P(v,j,2) ) ^ P(v,j,3);
3745 P(&r,j,2) = P(v,j,0) ^ P(v,j,1) ^ ff_mul( 0x02, P(v,j,2) )
3746 ^ ff_mul(0x03, P(v,j,3) );
3747 P(&r,j,3) = ff_mul(0x03, P(v,j,0) ) ^ P(v,j,1) ^ P(v,j,2)
3748 ^ ff_mul( 0x02, P(v,j,3) );
3749 }
3750 *v = r;
3751#undef P
3752}
3753
3754static void InvMixColumns (V128* v)
3755{
3756 V128 r;
3757 Int j;
3758#define P(x,row,col) (x)->w8[((row)*4+(col))]
3759 for (j = 0; j < 4; j++) {
3760 P(&r,j,0) = ff_mul(0x0e, P(v,j,0) ) ^ ff_mul(0x0b, P(v,j,1) )
3761 ^ ff_mul(0x0d,P(v,j,2) ) ^ ff_mul(0x09, P(v,j,3) );
3762 P(&r,j,1) = ff_mul(0x09, P(v,j,0) ) ^ ff_mul(0x0e, P(v,j,1) )
3763 ^ ff_mul(0x0b,P(v,j,2) ) ^ ff_mul(0x0d, P(v,j,3) );
3764 P(&r,j,2) = ff_mul(0x0d, P(v,j,0) ) ^ ff_mul(0x09, P(v,j,1) )
3765 ^ ff_mul(0x0e,P(v,j,2) ) ^ ff_mul(0x0b, P(v,j,3) );
3766 P(&r,j,3) = ff_mul(0x0b, P(v,j,0) ) ^ ff_mul(0x0d, P(v,j,1) )
3767 ^ ff_mul(0x09,P(v,j,2) ) ^ ff_mul(0x0e, P(v,j,3) );
3768 }
3769 *v = r;
3770#undef P
3771
3772}
3773
3774/* For description, see definition in guest_amd64_defs.h */
3775void amd64g_dirtyhelper_AES (
3776 VexGuestAMD64State* gst,
sewardj1407a362012-06-24 15:11:38 +00003777 HWord opc4, HWord gstOffD,
philippeff4d6be2012-02-14 21:34:56 +00003778 HWord gstOffL, HWord gstOffR
3779 )
3780{
3781 // where the args are
sewardj1407a362012-06-24 15:11:38 +00003782 V128* argD = (V128*)( ((UChar*)gst) + gstOffD );
philippeff4d6be2012-02-14 21:34:56 +00003783 V128* argL = (V128*)( ((UChar*)gst) + gstOffL );
3784 V128* argR = (V128*)( ((UChar*)gst) + gstOffR );
sewardj1407a362012-06-24 15:11:38 +00003785 V128 r;
philippeff4d6be2012-02-14 21:34:56 +00003786
3787 switch (opc4) {
3788 case 0xDC: /* AESENC */
3789 case 0xDD: /* AESENCLAST */
sewardj1407a362012-06-24 15:11:38 +00003790 r = *argR;
3791 ShiftRows (&r);
3792 SubBytes (&r);
philippeff4d6be2012-02-14 21:34:56 +00003793 if (opc4 == 0xDC)
sewardj1407a362012-06-24 15:11:38 +00003794 MixColumns (&r);
3795 argD->w64[0] = r.w64[0] ^ argL->w64[0];
3796 argD->w64[1] = r.w64[1] ^ argL->w64[1];
philippeff4d6be2012-02-14 21:34:56 +00003797 break;
3798
3799 case 0xDE: /* AESDEC */
3800 case 0xDF: /* AESDECLAST */
sewardj1407a362012-06-24 15:11:38 +00003801 r = *argR;
3802 InvShiftRows (&r);
3803 InvSubBytes (&r);
philippeff4d6be2012-02-14 21:34:56 +00003804 if (opc4 == 0xDE)
sewardj1407a362012-06-24 15:11:38 +00003805 InvMixColumns (&r);
3806 argD->w64[0] = r.w64[0] ^ argL->w64[0];
3807 argD->w64[1] = r.w64[1] ^ argL->w64[1];
philippeff4d6be2012-02-14 21:34:56 +00003808 break;
3809
3810 case 0xDB: /* AESIMC */
sewardj1407a362012-06-24 15:11:38 +00003811 *argD = *argL;
3812 InvMixColumns (argD);
philippeff4d6be2012-02-14 21:34:56 +00003813 break;
3814 default: vassert(0);
3815 }
3816}
3817
3818static inline UInt RotWord (UInt w32)
3819{
3820 return ((w32 >> 8) | (w32 << 24));
3821}
3822
3823static inline UInt SubWord (UInt w32)
3824{
3825 UChar *w8;
3826 UChar *r8;
3827 UInt res;
3828 w8 = (UChar*) &w32;
3829 r8 = (UChar*) &res;
3830 r8[0] = sbox[w8[0]];
3831 r8[1] = sbox[w8[1]];
3832 r8[2] = sbox[w8[2]];
3833 r8[3] = sbox[w8[3]];
3834 return res;
3835}
3836
3837/* For description, see definition in guest_amd64_defs.h */
3838extern void amd64g_dirtyhelper_AESKEYGENASSIST (
3839 VexGuestAMD64State* gst,
3840 HWord imm8,
3841 HWord gstOffL, HWord gstOffR
3842 )
3843{
3844 // where the args are
3845 V128* argL = (V128*)( ((UChar*)gst) + gstOffL );
3846 V128* argR = (V128*)( ((UChar*)gst) + gstOffR );
3847
3848 argR->w32[3] = RotWord (SubWord (argL->w32[3])) ^ imm8;
3849 argR->w32[2] = SubWord (argL->w32[3]);
3850 argR->w32[1] = RotWord (SubWord (argL->w32[1])) ^ imm8;
3851 argR->w32[0] = SubWord (argL->w32[1]);
3852}
3853
3854
sewardj0b2d3fe2010-08-06 07:59:38 +00003855
3856/*---------------------------------------------------------------*/
sewardjf8c37f72005-02-07 18:55:29 +00003857/*--- Helpers for dealing with, and describing, ---*/
3858/*--- guest state as a whole. ---*/
3859/*---------------------------------------------------------------*/
3860
3861/* Initialise the entire amd64 guest state. */
3862/* VISIBLE TO LIBVEX CLIENT */
3863void LibVEX_GuestAMD64_initialise ( /*OUT*/VexGuestAMD64State* vex_state )
3864{
sewardjc6f970f2012-04-02 21:54:49 +00003865 vex_state->host_EvC_FAILADDR = 0;
3866 vex_state->host_EvC_COUNTER = 0;
3867 vex_state->pad0 = 0;
3868
sewardjf8c37f72005-02-07 18:55:29 +00003869 vex_state->guest_RAX = 0;
3870 vex_state->guest_RCX = 0;
3871 vex_state->guest_RDX = 0;
3872 vex_state->guest_RBX = 0;
3873 vex_state->guest_RSP = 0;
3874 vex_state->guest_RBP = 0;
3875 vex_state->guest_RSI = 0;
3876 vex_state->guest_RDI = 0;
3877 vex_state->guest_R8 = 0;
3878 vex_state->guest_R9 = 0;
3879 vex_state->guest_R10 = 0;
3880 vex_state->guest_R11 = 0;
3881 vex_state->guest_R12 = 0;
3882 vex_state->guest_R13 = 0;
3883 vex_state->guest_R14 = 0;
3884 vex_state->guest_R15 = 0;
3885
3886 vex_state->guest_CC_OP = AMD64G_CC_OP_COPY;
3887 vex_state->guest_CC_DEP1 = 0;
3888 vex_state->guest_CC_DEP2 = 0;
3889 vex_state->guest_CC_NDEP = 0;
3890
sewardjd0a12df2005-02-10 02:07:43 +00003891 vex_state->guest_DFLAG = 1; /* forwards */
sewardj85520e42005-02-19 15:22:38 +00003892 vex_state->guest_IDFLAG = 0;
sewardj0e457fc2013-12-11 16:47:59 +00003893 vex_state->guest_ACFLAG = 0;
sewardjf8c37f72005-02-07 18:55:29 +00003894
sewardjcb6091d2005-02-21 08:23:39 +00003895 /* HACK: represent the offset associated with %fs==0. This
3896 assumes that %fs is only ever zero. */
sewardja6b93d12005-02-17 09:28:28 +00003897 vex_state->guest_FS_ZERO = 0;
3898
sewardjf8c37f72005-02-07 18:55:29 +00003899 vex_state->guest_RIP = 0;
3900
sewardj8d965312005-02-25 02:48:47 +00003901 /* Initialise the simulated FPU */
3902 amd64g_dirtyhelper_FINIT( vex_state );
3903
sewardjc4530ae2012-05-21 10:18:49 +00003904 /* Initialise the AVX state. */
3905# define AVXZERO(_ymm) \
3906 do { _ymm[0]=_ymm[1]=_ymm[2]=_ymm[3] = 0; \
3907 _ymm[4]=_ymm[5]=_ymm[6]=_ymm[7] = 0; \
3908 } while (0)
sewardjcb6091d2005-02-21 08:23:39 +00003909 vex_state->guest_SSEROUND = (ULong)Irrm_NEAREST;
sewardjc4530ae2012-05-21 10:18:49 +00003910 AVXZERO(vex_state->guest_YMM0);
3911 AVXZERO(vex_state->guest_YMM1);
3912 AVXZERO(vex_state->guest_YMM2);
3913 AVXZERO(vex_state->guest_YMM3);
3914 AVXZERO(vex_state->guest_YMM4);
3915 AVXZERO(vex_state->guest_YMM5);
3916 AVXZERO(vex_state->guest_YMM6);
3917 AVXZERO(vex_state->guest_YMM7);
3918 AVXZERO(vex_state->guest_YMM8);
3919 AVXZERO(vex_state->guest_YMM9);
3920 AVXZERO(vex_state->guest_YMM10);
3921 AVXZERO(vex_state->guest_YMM11);
3922 AVXZERO(vex_state->guest_YMM12);
3923 AVXZERO(vex_state->guest_YMM13);
3924 AVXZERO(vex_state->guest_YMM14);
3925 AVXZERO(vex_state->guest_YMM15);
3926 AVXZERO(vex_state->guest_YMM16);
sewardjcb6091d2005-02-21 08:23:39 +00003927
sewardjc4530ae2012-05-21 10:18:49 +00003928# undef AVXZERO
sewardjf8c37f72005-02-07 18:55:29 +00003929
florian6ef84be2012-08-26 03:20:07 +00003930 vex_state->guest_EMNOTE = EmNote_NONE;
sewardj1f126c52005-03-16 13:57:58 +00003931
3932 /* These should not ever be either read or written, but we
3933 initialise them anyway. */
sewardj05f5e012014-05-04 10:52:11 +00003934 vex_state->guest_CMSTART = 0;
3935 vex_state->guest_CMLEN = 0;
sewardjce02aa72006-01-12 12:27:58 +00003936
sewardjd660d412008-12-03 21:29:59 +00003937 vex_state->guest_NRADDR = 0;
3938 vex_state->guest_SC_CLASS = 0;
3939 vex_state->guest_GS_0x60 = 0;
3940
sewardje86310f2009-03-19 22:21:40 +00003941 vex_state->guest_IP_AT_SYSCALL = 0;
sewardjc6f970f2012-04-02 21:54:49 +00003942 vex_state->pad1 = 0;
sewardjf8c37f72005-02-07 18:55:29 +00003943}
3944
3945
sewardj2f959cc2005-01-26 01:19:35 +00003946/* Figure out if any part of the guest state contained in minoff
3947 .. maxoff requires precise memory exceptions. If in doubt return
philippe6c46bef2012-08-14 22:29:01 +00003948 True (but this generates significantly slower code).
sewardj2f959cc2005-01-26 01:19:35 +00003949
sewardj4cca75c2005-03-16 11:52:25 +00003950 By default we enforce precise exns for guest %RSP, %RBP and %RIP
3951 only. These are the minimum needed to extract correct stack
3952 backtraces from amd64 code.
philippe6c46bef2012-08-14 22:29:01 +00003953
3954 Only %RSP is needed in mode VexRegUpdSpAtMemAccess.
sewardj2f959cc2005-01-26 01:19:35 +00003955*/
sewardj44d494d2005-01-20 20:26:33 +00003956Bool guest_amd64_state_requires_precise_mem_exns ( Int minoff,
3957 Int maxoff)
3958{
sewardj4cca75c2005-03-16 11:52:25 +00003959 Int rbp_min = offsetof(VexGuestAMD64State, guest_RBP);
3960 Int rbp_max = rbp_min + 8 - 1;
sewardj2f959cc2005-01-26 01:19:35 +00003961 Int rsp_min = offsetof(VexGuestAMD64State, guest_RSP);
3962 Int rsp_max = rsp_min + 8 - 1;
3963 Int rip_min = offsetof(VexGuestAMD64State, guest_RIP);
3964 Int rip_max = rip_min + 8 - 1;
3965
philippe6c46bef2012-08-14 22:29:01 +00003966 if (maxoff < rsp_min || minoff > rsp_max) {
3967 /* no overlap with rsp */
3968 if (vex_control.iropt_register_updates == VexRegUpdSpAtMemAccess)
3969 return False; // We only need to check stack pointer.
sewardj4cca75c2005-03-16 11:52:25 +00003970 } else {
3971 return True;
3972 }
3973
philippe6c46bef2012-08-14 22:29:01 +00003974 if (maxoff < rbp_min || minoff > rbp_max) {
3975 /* no overlap with rbp */
sewardj2f959cc2005-01-26 01:19:35 +00003976 } else {
3977 return True;
3978 }
3979
3980 if (maxoff < rip_min || minoff > rip_max) {
3981 /* no overlap with eip */
3982 } else {
3983 return True;
3984 }
3985
3986 return False;
sewardj44d494d2005-01-20 20:26:33 +00003987}
sewardj2f959cc2005-01-26 01:19:35 +00003988
3989
sewardjc85e91c2005-02-07 14:59:28 +00003990#define ALWAYSDEFD(field) \
3991 { offsetof(VexGuestAMD64State, field), \
3992 (sizeof ((VexGuestAMD64State*)0)->field) }
sewardj44d494d2005-01-20 20:26:33 +00003993
3994VexGuestLayout
sewardjc85e91c2005-02-07 14:59:28 +00003995 amd64guest_layout
sewardj44d494d2005-01-20 20:26:33 +00003996 = {
3997 /* Total size of the guest state, in bytes. */
sewardjc85e91c2005-02-07 14:59:28 +00003998 .total_sizeB = sizeof(VexGuestAMD64State),
sewardj44d494d2005-01-20 20:26:33 +00003999
4000 /* Describe the stack pointer. */
sewardjc85e91c2005-02-07 14:59:28 +00004001 .offset_SP = offsetof(VexGuestAMD64State,guest_RSP),
4002 .sizeof_SP = 8,
sewardj44d494d2005-01-20 20:26:33 +00004003
sewardja2033302008-08-19 11:15:10 +00004004 /* Describe the frame pointer. */
4005 .offset_FP = offsetof(VexGuestAMD64State,guest_RBP),
4006 .sizeof_FP = 8,
4007
sewardj44d494d2005-01-20 20:26:33 +00004008 /* Describe the instruction pointer. */
sewardjc85e91c2005-02-07 14:59:28 +00004009 .offset_IP = offsetof(VexGuestAMD64State,guest_RIP),
4010 .sizeof_IP = 8,
sewardj44d494d2005-01-20 20:26:33 +00004011
4012 /* Describe any sections to be regarded by Memcheck as
4013 'always-defined'. */
sewardje86310f2009-03-19 22:21:40 +00004014 .n_alwaysDefd = 16,
sewardj44d494d2005-01-20 20:26:33 +00004015
4016 /* flags thunk: OP and NDEP are always defd, whereas DEP1
4017 and DEP2 have to be tracked. See detailed comment in
4018 gdefs.h on meaning of thunk fields. */
4019 .alwaysDefd
4020 = { /* 0 */ ALWAYSDEFD(guest_CC_OP),
4021 /* 1 */ ALWAYSDEFD(guest_CC_NDEP),
sewardj85520e42005-02-19 15:22:38 +00004022 /* 2 */ ALWAYSDEFD(guest_DFLAG),
4023 /* 3 */ ALWAYSDEFD(guest_IDFLAG),
4024 /* 4 */ ALWAYSDEFD(guest_RIP),
4025 /* 5 */ ALWAYSDEFD(guest_FS_ZERO),
sewardj8d965312005-02-25 02:48:47 +00004026 /* 6 */ ALWAYSDEFD(guest_FTOP),
4027 /* 7 */ ALWAYSDEFD(guest_FPTAG),
4028 /* 8 */ ALWAYSDEFD(guest_FPROUND),
4029 /* 9 */ ALWAYSDEFD(guest_FC3210),
sewardj85520e42005-02-19 15:22:38 +00004030 // /* */ ALWAYSDEFD(guest_CS),
4031 // /* */ ALWAYSDEFD(guest_DS),
4032 // /* */ ALWAYSDEFD(guest_ES),
4033 // /* */ ALWAYSDEFD(guest_FS),
4034 // /* */ ALWAYSDEFD(guest_GS),
4035 // /* */ ALWAYSDEFD(guest_SS),
4036 // /* */ ALWAYSDEFD(guest_LDT),
4037 // /* */ ALWAYSDEFD(guest_GDT),
florian6ef84be2012-08-26 03:20:07 +00004038 /* 10 */ ALWAYSDEFD(guest_EMNOTE),
sewardj16a403b2005-07-07 12:26:36 +00004039 /* 11 */ ALWAYSDEFD(guest_SSEROUND),
sewardj05f5e012014-05-04 10:52:11 +00004040 /* 12 */ ALWAYSDEFD(guest_CMSTART),
4041 /* 13 */ ALWAYSDEFD(guest_CMLEN),
sewardje86310f2009-03-19 22:21:40 +00004042 /* 14 */ ALWAYSDEFD(guest_SC_CLASS),
4043 /* 15 */ ALWAYSDEFD(guest_IP_AT_SYSCALL)
sewardj44d494d2005-01-20 20:26:33 +00004044 }
4045 };
njn9c6acb02004-11-30 15:56:47 +00004046
4047
njn9c6acb02004-11-30 15:56:47 +00004048/*---------------------------------------------------------------*/
sewardjcef7d3e2009-07-02 12:21:59 +00004049/*--- end guest_amd64_helpers.c ---*/
njn9c6acb02004-11-30 15:56:47 +00004050/*---------------------------------------------------------------*/