]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/valgrind/src/valgrind-3.6.0-svn/VEX/priv/guest_amd64_toIR.c
1fa1ed429b7390071f824381154173640e8c218f
[l4.git] / l4 / pkg / valgrind / src / valgrind-3.6.0-svn / VEX / priv / guest_amd64_toIR.c
1
2 /*--------------------------------------------------------------------*/
3 /*--- begin                                     guest_amd64_toIR.c ---*/
4 /*--------------------------------------------------------------------*/
5
6 /*
7    This file is part of Valgrind, a dynamic binary instrumentation
8    framework.
9
10    Copyright (C) 2004-2010 OpenWorks LLP
11       info@open-works.net
12
13    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.
17
18    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
26    02110-1301, USA.
27
28    The GNU General Public License is contained in the file COPYING.
29
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.
34 */
35
36 /* Translates AMD64 code to IR. */
37
38 /* TODO:
39
40    All Puts to CC_OP/CC_DEP1/CC_DEP2/CC_NDEP should really be checked
41    to ensure a 64-bit value is being written.
42
43    x87 FP Limitations:
44  
45    * all arithmetic done at 64 bits
46  
47    * no FP exceptions, except for handling stack over/underflow
48  
49    * FP rounding mode observed only for float->int conversions and
50      int->float conversions which could lose accuracy, and for
51      float-to-float rounding.  For all other operations,
52      round-to-nearest is used, regardless.
53  
54    * FP sin/cos/tan/sincos: C2 flag is always cleared.  IOW the
55      simulation claims the argument is in-range (-2^63 <= arg <= 2^63)
56      even when it isn't.
57  
58    * some of the FCOM cases could do with testing -- not convinced
59      that the args are the right way round.
60  
61    * FSAVE does not re-initialise the FPU; it should do
62  
63    * FINIT not only initialises the FPU environment, it also zeroes
64      all the FP registers.  It should leave the registers unchanged.
65  
66     RDTSC returns zero, always.
67  
68     SAHF should cause eflags[1] == 1, and in fact it produces 0.  As
69     per Intel docs this bit has no meaning anyway.  Since PUSHF is the
70     only way to observe eflags[1], a proper fix would be to make that
71     bit be set by PUSHF.
72  
73     This module uses global variables and so is not MT-safe (if that
74     should ever become relevant).
75 */
76
77 /* Notes re address size overrides (0x67).
78
79    According to the AMD documentation (24594 Rev 3.09, Sept 2003,
80    "AMD64 Architecture Programmer's Manual Volume 3: General-Purpose
81    and System Instructions"), Section 1.2.3 ("Address-Size Override
82    Prefix"):
83
84    0x67 applies to all explicit memory references, causing the top
85    32 bits of the effective address to become zero.
86
87    0x67 has no effect on stack references (push/pop); these always
88    use a 64-bit address.
89
90    0x67 changes the interpretation of instructions which implicitly
91    reference RCX/RSI/RDI, so that in fact ECX/ESI/EDI are used
92    instead.  These are:
93
94       cmp{s,sb,sw,sd,sq}
95       in{s,sb,sw,sd}
96       jcxz, jecxz, jrcxz
97       lod{s,sb,sw,sd,sq}
98       loop{,e,bz,be,z}
99       mov{s,sb,sw,sd,sq}
100       out{s,sb,sw,sd}
101       rep{,e,ne,nz}
102       sca{s,sb,sw,sd,sq}
103       sto{s,sb,sw,sd,sq}
104       xlat{,b} */
105
106 /* "Special" instructions.
107
108    This instruction decoder can decode three special instructions
109    which mean nothing natively (are no-ops as far as regs/mem are
110    concerned) but have meaning for supporting Valgrind.  A special
111    instruction is flagged by the 16-byte preamble 48C1C703 48C1C70D
112    48C1C73D 48C1C733 (in the standard interpretation, that means: rolq
113    $3, %rdi; rolq $13, %rdi; rolq $61, %rdi; rolq $51, %rdi).
114    Following that, one of the following 3 are allowed (standard
115    interpretation in parentheses):
116
117       4887DB (xchgq %rbx,%rbx)   %RDX = client_request ( %RAX )
118       4887C9 (xchgq %rcx,%rcx)   %RAX = guest_NRADDR
119       4887D2 (xchgq %rdx,%rdx)   call-noredir *%RAX
120
121    Any other bytes following the 16-byte preamble are illegal and
122    constitute a failure in instruction decoding.  This all assumes
123    that the preamble will never occur except in specific code
124    fragments designed for Valgrind to catch.
125
126    No prefixes may precede a "Special" instruction.
127 */
128
129 /* casLE (implementation of lock-prefixed insns) and rep-prefixed
130    insns: the side-exit back to the start of the insn is done with
131    Ijk_Boring.  This is quite wrong, it should be done with
132    Ijk_NoRedir, since otherwise the side exit, which is intended to
133    restart the instruction for whatever reason, could go somewhere
134    entirely else.  Doing it right (with Ijk_NoRedir jumps) would make
135    no-redir jumps performance critical, at least for rep-prefixed
136    instructions, since all iterations thereof would involve such a
137    jump.  It's not such a big deal with casLE since the side exit is
138    only taken if the CAS fails, that is, the location is contended,
139    which is relatively unlikely.
140
141    Note also, the test for CAS success vs failure is done using
142    Iop_CasCmp{EQ,NE}{8,16,32,64} rather than the ordinary
143    Iop_Cmp{EQ,NE} equivalents.  This is so as to tell Memcheck that it
144    shouldn't definedness-check these comparisons.  See
145    COMMENT_ON_CasCmpEQ in memcheck/mc_translate.c for
146    background/rationale.
147 */
148
149 /* LOCK prefixed instructions.  These are translated using IR-level
150    CAS statements (IRCAS) and are believed to preserve atomicity, even
151    from the point of view of some other process racing against a
152    simulated one (presumably they communicate via a shared memory
153    segment).
154
155    Handlers which are aware of LOCK prefixes are:
156       dis_op2_G_E      (add, or, adc, sbb, and, sub, xor)
157       dis_cmpxchg_G_E  (cmpxchg)
158       dis_Grp1         (add, or, adc, sbb, and, sub, xor)
159       dis_Grp3         (not, neg)
160       dis_Grp4         (inc, dec)
161       dis_Grp5         (inc, dec)
162       dis_Grp8_Imm     (bts, btc, btr)
163       dis_bt_G_E       (bts, btc, btr)
164       dis_xadd_G_E     (xadd)
165 */
166
167
168 #include "libvex_basictypes.h"
169 #include "libvex_ir.h"
170 #include "libvex.h"
171 #include "libvex_guest_amd64.h"
172
173 #include "main_util.h"
174 #include "main_globals.h"
175 #include "guest_generic_bb_to_IR.h"
176 #include "guest_generic_x87.h"
177 #include "guest_amd64_defs.h"
178
179
180 /*------------------------------------------------------------*/
181 /*--- Globals                                              ---*/
182 /*------------------------------------------------------------*/
183
184 /* These are set at the start of the translation of an insn, right
185    down in disInstr_AMD64, so that we don't have to pass them around
186    endlessly.  They are all constant during the translation of any
187    given insn. */
188
189 /* These are set at the start of the translation of a BB, so
190    that we don't have to pass them around endlessly. */
191
192 /* We need to know this to do sub-register accesses correctly. */
193 static Bool host_is_bigendian;
194
195 /* Pointer to the guest code area (points to start of BB, not to the
196    insn being processed). */
197 static UChar* guest_code;
198
199 /* The guest address corresponding to guest_code[0]. */
200 static Addr64 guest_RIP_bbstart;
201
202 /* The guest address for the instruction currently being
203    translated. */
204 static Addr64 guest_RIP_curr_instr;
205
206 /* The IRSB* into which we're generating code. */
207 static IRSB* irsb;
208
209 /* For ensuring that %rip-relative addressing is done right.  A read
210    of %rip generates the address of the next instruction.  It may be
211    that we don't conveniently know that inside disAMode().  For sanity
212    checking, if the next insn %rip is needed, we make a guess at what
213    it is, record that guess here, and set the accompanying Bool to
214    indicate that -- after this insn's decode is finished -- that guess
215    needs to be checked.  */
216
217 /* At the start of each insn decode, is set to (0, False).
218    After the decode, if _mustcheck is now True, _assumed is
219    checked. */
220
221 static Addr64 guest_RIP_next_assumed;
222 static Bool   guest_RIP_next_mustcheck;
223
224
225 /*------------------------------------------------------------*/
226 /*--- Helpers for constructing IR.                         ---*/
227 /*------------------------------------------------------------*/
228  
229 /* Generate a new temporary of the given type. */
230 static IRTemp newTemp ( IRType ty )
231 {
232    vassert(isPlausibleIRType(ty));
233    return newIRTemp( irsb->tyenv, ty );
234 }
235
236 /* Add a statement to the list held by "irsb". */
237 static void stmt ( IRStmt* st )
238 {
239    addStmtToIRSB( irsb, st );
240 }
241
242 /* Generate a statement "dst := e". */ 
243 static void assign ( IRTemp dst, IRExpr* e )
244 {
245    stmt( IRStmt_WrTmp(dst, e) );
246 }
247
248 static IRExpr* unop ( IROp op, IRExpr* a )
249 {
250    return IRExpr_Unop(op, a);
251 }
252
253 static IRExpr* binop ( IROp op, IRExpr* a1, IRExpr* a2 )
254 {
255    return IRExpr_Binop(op, a1, a2);
256 }
257
258 static IRExpr* triop ( IROp op, IRExpr* a1, IRExpr* a2, IRExpr* a3 )
259 {
260    return IRExpr_Triop(op, a1, a2, a3);
261 }
262
263 static IRExpr* mkexpr ( IRTemp tmp )
264 {
265    return IRExpr_RdTmp(tmp);
266 }
267
268 static IRExpr* mkU8 ( ULong i )
269 {
270    vassert(i < 256);
271    return IRExpr_Const(IRConst_U8( (UChar)i ));
272 }
273
274 static IRExpr* mkU16 ( ULong i )
275 {
276    vassert(i < 0x10000ULL);
277    return IRExpr_Const(IRConst_U16( (UShort)i ));
278 }
279
280 static IRExpr* mkU32 ( ULong i )
281 {
282    vassert(i < 0x100000000ULL);
283    return IRExpr_Const(IRConst_U32( (UInt)i ));
284 }
285
286 static IRExpr* mkU64 ( ULong i )
287 {
288    return IRExpr_Const(IRConst_U64(i));
289 }
290
291 static IRExpr* mkU ( IRType ty, ULong i )
292 {
293    switch (ty) {
294       case Ity_I8:  return mkU8(i);
295       case Ity_I16: return mkU16(i);
296       case Ity_I32: return mkU32(i);
297       case Ity_I64: return mkU64(i);
298       default: vpanic("mkU(amd64)");
299    }
300 }
301
302 static void storeLE ( IRExpr* addr, IRExpr* data )
303 {
304    stmt( IRStmt_Store(Iend_LE, addr, data) );
305 }
306
307 static IRExpr* loadLE ( IRType ty, IRExpr* addr )
308 {
309    return IRExpr_Load(Iend_LE, ty, addr);
310 }
311
312 static IROp mkSizedOp ( IRType ty, IROp op8 )
313 {
314    vassert(op8 == Iop_Add8 || op8 == Iop_Sub8 
315            || op8 == Iop_Mul8 
316            || op8 == Iop_Or8 || op8 == Iop_And8 || op8 == Iop_Xor8
317            || op8 == Iop_Shl8 || op8 == Iop_Shr8 || op8 == Iop_Sar8
318            || op8 == Iop_CmpEQ8 || op8 == Iop_CmpNE8
319            || op8 == Iop_CasCmpNE8
320            || op8 == Iop_Not8 );
321    switch (ty) {
322       case Ity_I8:  return 0 +op8;
323       case Ity_I16: return 1 +op8;
324       case Ity_I32: return 2 +op8;
325       case Ity_I64: return 3 +op8;
326       default: vpanic("mkSizedOp(amd64)");
327    }
328 }
329
330 static 
331 IRExpr* doScalarWidening ( Int szSmall, Int szBig, Bool signd, IRExpr* src )
332 {
333    if (szSmall == 1 && szBig == 4) {
334       return unop(signd ? Iop_8Sto32 : Iop_8Uto32, src);
335    }
336    if (szSmall == 1 && szBig == 2) {
337       return unop(signd ? Iop_8Sto16 : Iop_8Uto16, src);
338    }
339    if (szSmall == 2 && szBig == 4) {
340       return unop(signd ? Iop_16Sto32 : Iop_16Uto32, src);
341    }
342    if (szSmall == 1 && szBig == 8 && !signd) {
343       return unop(Iop_8Uto64, src);
344    }
345    if (szSmall == 1 && szBig == 8 && signd) {
346       return unop(Iop_8Sto64, src);
347    }
348    if (szSmall == 2 && szBig == 8 && !signd) {
349       return unop(Iop_16Uto64, src);
350    }
351    if (szSmall == 2 && szBig == 8 && signd) {
352       return unop(Iop_16Sto64, src);
353    }
354    vpanic("doScalarWidening(amd64)");
355 }
356
357
358
359 /*------------------------------------------------------------*/
360 /*--- Debugging output                                     ---*/
361 /*------------------------------------------------------------*/
362
363 /* Bomb out if we can't handle something. */
364 __attribute__ ((noreturn))
365 static void unimplemented ( HChar* str )
366 {
367    vex_printf("amd64toIR: unimplemented feature\n");
368    vpanic(str);
369 }
370
371 #define DIP(format, args...)           \
372    if (vex_traceflags & VEX_TRACE_FE)  \
373       vex_printf(format, ## args)
374
375 #define DIS(buf, format, args...)      \
376    if (vex_traceflags & VEX_TRACE_FE)  \
377       vex_sprintf(buf, format, ## args)
378
379
380 /*------------------------------------------------------------*/
381 /*--- Offsets of various parts of the amd64 guest state.   ---*/
382 /*------------------------------------------------------------*/
383
384 #define OFFB_RAX       offsetof(VexGuestAMD64State,guest_RAX)
385 #define OFFB_RBX       offsetof(VexGuestAMD64State,guest_RBX)
386 #define OFFB_RCX       offsetof(VexGuestAMD64State,guest_RCX)
387 #define OFFB_RDX       offsetof(VexGuestAMD64State,guest_RDX)
388 #define OFFB_RSP       offsetof(VexGuestAMD64State,guest_RSP)
389 #define OFFB_RBP       offsetof(VexGuestAMD64State,guest_RBP)
390 #define OFFB_RSI       offsetof(VexGuestAMD64State,guest_RSI)
391 #define OFFB_RDI       offsetof(VexGuestAMD64State,guest_RDI)
392 #define OFFB_R8        offsetof(VexGuestAMD64State,guest_R8)
393 #define OFFB_R9        offsetof(VexGuestAMD64State,guest_R9)
394 #define OFFB_R10       offsetof(VexGuestAMD64State,guest_R10)
395 #define OFFB_R11       offsetof(VexGuestAMD64State,guest_R11)
396 #define OFFB_R12       offsetof(VexGuestAMD64State,guest_R12)
397 #define OFFB_R13       offsetof(VexGuestAMD64State,guest_R13)
398 #define OFFB_R14       offsetof(VexGuestAMD64State,guest_R14)
399 #define OFFB_R15       offsetof(VexGuestAMD64State,guest_R15)
400
401 #define OFFB_RIP       offsetof(VexGuestAMD64State,guest_RIP)
402
403 #define OFFB_FS_ZERO   offsetof(VexGuestAMD64State,guest_FS_ZERO)
404 #define OFFB_GS_0x60   offsetof(VexGuestAMD64State,guest_GS_0x60)
405
406 #define OFFB_CC_OP     offsetof(VexGuestAMD64State,guest_CC_OP)
407 #define OFFB_CC_DEP1   offsetof(VexGuestAMD64State,guest_CC_DEP1)
408 #define OFFB_CC_DEP2   offsetof(VexGuestAMD64State,guest_CC_DEP2)
409 #define OFFB_CC_NDEP   offsetof(VexGuestAMD64State,guest_CC_NDEP)
410
411 #define OFFB_FPREGS    offsetof(VexGuestAMD64State,guest_FPREG[0])
412 #define OFFB_FPTAGS    offsetof(VexGuestAMD64State,guest_FPTAG[0])
413 #define OFFB_DFLAG     offsetof(VexGuestAMD64State,guest_DFLAG)
414 #define OFFB_IDFLAG    offsetof(VexGuestAMD64State,guest_IDFLAG)
415 #define OFFB_FTOP      offsetof(VexGuestAMD64State,guest_FTOP)
416 #define OFFB_FC3210    offsetof(VexGuestAMD64State,guest_FC3210)
417 #define OFFB_FPROUND   offsetof(VexGuestAMD64State,guest_FPROUND)
418 //.. 
419 //.. #define OFFB_CS        offsetof(VexGuestX86State,guest_CS)
420 //.. #define OFFB_DS        offsetof(VexGuestX86State,guest_DS)
421 //.. #define OFFB_ES        offsetof(VexGuestX86State,guest_ES)
422 //.. #define OFFB_FS        offsetof(VexGuestX86State,guest_FS)
423 //.. #define OFFB_GS        offsetof(VexGuestX86State,guest_GS)
424 //.. #define OFFB_SS        offsetof(VexGuestX86State,guest_SS)
425 //.. #define OFFB_LDT       offsetof(VexGuestX86State,guest_LDT)
426 //.. #define OFFB_GDT       offsetof(VexGuestX86State,guest_GDT)
427
428 #define OFFB_SSEROUND  offsetof(VexGuestAMD64State,guest_SSEROUND)
429 #define OFFB_XMM0      offsetof(VexGuestAMD64State,guest_XMM0)
430 #define OFFB_XMM1      offsetof(VexGuestAMD64State,guest_XMM1)
431 #define OFFB_XMM2      offsetof(VexGuestAMD64State,guest_XMM2)
432 #define OFFB_XMM3      offsetof(VexGuestAMD64State,guest_XMM3)
433 #define OFFB_XMM4      offsetof(VexGuestAMD64State,guest_XMM4)
434 #define OFFB_XMM5      offsetof(VexGuestAMD64State,guest_XMM5)
435 #define OFFB_XMM6      offsetof(VexGuestAMD64State,guest_XMM6)
436 #define OFFB_XMM7      offsetof(VexGuestAMD64State,guest_XMM7)
437 #define OFFB_XMM8      offsetof(VexGuestAMD64State,guest_XMM8)
438 #define OFFB_XMM9      offsetof(VexGuestAMD64State,guest_XMM9)
439 #define OFFB_XMM10     offsetof(VexGuestAMD64State,guest_XMM10)
440 #define OFFB_XMM11     offsetof(VexGuestAMD64State,guest_XMM11)
441 #define OFFB_XMM12     offsetof(VexGuestAMD64State,guest_XMM12)
442 #define OFFB_XMM13     offsetof(VexGuestAMD64State,guest_XMM13)
443 #define OFFB_XMM14     offsetof(VexGuestAMD64State,guest_XMM14)
444 #define OFFB_XMM15     offsetof(VexGuestAMD64State,guest_XMM15)
445
446 #define OFFB_EMWARN    offsetof(VexGuestAMD64State,guest_EMWARN)
447 #define OFFB_TISTART   offsetof(VexGuestAMD64State,guest_TISTART)
448 #define OFFB_TILEN     offsetof(VexGuestAMD64State,guest_TILEN)
449
450 #define OFFB_NRADDR    offsetof(VexGuestAMD64State,guest_NRADDR)
451
452
453 /*------------------------------------------------------------*/
454 /*--- Helper bits and pieces for deconstructing the        ---*/
455 /*--- amd64 insn stream.                                   ---*/
456 /*------------------------------------------------------------*/
457
458 /* This is the AMD64 register encoding -- integer regs. */
459 #define R_RAX 0
460 #define R_RCX 1
461 #define R_RDX 2
462 #define R_RBX 3
463 #define R_RSP 4
464 #define R_RBP 5
465 #define R_RSI 6
466 #define R_RDI 7
467 #define R_R8  8
468 #define R_R9  9
469 #define R_R10 10
470 #define R_R11 11
471 #define R_R12 12
472 #define R_R13 13
473 #define R_R14 14
474 #define R_R15 15
475
476 //.. #define R_AL (0+R_EAX)
477 //.. #define R_AH (4+R_EAX)
478
479 /* This is the Intel register encoding -- segment regs. */
480 #define R_ES 0
481 #define R_CS 1
482 #define R_SS 2
483 #define R_DS 3
484 #define R_FS 4
485 #define R_GS 5
486
487
488 /* Various simple conversions */
489
490 static ULong extend_s_8to64 ( UChar x )
491 {
492    return (ULong)((((Long)x) << 56) >> 56);
493 }
494
495 static ULong extend_s_16to64 ( UShort x )
496 {
497    return (ULong)((((Long)x) << 48) >> 48);
498 }
499
500 static ULong extend_s_32to64 ( UInt x )
501 {
502    return (ULong)((((Long)x) << 32) >> 32);
503 }
504
505 /* Figure out whether the mod and rm parts of a modRM byte refer to a
506    register or memory.  If so, the byte will have the form 11XXXYYY,
507    where YYY is the register number. */
508 inline
509 static Bool epartIsReg ( UChar mod_reg_rm )
510 {
511    return toBool(0xC0 == (mod_reg_rm & 0xC0));
512 }
513
514 /* Extract the 'g' field from a modRM byte.  This only produces 3
515    bits, which is not a complete register number.  You should avoid
516    this function if at all possible. */
517 inline
518 static Int gregLO3ofRM ( UChar mod_reg_rm )
519 {
520    return (Int)( (mod_reg_rm >> 3) & 7 );
521 }
522
523 /* Ditto the 'e' field of a modRM byte. */
524 inline
525 static Int eregLO3ofRM ( UChar mod_reg_rm )
526 {
527    return (Int)(mod_reg_rm & 0x7);
528 }
529
530 /* Get a 8/16/32-bit unsigned value out of the insn stream. */
531
532 static UChar getUChar ( Long delta )
533 {
534    UChar v = guest_code[delta+0];
535    return v;
536 }
537
538 static UInt getUDisp16 ( Long delta )
539 {
540    UInt v = guest_code[delta+1]; v <<= 8;
541    v |= guest_code[delta+0];
542    return v & 0xFFFF;
543 }
544
545 //.. static UInt getUDisp ( Int size, Long delta )
546 //.. {
547 //..    switch (size) {
548 //..       case 4: return getUDisp32(delta);
549 //..       case 2: return getUDisp16(delta);
550 //..       case 1: return getUChar(delta);
551 //..       default: vpanic("getUDisp(x86)");
552 //..    }
553 //..    return 0; /*notreached*/
554 //.. }
555
556
557 /* Get a byte value out of the insn stream and sign-extend to 64
558    bits. */
559 static Long getSDisp8 ( Long delta )
560 {
561    return extend_s_8to64( guest_code[delta] );
562 }
563
564 /* Get a 16-bit value out of the insn stream and sign-extend to 64
565    bits. */
566 static Long getSDisp16 ( Long delta )
567 {
568    UInt v = guest_code[delta+1]; v <<= 8;
569    v |= guest_code[delta+0];
570    return extend_s_16to64( (UShort)v );
571 }
572
573 /* Get a 32-bit value out of the insn stream and sign-extend to 64
574    bits. */
575 static Long getSDisp32 ( Long delta )
576 {
577    UInt v = guest_code[delta+3]; v <<= 8;
578    v |= guest_code[delta+2]; v <<= 8;
579    v |= guest_code[delta+1]; v <<= 8;
580    v |= guest_code[delta+0];
581    return extend_s_32to64( v );
582 }
583
584 /* Get a 64-bit value out of the insn stream. */
585 static Long getDisp64 ( Long delta )
586 {
587    ULong v = 0;
588    v |= guest_code[delta+7]; v <<= 8;
589    v |= guest_code[delta+6]; v <<= 8;
590    v |= guest_code[delta+5]; v <<= 8;
591    v |= guest_code[delta+4]; v <<= 8;
592    v |= guest_code[delta+3]; v <<= 8;
593    v |= guest_code[delta+2]; v <<= 8;
594    v |= guest_code[delta+1]; v <<= 8;
595    v |= guest_code[delta+0];
596    return v;
597 }
598
599 /* Note: because AMD64 doesn't allow 64-bit literals, it is an error
600    if this is called with size==8.  Should not happen. */
601 static Long getSDisp ( Int size, Long delta )
602 {
603    switch (size) {
604       case 4: return getSDisp32(delta);
605       case 2: return getSDisp16(delta);
606       case 1: return getSDisp8(delta);
607       default: vpanic("getSDisp(amd64)");
608   }
609 }
610
611 static ULong mkSizeMask ( Int sz )
612 {
613    switch (sz) {
614       case 1: return 0x00000000000000FFULL;
615       case 2: return 0x000000000000FFFFULL;
616       case 4: return 0x00000000FFFFFFFFULL;
617       case 8: return 0xFFFFFFFFFFFFFFFFULL;
618       default: vpanic("mkSzMask(amd64)");
619    }
620 }
621
622 static Int imin ( Int a, Int b )
623 {
624    return (a < b) ? a : b;
625 }
626
627 static IRType szToITy ( Int n )
628 {
629    switch (n) {
630       case 1: return Ity_I8;
631       case 2: return Ity_I16;
632       case 4: return Ity_I32;
633       case 8: return Ity_I64;
634       default: vex_printf("\nszToITy(%d)\n", n);
635                vpanic("szToITy(amd64)");
636    }
637 }
638
639
640 /*------------------------------------------------------------*/
641 /*--- For dealing with prefixes.                           ---*/
642 /*------------------------------------------------------------*/
643
644 /* The idea is to pass around an int holding a bitmask summarising
645    info from the prefixes seen on the current instruction, including
646    info from the REX byte.  This info is used in various places, but
647    most especially when making sense of register fields in
648    instructions.
649
650    The top 16 bits of the prefix are 0x3141, just as a hacky way
651    to ensure it really is a valid prefix.
652
653    Things you can safely assume about a well-formed prefix:
654    * at most one segment-override bit (CS,DS,ES,FS,GS,SS) is set.
655    * if REX is not present then REXW,REXR,REXX,REXB will read
656      as zero.
657    * F2 and F3 will not both be 1.
658 */
659
660 typedef UInt  Prefix;
661
662 #define PFX_ASO   (1<<0)     /* address-size override present (0x67) */
663 #define PFX_66    (1<<1)     /* operand-size override-to-16 present (0x66) */
664 #define PFX_REX   (1<<2)     /* REX byte present (0x40 to 0x4F) */
665 #define PFX_REXW  (1<<3)     /* REX W bit, if REX present, else 0 */
666 #define PFX_REXR  (1<<4)     /* REX R bit, if REX present, else 0 */
667 #define PFX_REXX  (1<<5)     /* REX X bit, if REX present, else 0 */
668 #define PFX_REXB  (1<<6)     /* REX B bit, if REX present, else 0 */
669 #define PFX_LOCK  (1<<7)     /* bus LOCK prefix present (0xF0) */
670 #define PFX_F2    (1<<8)     /* REP/REPE/REPZ prefix present (0xF2) */
671 #define PFX_F3    (1<<9)     /* REPNE/REPNZ prefix present (0xF3) */
672 #define PFX_CS    (1<<10)    /* CS segment prefix present (0x2E) */
673 #define PFX_DS    (1<<11)    /* DS segment prefix present (0x3E) */
674 #define PFX_ES    (1<<12)    /* ES segment prefix present (0x26) */
675 #define PFX_FS    (1<<13)    /* FS segment prefix present (0x64) */
676 #define PFX_GS    (1<<14)    /* GS segment prefix present (0x65) */
677 #define PFX_SS    (1<<15)    /* SS segment prefix present (0x36) */
678
679 #define PFX_EMPTY 0x31410000
680
681 static Bool IS_VALID_PFX ( Prefix pfx ) {
682    return toBool((pfx & 0xFFFF0000) == PFX_EMPTY);
683 }
684
685 static Bool haveREX ( Prefix pfx ) {
686    return toBool(pfx & PFX_REX);
687 }
688
689 static Int getRexW ( Prefix pfx ) {
690    return (pfx & PFX_REXW) ? 1 : 0;
691 }
692 /* Apparently unused.
693 static Int getRexR ( Prefix pfx ) {
694    return (pfx & PFX_REXR) ? 1 : 0;
695 }
696 */
697 static Int getRexX ( Prefix pfx ) {
698    return (pfx & PFX_REXX) ? 1 : 0;
699 }
700 static Int getRexB ( Prefix pfx ) {
701    return (pfx & PFX_REXB) ? 1 : 0;
702 }
703
704 /* Check a prefix doesn't have F2 or F3 set in it, since usually that
705    completely changes what instruction it really is. */
706 static Bool haveF2orF3 ( Prefix pfx ) {
707    return toBool((pfx & (PFX_F2|PFX_F3)) > 0);
708 }
709 static Bool haveF2 ( Prefix pfx ) {
710    return toBool((pfx & PFX_F2) > 0);
711 }
712 static Bool haveF3 ( Prefix pfx ) {
713    return toBool((pfx & PFX_F3) > 0);
714 }
715
716 static Bool have66 ( Prefix pfx ) {
717    return toBool((pfx & PFX_66) > 0);
718 }
719 static Bool haveASO ( Prefix pfx ) {
720    return toBool((pfx & PFX_ASO) > 0);
721 }
722
723 /* Return True iff pfx has 66 set and F2 and F3 clear */
724 static Bool have66noF2noF3 ( Prefix pfx )
725 {
726   return 
727      toBool((pfx & (PFX_66|PFX_F2|PFX_F3)) == PFX_66);
728 }
729
730 /* Return True iff pfx has F2 set and 66 and F3 clear */
731 static Bool haveF2no66noF3 ( Prefix pfx )
732 {
733   return 
734      toBool((pfx & (PFX_66|PFX_F2|PFX_F3)) == PFX_F2);
735 }
736
737 /* Return True iff pfx has F3 set and 66 and F2 clear */
738 static Bool haveF3no66noF2 ( Prefix pfx )
739 {
740   return 
741      toBool((pfx & (PFX_66|PFX_F2|PFX_F3)) == PFX_F3);
742 }
743
744 /* Return True iff pfx has 66, F2 and F3 clear */
745 static Bool haveNo66noF2noF3 ( Prefix pfx )
746 {
747   return 
748      toBool((pfx & (PFX_66|PFX_F2|PFX_F3)) == 0);
749 }
750
751 /* Return True iff pfx has any of 66, F2 and F3 set */
752 static Bool have66orF2orF3 ( Prefix pfx )
753 {
754   return toBool( ! haveNo66noF2noF3(pfx) );
755 }
756
757 /* Return True iff pfx has 66 or F2 set */
758 static Bool have66orF2 ( Prefix pfx )
759 {
760    return toBool((pfx & (PFX_66|PFX_F2)) > 0);
761 }
762
763 /* Clear all the segment-override bits in a prefix. */
764 static Prefix clearSegBits ( Prefix p )
765 {
766    return 
767       p & ~(PFX_CS | PFX_DS | PFX_ES | PFX_FS | PFX_GS | PFX_SS);
768 }
769
770
771 /*------------------------------------------------------------*/
772 /*--- For dealing with integer registers                   ---*/
773 /*------------------------------------------------------------*/
774
775 /* This is somewhat complex.  The rules are:
776
777    For 64, 32 and 16 bit register references, the e or g fields in the
778    modrm bytes supply the low 3 bits of the register number.  The
779    fourth (most-significant) bit of the register number is supplied by
780    the REX byte, if it is present; else that bit is taken to be zero.
781
782    The REX.R bit supplies the high bit corresponding to the g register
783    field, and the REX.B bit supplies the high bit corresponding to the
784    e register field (when the mod part of modrm indicates that modrm's
785    e component refers to a register and not to memory).
786
787    The REX.X bit supplies a high register bit for certain registers
788    in SIB address modes, and is generally rarely used.
789
790    For 8 bit register references, the presence of the REX byte itself
791    has significance.  If there is no REX present, then the 3-bit
792    number extracted from the modrm e or g field is treated as an index
793    into the sequence %al %cl %dl %bl %ah %ch %dh %bh -- that is, the
794    old x86 encoding scheme.
795
796    But if there is a REX present, the register reference is
797    interpreted in the same way as for 64/32/16-bit references: a high
798    bit is extracted from REX, giving a 4-bit number, and the denoted
799    register is the lowest 8 bits of the 16 integer registers denoted
800    by the number.  In particular, values 3 through 7 of this sequence
801    do not refer to %ah %ch %dh %bh but instead to the lowest 8 bits of
802    %rsp %rbp %rsi %rdi.
803
804    The REX.W bit has no bearing at all on register numbers.  Instead
805    its presence indicates that the operand size is to be overridden
806    from its default value (32 bits) to 64 bits instead.  This is in
807    the same fashion that an 0x66 prefix indicates the operand size is
808    to be overridden from 32 bits down to 16 bits.  When both REX.W and
809    0x66 are present there is a conflict, and REX.W takes precedence.
810
811    Rather than try to handle this complexity using a single huge
812    function, several smaller ones are provided.  The aim is to make it
813    as difficult as possible to screw up register decoding in a subtle
814    and hard-to-track-down way.
815
816    Because these routines fish around in the host's memory (that is,
817    in the guest state area) for sub-parts of guest registers, their
818    correctness depends on the host's endianness.  So far these
819    routines only work for little-endian hosts.  Those for which
820    endianness is important have assertions to ensure sanity.
821 */
822
823
824 /* About the simplest question you can ask: where do the 64-bit
825    integer registers live (in the guest state) ? */
826
827 static Int integerGuestReg64Offset ( UInt reg )
828 {
829    switch (reg) {
830       case R_RAX: return OFFB_RAX;
831       case R_RCX: return OFFB_RCX;
832       case R_RDX: return OFFB_RDX;
833       case R_RBX: return OFFB_RBX;
834       case R_RSP: return OFFB_RSP;
835       case R_RBP: return OFFB_RBP;
836       case R_RSI: return OFFB_RSI;
837       case R_RDI: return OFFB_RDI;
838       case R_R8:  return OFFB_R8;
839       case R_R9:  return OFFB_R9;
840       case R_R10: return OFFB_R10;
841       case R_R11: return OFFB_R11;
842       case R_R12: return OFFB_R12;
843       case R_R13: return OFFB_R13;
844       case R_R14: return OFFB_R14;
845       case R_R15: return OFFB_R15;
846       default: vpanic("integerGuestReg64Offset(amd64)");
847    }
848 }
849
850
851 /* Produce the name of an integer register, for printing purposes.
852    reg is a number in the range 0 .. 15 that has been generated from a
853    3-bit reg-field number and a REX extension bit.  irregular denotes
854    the case where sz==1 and no REX byte is present. */
855
856 static 
857 HChar* nameIReg ( Int sz, UInt reg, Bool irregular )
858 {
859    static HChar* ireg64_names[16]
860      = { "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi",
861          "%r8",  "%r9",  "%r10", "%r11", "%r12", "%r13", "%r14", "%r15" };
862    static HChar* ireg32_names[16]
863      = { "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi",
864          "%r8d", "%r9d", "%r10d","%r11d","%r12d","%r13d","%r14d","%r15d" };
865    static HChar* ireg16_names[16]
866      = { "%ax",  "%cx",  "%dx",  "%bx",  "%sp",  "%bp",  "%si",  "%di",
867          "%r8w", "%r9w", "%r10w","%r11w","%r12w","%r13w","%r14w","%r15w" };
868    static HChar* ireg8_names[16]
869      = { "%al",  "%cl",  "%dl",  "%bl",  "%spl", "%bpl", "%sil", "%dil",
870          "%r8b", "%r9b", "%r10b","%r11b","%r12b","%r13b","%r14b","%r15b" };
871    static HChar* ireg8_irregular[8] 
872      = { "%al", "%cl", "%dl", "%bl", "%ah", "%ch", "%dh", "%bh" };
873
874    vassert(reg < 16);
875    if (sz == 1) {
876       if (irregular)
877          vassert(reg < 8);
878    } else {
879       vassert(irregular == False);
880    }
881
882    switch (sz) {
883       case 8: return ireg64_names[reg];
884       case 4: return ireg32_names[reg];
885       case 2: return ireg16_names[reg];
886       case 1: if (irregular) {
887                  return ireg8_irregular[reg];
888               } else {
889                  return ireg8_names[reg];
890               }
891       default: vpanic("nameIReg(amd64)");
892    }
893 }
894
895 /* Using the same argument conventions as nameIReg, produce the
896    guest state offset of an integer register. */
897
898 static 
899 Int offsetIReg ( Int sz, UInt reg, Bool irregular )
900 {
901    vassert(reg < 16);
902    if (sz == 1) {
903       if (irregular)
904          vassert(reg < 8);
905    } else {
906       vassert(irregular == False);
907    }
908
909    /* Deal with irregular case -- sz==1 and no REX present */
910    if (sz == 1 && irregular) {
911       switch (reg) {
912          case R_RSP: return 1+ OFFB_RAX;
913          case R_RBP: return 1+ OFFB_RCX;
914          case R_RSI: return 1+ OFFB_RDX;
915          case R_RDI: return 1+ OFFB_RBX;
916          default:    break; /* use the normal case */
917       }
918    }
919
920    /* Normal case */
921    return integerGuestReg64Offset(reg);
922 }
923
924
925 /* Read the %CL register :: Ity_I8, for shift/rotate operations. */
926
927 static IRExpr* getIRegCL ( void )
928 {
929    vassert(!host_is_bigendian);
930    return IRExpr_Get( OFFB_RCX, Ity_I8 );
931 }
932
933
934 /* Write to the %AH register. */
935
936 static void putIRegAH ( IRExpr* e )
937 {
938    vassert(!host_is_bigendian);
939    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
940    stmt( IRStmt_Put( OFFB_RAX+1, e ) );
941 }
942
943
944 /* Read/write various widths of %RAX, as it has various
945    special-purpose uses. */
946
947 static HChar* nameIRegRAX ( Int sz )
948 {
949    switch (sz) {
950       case 1: return "%al";
951       case 2: return "%ax";
952       case 4: return "%eax";
953       case 8: return "%rax";
954       default: vpanic("nameIRegRAX(amd64)");
955    }
956 }
957
958 static IRExpr* getIRegRAX ( Int sz )
959 {
960    vassert(!host_is_bigendian);
961    switch (sz) {
962       case 1: return IRExpr_Get( OFFB_RAX, Ity_I8 );
963       case 2: return IRExpr_Get( OFFB_RAX, Ity_I16 );
964       case 4: return unop(Iop_64to32, IRExpr_Get( OFFB_RAX, Ity_I64 ));
965       case 8: return IRExpr_Get( OFFB_RAX, Ity_I64 );
966       default: vpanic("getIRegRAX(amd64)");
967    }
968 }
969
970 static void putIRegRAX ( Int sz, IRExpr* e )
971 {
972    IRType ty = typeOfIRExpr(irsb->tyenv, e);
973    vassert(!host_is_bigendian);
974    switch (sz) {
975       case 8: vassert(ty == Ity_I64);
976               stmt( IRStmt_Put( OFFB_RAX, e ));
977               break;
978       case 4: vassert(ty == Ity_I32);
979               stmt( IRStmt_Put( OFFB_RAX, unop(Iop_32Uto64,e) ));
980               break;
981       case 2: vassert(ty == Ity_I16);
982               stmt( IRStmt_Put( OFFB_RAX, e ));
983               break;
984       case 1: vassert(ty == Ity_I8);
985               stmt( IRStmt_Put( OFFB_RAX, e ));
986               break;
987       default: vpanic("putIRegRAX(amd64)");
988    }
989 }
990
991
992 /* Read/write various widths of %RDX, as it has various
993    special-purpose uses. */
994
995 static HChar* nameIRegRDX ( Int sz )
996 {
997    switch (sz) {
998       case 1: return "%dl";
999       case 2: return "%dx";
1000       case 4: return "%edx";
1001       case 8: return "%rdx";
1002       default: vpanic("nameIRegRDX(amd64)");
1003    }
1004 }
1005
1006 static IRExpr* getIRegRDX ( Int sz )
1007 {
1008    vassert(!host_is_bigendian);
1009    switch (sz) {
1010       case 1: return IRExpr_Get( OFFB_RDX, Ity_I8 );
1011       case 2: return IRExpr_Get( OFFB_RDX, Ity_I16 );
1012       case 4: return unop(Iop_64to32, IRExpr_Get( OFFB_RDX, Ity_I64 ));
1013       case 8: return IRExpr_Get( OFFB_RDX, Ity_I64 );
1014       default: vpanic("getIRegRDX(amd64)");
1015    }
1016 }
1017
1018 static void putIRegRDX ( Int sz, IRExpr* e )
1019 {
1020    vassert(!host_is_bigendian);
1021    vassert(typeOfIRExpr(irsb->tyenv, e) == szToITy(sz));
1022    switch (sz) {
1023       case 8: stmt( IRStmt_Put( OFFB_RDX, e ));
1024               break;
1025       case 4: stmt( IRStmt_Put( OFFB_RDX, unop(Iop_32Uto64,e) ));
1026               break;
1027       case 2: stmt( IRStmt_Put( OFFB_RDX, e ));
1028               break;
1029       case 1: stmt( IRStmt_Put( OFFB_RDX, e ));
1030               break;
1031       default: vpanic("putIRegRDX(amd64)");
1032    }
1033 }
1034
1035
1036 /* Simplistic functions to deal with the integer registers as a
1037    straightforward bank of 16 64-bit regs. */
1038
1039 static IRExpr* getIReg64 ( UInt regno )
1040 {
1041    return IRExpr_Get( integerGuestReg64Offset(regno),
1042                       Ity_I64 );
1043 }
1044
1045 static void putIReg64 ( UInt regno, IRExpr* e )
1046 {
1047    vassert(typeOfIRExpr(irsb->tyenv,e) == Ity_I64);
1048    stmt( IRStmt_Put( integerGuestReg64Offset(regno), e ) );
1049 }
1050
1051 static HChar* nameIReg64 ( UInt regno )
1052 {
1053    return nameIReg( 8, regno, False );
1054 }
1055
1056
1057 /* Simplistic functions to deal with the lower halves of integer
1058    registers as a straightforward bank of 16 32-bit regs. */
1059
1060 static IRExpr* getIReg32 ( UInt regno )
1061 {
1062    vassert(!host_is_bigendian);
1063    return unop(Iop_64to32,
1064                IRExpr_Get( integerGuestReg64Offset(regno),
1065                            Ity_I64 ));
1066 }
1067
1068 static void putIReg32 ( UInt regno, IRExpr* e )
1069 {
1070    vassert(typeOfIRExpr(irsb->tyenv,e) == Ity_I32);
1071    stmt( IRStmt_Put( integerGuestReg64Offset(regno), 
1072                      unop(Iop_32Uto64,e) ) );
1073 }
1074
1075 static HChar* nameIReg32 ( UInt regno )
1076 {
1077    return nameIReg( 4, regno, False );
1078 }
1079
1080
1081 /* Simplistic functions to deal with the lower quarters of integer
1082    registers as a straightforward bank of 16 16-bit regs. */
1083
1084 static IRExpr* getIReg16 ( UInt regno )
1085 {
1086    vassert(!host_is_bigendian);
1087    return IRExpr_Get( integerGuestReg64Offset(regno),
1088                       Ity_I16 );
1089 }
1090
1091 static HChar* nameIReg16 ( UInt regno )
1092 {
1093    return nameIReg( 2, regno, False );
1094 }
1095
1096
1097 /* Sometimes what we know is a 3-bit register number, a REX byte, and
1098    which field of the REX byte is to be used to extend to a 4-bit
1099    number.  These functions cater for that situation.  
1100 */
1101 static IRExpr* getIReg64rexX ( Prefix pfx, UInt lo3bits )
1102 {
1103    vassert(lo3bits < 8);
1104    vassert(IS_VALID_PFX(pfx));
1105    return getIReg64( lo3bits | (getRexX(pfx) << 3) );
1106 }
1107
1108 static HChar* nameIReg64rexX ( Prefix pfx, UInt lo3bits )
1109 {
1110    vassert(lo3bits < 8);
1111    vassert(IS_VALID_PFX(pfx));
1112    return nameIReg( 8, lo3bits | (getRexX(pfx) << 3), False );
1113 }
1114
1115 static HChar* nameIRegRexB ( Int sz, Prefix pfx, UInt lo3bits )
1116 {
1117    vassert(lo3bits < 8);
1118    vassert(IS_VALID_PFX(pfx));
1119    vassert(sz == 8 || sz == 4 || sz == 2 || sz == 1);
1120    return nameIReg( sz, lo3bits | (getRexB(pfx) << 3), 
1121                         toBool(sz==1 && !haveREX(pfx)) );
1122 }
1123
1124 static IRExpr* getIRegRexB ( Int sz, Prefix pfx, UInt lo3bits )
1125 {
1126    vassert(lo3bits < 8);
1127    vassert(IS_VALID_PFX(pfx));
1128    vassert(sz == 8 || sz == 4 || sz == 2 || sz == 1);
1129    if (sz == 4) {
1130       sz = 8;
1131       return unop(Iop_64to32,
1132                   IRExpr_Get(
1133                      offsetIReg( sz, lo3bits | (getRexB(pfx) << 3), 
1134                                      toBool(sz==1 && !haveREX(pfx)) ),
1135                      szToITy(sz)
1136                  )
1137              );
1138    } else {
1139    return IRExpr_Get(
1140              offsetIReg( sz, lo3bits | (getRexB(pfx) << 3), 
1141                              toBool(sz==1 && !haveREX(pfx)) ),
1142              szToITy(sz)
1143           );
1144    }
1145 }
1146
1147 static void putIRegRexB ( Int sz, Prefix pfx, UInt lo3bits, IRExpr* e )
1148 {
1149    vassert(lo3bits < 8);
1150    vassert(IS_VALID_PFX(pfx));
1151    vassert(sz == 8 || sz == 4 || sz == 2 || sz == 1);
1152    vassert(typeOfIRExpr(irsb->tyenv, e) == szToITy(sz));
1153    stmt( IRStmt_Put( 
1154             offsetIReg( sz, lo3bits | (getRexB(pfx) << 3), 
1155                             toBool(sz==1 && !haveREX(pfx)) ),
1156             sz==4 ? unop(Iop_32Uto64,e) : e
1157    ));
1158 }
1159
1160
1161 /* Functions for getting register numbers from modrm bytes and REX
1162    when we don't have to consider the complexities of integer subreg
1163    accesses.
1164 */
1165 /* Extract the g reg field from a modRM byte, and augment it using the
1166    REX.R bit from the supplied REX byte.  The R bit usually is
1167    associated with the g register field.
1168 */
1169 static UInt gregOfRexRM ( Prefix pfx, UChar mod_reg_rm )
1170 {
1171    Int reg = (Int)( (mod_reg_rm >> 3) & 7 );
1172    reg += (pfx & PFX_REXR) ? 8 : 0;
1173    return reg;
1174 }
1175
1176 /* Extract the e reg field from a modRM byte, and augment it using the
1177    REX.B bit from the supplied REX byte.  The B bit usually is
1178    associated with the e register field (when modrm indicates e is a
1179    register, that is).
1180 */
1181 static UInt eregOfRexRM ( Prefix pfx, UChar mod_reg_rm )
1182 {
1183    Int rm;
1184    vassert(epartIsReg(mod_reg_rm));
1185    rm = (Int)(mod_reg_rm & 0x7);
1186    rm += (pfx & PFX_REXB) ? 8 : 0;
1187    return rm;
1188 }
1189
1190
1191 /* General functions for dealing with integer register access. */
1192
1193 /* Produce the guest state offset for a reference to the 'g' register
1194    field in a modrm byte, taking into account REX (or its absence),
1195    and the size of the access.
1196 */
1197 static UInt offsetIRegG ( Int sz, Prefix pfx, UChar mod_reg_rm )
1198 {
1199    UInt reg;
1200    vassert(!host_is_bigendian);
1201    vassert(IS_VALID_PFX(pfx));
1202    vassert(sz == 8 || sz == 4 || sz == 2 || sz == 1);
1203    reg = gregOfRexRM( pfx, mod_reg_rm );
1204    return offsetIReg( sz, reg, toBool(sz == 1 && !haveREX(pfx)) );
1205 }
1206
1207 static 
1208 IRExpr* getIRegG ( Int sz, Prefix pfx, UChar mod_reg_rm )
1209 {
1210    if (sz == 4) {
1211       sz = 8;
1212       return unop(Iop_64to32,
1213                   IRExpr_Get( offsetIRegG( sz, pfx, mod_reg_rm ),
1214                               szToITy(sz) ));
1215    } else {
1216    return IRExpr_Get( offsetIRegG( sz, pfx, mod_reg_rm ),
1217                       szToITy(sz) );
1218    }
1219 }
1220
1221 static 
1222 void putIRegG ( Int sz, Prefix pfx, UChar mod_reg_rm, IRExpr* e )
1223 {
1224    vassert(typeOfIRExpr(irsb->tyenv,e) == szToITy(sz));
1225    if (sz == 4) {
1226       e = unop(Iop_32Uto64,e);
1227    }
1228    stmt( IRStmt_Put( offsetIRegG( sz, pfx, mod_reg_rm ), e ) );
1229 }
1230
1231 static
1232 HChar* nameIRegG ( Int sz, Prefix pfx, UChar mod_reg_rm )
1233 {
1234    return nameIReg( sz, gregOfRexRM(pfx,mod_reg_rm),
1235                         toBool(sz==1 && !haveREX(pfx)) );
1236 }
1237
1238
1239 /* Produce the guest state offset for a reference to the 'e' register
1240    field in a modrm byte, taking into account REX (or its absence),
1241    and the size of the access.  eregOfRexRM will assert if mod_reg_rm
1242    denotes a memory access rather than a register access.
1243 */
1244 static UInt offsetIRegE ( Int sz, Prefix pfx, UChar mod_reg_rm )
1245 {
1246    UInt reg;
1247    vassert(!host_is_bigendian);
1248    vassert(IS_VALID_PFX(pfx));
1249    vassert(sz == 8 || sz == 4 || sz == 2 || sz == 1);
1250    reg = eregOfRexRM( pfx, mod_reg_rm );
1251    return offsetIReg( sz, reg, toBool(sz == 1 && !haveREX(pfx)) );
1252 }
1253
1254 static 
1255 IRExpr* getIRegE ( Int sz, Prefix pfx, UChar mod_reg_rm )
1256 {
1257    if (sz == 4) {
1258       sz = 8;
1259       return unop(Iop_64to32,
1260                   IRExpr_Get( offsetIRegE( sz, pfx, mod_reg_rm ),
1261                               szToITy(sz) ));
1262    } else {
1263    return IRExpr_Get( offsetIRegE( sz, pfx, mod_reg_rm ),
1264                       szToITy(sz) );
1265    }
1266 }
1267
1268 static 
1269 void putIRegE ( Int sz, Prefix pfx, UChar mod_reg_rm, IRExpr* e )
1270 {
1271    vassert(typeOfIRExpr(irsb->tyenv,e) == szToITy(sz));
1272    if (sz == 4) {
1273       e = unop(Iop_32Uto64,e);
1274    }
1275    stmt( IRStmt_Put( offsetIRegE( sz, pfx, mod_reg_rm ), e ) );
1276 }
1277
1278 static
1279 HChar* nameIRegE ( Int sz, Prefix pfx, UChar mod_reg_rm )
1280 {
1281    return nameIReg( sz, eregOfRexRM(pfx,mod_reg_rm),
1282                         toBool(sz==1 && !haveREX(pfx)) );
1283 }
1284
1285
1286 /*------------------------------------------------------------*/
1287 /*--- For dealing with XMM registers                       ---*/
1288 /*------------------------------------------------------------*/
1289
1290 //.. static Int segmentGuestRegOffset ( UInt sreg )
1291 //.. {
1292 //..    switch (sreg) {
1293 //..       case R_ES: return OFFB_ES;
1294 //..       case R_CS: return OFFB_CS;
1295 //..       case R_SS: return OFFB_SS;
1296 //..       case R_DS: return OFFB_DS;
1297 //..       case R_FS: return OFFB_FS;
1298 //..       case R_GS: return OFFB_GS;
1299 //..       default: vpanic("segmentGuestRegOffset(x86)");
1300 //..    }
1301 //.. }
1302
1303 static Int xmmGuestRegOffset ( UInt xmmreg )
1304 {
1305    switch (xmmreg) {
1306       case 0:  return OFFB_XMM0;
1307       case 1:  return OFFB_XMM1;
1308       case 2:  return OFFB_XMM2;
1309       case 3:  return OFFB_XMM3;
1310       case 4:  return OFFB_XMM4;
1311       case 5:  return OFFB_XMM5;
1312       case 6:  return OFFB_XMM6;
1313       case 7:  return OFFB_XMM7;
1314       case 8:  return OFFB_XMM8;
1315       case 9:  return OFFB_XMM9;
1316       case 10: return OFFB_XMM10;
1317       case 11: return OFFB_XMM11;
1318       case 12: return OFFB_XMM12;
1319       case 13: return OFFB_XMM13;
1320       case 14: return OFFB_XMM14;
1321       case 15: return OFFB_XMM15;
1322       default: vpanic("xmmGuestRegOffset(amd64)");
1323    }
1324 }
1325
1326 /* Lanes of vector registers are always numbered from zero being the
1327    least significant lane (rightmost in the register).  */
1328
1329 static Int xmmGuestRegLane16offset ( UInt xmmreg, Int laneno )
1330 {
1331    /* Correct for little-endian host only. */
1332    vassert(!host_is_bigendian);
1333    vassert(laneno >= 0 && laneno < 8);
1334    return xmmGuestRegOffset( xmmreg ) + 2 * laneno;
1335 }
1336
1337 static Int xmmGuestRegLane32offset ( UInt xmmreg, Int laneno )
1338 {
1339    /* Correct for little-endian host only. */
1340    vassert(!host_is_bigendian);
1341    vassert(laneno >= 0 && laneno < 4);
1342    return xmmGuestRegOffset( xmmreg ) + 4 * laneno;
1343 }
1344
1345 static Int xmmGuestRegLane64offset ( UInt xmmreg, Int laneno )
1346 {
1347    /* Correct for little-endian host only. */
1348    vassert(!host_is_bigendian);
1349    vassert(laneno >= 0 && laneno < 2);
1350    return xmmGuestRegOffset( xmmreg ) + 8 * laneno;
1351 }
1352
1353 //.. static IRExpr* getSReg ( UInt sreg )
1354 //.. {
1355 //..    return IRExpr_Get( segmentGuestRegOffset(sreg), Ity_I16 );
1356 //.. }
1357 //.. 
1358 //.. static void putSReg ( UInt sreg, IRExpr* e )
1359 //.. {
1360 //..    vassert(typeOfIRExpr(irsb->tyenv,e) == Ity_I16);
1361 //..    stmt( IRStmt_Put( segmentGuestRegOffset(sreg), e ) );
1362 //.. }
1363
1364 static IRExpr* getXMMReg ( UInt xmmreg )
1365 {
1366    return IRExpr_Get( xmmGuestRegOffset(xmmreg), Ity_V128 );
1367 }
1368
1369 static IRExpr* getXMMRegLane64 ( UInt xmmreg, Int laneno )
1370 {
1371    return IRExpr_Get( xmmGuestRegLane64offset(xmmreg,laneno), Ity_I64 );
1372 }
1373
1374 static IRExpr* getXMMRegLane64F ( UInt xmmreg, Int laneno )
1375 {
1376    return IRExpr_Get( xmmGuestRegLane64offset(xmmreg,laneno), Ity_F64 );
1377 }
1378
1379 static IRExpr* getXMMRegLane32 ( UInt xmmreg, Int laneno )
1380 {
1381    return IRExpr_Get( xmmGuestRegLane32offset(xmmreg,laneno), Ity_I32 );
1382 }
1383
1384 static IRExpr* getXMMRegLane32F ( UInt xmmreg, Int laneno )
1385 {
1386    return IRExpr_Get( xmmGuestRegLane32offset(xmmreg,laneno), Ity_F32 );
1387 }
1388
1389 static IRExpr* getXMMRegLane16 ( UInt xmmreg, Int laneno )
1390 {
1391   return IRExpr_Get( xmmGuestRegLane16offset(xmmreg,laneno), Ity_I16 );
1392 }
1393
1394 static void putXMMReg ( UInt xmmreg, IRExpr* e )
1395 {
1396    vassert(typeOfIRExpr(irsb->tyenv,e) == Ity_V128);
1397    stmt( IRStmt_Put( xmmGuestRegOffset(xmmreg), e ) );
1398 }
1399
1400 static void putXMMRegLane64 ( UInt xmmreg, Int laneno, IRExpr* e )
1401 {
1402    vassert(typeOfIRExpr(irsb->tyenv,e) == Ity_I64);
1403    stmt( IRStmt_Put( xmmGuestRegLane64offset(xmmreg,laneno), e ) );
1404 }
1405
1406 static void putXMMRegLane64F ( UInt xmmreg, Int laneno, IRExpr* e )
1407 {
1408    vassert(typeOfIRExpr(irsb->tyenv,e) == Ity_F64);
1409    stmt( IRStmt_Put( xmmGuestRegLane64offset(xmmreg,laneno), e ) );
1410 }
1411
1412 static void putXMMRegLane32F ( UInt xmmreg, Int laneno, IRExpr* e )
1413 {
1414    vassert(typeOfIRExpr(irsb->tyenv,e) == Ity_F32);
1415    stmt( IRStmt_Put( xmmGuestRegLane32offset(xmmreg,laneno), e ) );
1416 }
1417
1418 static void putXMMRegLane32 ( UInt xmmreg, Int laneno, IRExpr* e )
1419 {
1420    vassert(typeOfIRExpr(irsb->tyenv,e) == Ity_I32);
1421    stmt( IRStmt_Put( xmmGuestRegLane32offset(xmmreg,laneno), e ) );
1422 }
1423
1424 static void putXMMRegLane16 ( UInt xmmreg, Int laneno, IRExpr* e )
1425 {
1426    vassert(typeOfIRExpr(irsb->tyenv,e) == Ity_I16);
1427    stmt( IRStmt_Put( xmmGuestRegLane16offset(xmmreg,laneno), e ) );
1428 }
1429
1430 static IRExpr* mkV128 ( UShort mask )
1431 {
1432    return IRExpr_Const(IRConst_V128(mask));
1433 }
1434
1435 static IRExpr* mkAnd1 ( IRExpr* x, IRExpr* y )
1436 {
1437    vassert(typeOfIRExpr(irsb->tyenv,x) == Ity_I1);
1438    vassert(typeOfIRExpr(irsb->tyenv,y) == Ity_I1);
1439    return unop(Iop_64to1, 
1440                binop(Iop_And64, 
1441                      unop(Iop_1Uto64,x), 
1442                      unop(Iop_1Uto64,y)));
1443 }
1444
1445 /* Generate a compare-and-swap operation, operating on memory at
1446    'addr'.  The expected value is 'expVal' and the new value is
1447    'newVal'.  If the operation fails, then transfer control (with a
1448    no-redir jump (XXX no -- see comment at top of this file)) to
1449    'restart_point', which is presumably the address of the guest
1450    instruction again -- retrying, essentially. */
1451 static void casLE ( IRExpr* addr, IRExpr* expVal, IRExpr* newVal,
1452                     Addr64 restart_point )
1453 {
1454    IRCAS* cas;
1455    IRType tyE    = typeOfIRExpr(irsb->tyenv, expVal);
1456    IRType tyN    = typeOfIRExpr(irsb->tyenv, newVal);
1457    IRTemp oldTmp = newTemp(tyE);
1458    IRTemp expTmp = newTemp(tyE);
1459    vassert(tyE == tyN);
1460    vassert(tyE == Ity_I64 || tyE == Ity_I32
1461            || tyE == Ity_I16 || tyE == Ity_I8);
1462    assign(expTmp, expVal);
1463    cas = mkIRCAS( IRTemp_INVALID, oldTmp, Iend_LE, addr, 
1464                   NULL, mkexpr(expTmp), NULL, newVal );
1465    stmt( IRStmt_CAS(cas) );
1466    stmt( IRStmt_Exit(
1467             binop( mkSizedOp(tyE,Iop_CasCmpNE8),
1468                    mkexpr(oldTmp), mkexpr(expTmp) ),
1469             Ijk_Boring, /*Ijk_NoRedir*/
1470             IRConst_U64( restart_point ) 
1471          ));
1472 }
1473
1474
1475 /*------------------------------------------------------------*/
1476 /*--- Helpers for %rflags.                                 ---*/
1477 /*------------------------------------------------------------*/
1478
1479 /* -------------- Evaluating the flags-thunk. -------------- */
1480
1481 /* Build IR to calculate all the eflags from stored
1482    CC_OP/CC_DEP1/CC_DEP2/CC_NDEP.  Returns an expression ::
1483    Ity_I64. */
1484 static IRExpr* mk_amd64g_calculate_rflags_all ( void )
1485 {
1486    IRExpr** args
1487       = mkIRExprVec_4( IRExpr_Get(OFFB_CC_OP,   Ity_I64),
1488                        IRExpr_Get(OFFB_CC_DEP1, Ity_I64),
1489                        IRExpr_Get(OFFB_CC_DEP2, Ity_I64),
1490                        IRExpr_Get(OFFB_CC_NDEP, Ity_I64) );
1491    IRExpr* call
1492       = mkIRExprCCall(
1493            Ity_I64,
1494            0/*regparm*/, 
1495            "amd64g_calculate_rflags_all", &amd64g_calculate_rflags_all,
1496            args
1497         );
1498    /* Exclude OP and NDEP from definedness checking.  We're only
1499       interested in DEP1 and DEP2. */
1500    call->Iex.CCall.cee->mcx_mask = (1<<0) | (1<<3);
1501    return call;
1502 }
1503
1504 /* Build IR to calculate some particular condition from stored
1505    CC_OP/CC_DEP1/CC_DEP2/CC_NDEP.  Returns an expression ::
1506    Ity_Bit. */
1507 static IRExpr* mk_amd64g_calculate_condition ( AMD64Condcode cond )
1508 {
1509    IRExpr** args
1510       = mkIRExprVec_5( mkU64(cond),
1511                        IRExpr_Get(OFFB_CC_OP,   Ity_I64),
1512                        IRExpr_Get(OFFB_CC_DEP1, Ity_I64),
1513                        IRExpr_Get(OFFB_CC_DEP2, Ity_I64),
1514                        IRExpr_Get(OFFB_CC_NDEP, Ity_I64) );
1515    IRExpr* call
1516       = mkIRExprCCall(
1517            Ity_I64,
1518            0/*regparm*/, 
1519            "amd64g_calculate_condition", &amd64g_calculate_condition,
1520            args
1521         );
1522    /* Exclude the requested condition, OP and NDEP from definedness
1523       checking.  We're only interested in DEP1 and DEP2. */
1524    call->Iex.CCall.cee->mcx_mask = (1<<0) | (1<<1) | (1<<4);
1525    return unop(Iop_64to1, call);
1526 }
1527
1528 /* Build IR to calculate just the carry flag from stored
1529    CC_OP/CC_DEP1/CC_DEP2/CC_NDEP.  Returns an expression :: Ity_I64. */
1530 static IRExpr* mk_amd64g_calculate_rflags_c ( void )
1531 {
1532    IRExpr** args
1533       = mkIRExprVec_4( IRExpr_Get(OFFB_CC_OP,   Ity_I64),
1534                        IRExpr_Get(OFFB_CC_DEP1, Ity_I64),
1535                        IRExpr_Get(OFFB_CC_DEP2, Ity_I64),
1536                        IRExpr_Get(OFFB_CC_NDEP, Ity_I64) );
1537    IRExpr* call
1538       = mkIRExprCCall(
1539            Ity_I64,
1540            0/*regparm*/, 
1541            "amd64g_calculate_rflags_c", &amd64g_calculate_rflags_c,
1542            args
1543         );
1544    /* Exclude OP and NDEP from definedness checking.  We're only
1545       interested in DEP1 and DEP2. */
1546    call->Iex.CCall.cee->mcx_mask = (1<<0) | (1<<3);
1547    return call;
1548 }
1549
1550
1551 /* -------------- Building the flags-thunk. -------------- */
1552
1553 /* The machinery in this section builds the flag-thunk following a
1554    flag-setting operation.  Hence the various setFlags_* functions.
1555 */
1556
1557 static Bool isAddSub ( IROp op8 )
1558 {
1559    return toBool(op8 == Iop_Add8 || op8 == Iop_Sub8);
1560 }
1561
1562 static Bool isLogic ( IROp op8 )
1563 {
1564    return toBool(op8 == Iop_And8 || op8 == Iop_Or8 || op8 == Iop_Xor8);
1565 }
1566
1567 /* U-widen 8/16/32/64 bit int expr to 64. */
1568 static IRExpr* widenUto64 ( IRExpr* e )
1569 {
1570    switch (typeOfIRExpr(irsb->tyenv,e)) {
1571       case Ity_I64: return e;
1572       case Ity_I32: return unop(Iop_32Uto64, e);
1573       case Ity_I16: return unop(Iop_16Uto64, e);
1574       case Ity_I8:  return unop(Iop_8Uto64, e);
1575       default: vpanic("widenUto64");
1576    }
1577 }
1578
1579 /* S-widen 8/16/32/64 bit int expr to 32. */
1580 static IRExpr* widenSto64 ( IRExpr* e )
1581 {
1582    switch (typeOfIRExpr(irsb->tyenv,e)) {
1583       case Ity_I64: return e;
1584       case Ity_I32: return unop(Iop_32Sto64, e);
1585       case Ity_I16: return unop(Iop_16Sto64, e);
1586       case Ity_I8:  return unop(Iop_8Sto64, e);
1587       default: vpanic("widenSto64");
1588    }
1589 }
1590
1591 /* Narrow 8/16/32/64 bit int expr to 8/16/32/64.  Clearly only some
1592    of these combinations make sense. */
1593 static IRExpr* narrowTo ( IRType dst_ty, IRExpr* e )
1594 {
1595    IRType src_ty = typeOfIRExpr(irsb->tyenv,e);
1596    if (src_ty == dst_ty)
1597       return e;
1598    if (src_ty == Ity_I32 && dst_ty == Ity_I16)
1599       return unop(Iop_32to16, e);
1600    if (src_ty == Ity_I32 && dst_ty == Ity_I8)
1601       return unop(Iop_32to8, e);
1602    if (src_ty == Ity_I64 && dst_ty == Ity_I32)
1603       return unop(Iop_64to32, e);
1604    if (src_ty == Ity_I64 && dst_ty == Ity_I16)
1605       return unop(Iop_64to16, e);
1606    if (src_ty == Ity_I64 && dst_ty == Ity_I8)
1607       return unop(Iop_64to8, e);
1608
1609    vex_printf("\nsrc, dst tys are: ");
1610    ppIRType(src_ty);
1611    vex_printf(", ");
1612    ppIRType(dst_ty);
1613    vex_printf("\n");
1614    vpanic("narrowTo(amd64)");
1615 }
1616
1617
1618 /* Set the flags thunk OP, DEP1 and DEP2 fields.  The supplied op is
1619    auto-sized up to the real op. */
1620
1621 static 
1622 void setFlags_DEP1_DEP2 ( IROp op8, IRTemp dep1, IRTemp dep2, IRType ty )
1623 {
1624    Int ccOp = 0;
1625    switch (ty) {
1626       case Ity_I8:  ccOp = 0; break;
1627       case Ity_I16: ccOp = 1; break;
1628       case Ity_I32: ccOp = 2; break;
1629       case Ity_I64: ccOp = 3; break;
1630       default: vassert(0);
1631    }
1632    switch (op8) {
1633       case Iop_Add8: ccOp += AMD64G_CC_OP_ADDB;   break;
1634       case Iop_Sub8: ccOp += AMD64G_CC_OP_SUBB;   break;
1635       default:       ppIROp(op8);
1636                      vpanic("setFlags_DEP1_DEP2(amd64)");
1637    }
1638    stmt( IRStmt_Put( OFFB_CC_OP,   mkU64(ccOp)) );
1639    stmt( IRStmt_Put( OFFB_CC_DEP1, widenUto64(mkexpr(dep1))) );
1640    stmt( IRStmt_Put( OFFB_CC_DEP2, widenUto64(mkexpr(dep2))) );
1641 }
1642
1643
1644 /* Set the OP and DEP1 fields only, and write zero to DEP2. */
1645
1646 static 
1647 void setFlags_DEP1 ( IROp op8, IRTemp dep1, IRType ty )
1648 {
1649    Int ccOp = 0;
1650    switch (ty) {
1651       case Ity_I8:  ccOp = 0; break;
1652       case Ity_I16: ccOp = 1; break;
1653       case Ity_I32: ccOp = 2; break;
1654       case Ity_I64: ccOp = 3; break;
1655       default: vassert(0);
1656    }
1657    switch (op8) {
1658       case Iop_Or8:
1659       case Iop_And8:
1660       case Iop_Xor8: ccOp += AMD64G_CC_OP_LOGICB; break;
1661       default:       ppIROp(op8);
1662                      vpanic("setFlags_DEP1(amd64)");
1663    }
1664    stmt( IRStmt_Put( OFFB_CC_OP,   mkU64(ccOp)) );
1665    stmt( IRStmt_Put( OFFB_CC_DEP1, widenUto64(mkexpr(dep1))) );
1666    stmt( IRStmt_Put( OFFB_CC_DEP2, mkU64(0)) );
1667 }
1668
1669
1670 /* For shift operations, we put in the result and the undershifted
1671    result.  Except if the shift amount is zero, the thunk is left
1672    unchanged. */
1673
1674 static void setFlags_DEP1_DEP2_shift ( IROp    op64,
1675                                        IRTemp  res,
1676                                        IRTemp  resUS,
1677                                        IRType  ty,
1678                                        IRTemp  guard )
1679 {
1680    Int ccOp = 0;
1681    switch (ty) {
1682       case Ity_I8:  ccOp = 0; break;
1683       case Ity_I16: ccOp = 1; break;
1684       case Ity_I32: ccOp = 2; break;
1685       case Ity_I64: ccOp = 3; break;
1686       default: vassert(0);
1687    }
1688
1689    vassert(guard);
1690
1691    /* Both kinds of right shifts are handled by the same thunk
1692       operation. */
1693    switch (op64) {
1694       case Iop_Shr64:
1695       case Iop_Sar64: ccOp += AMD64G_CC_OP_SHRB; break;
1696       case Iop_Shl64: ccOp += AMD64G_CC_OP_SHLB; break;
1697       default:        ppIROp(op64);
1698                       vpanic("setFlags_DEP1_DEP2_shift(amd64)");
1699    }
1700
1701    /* DEP1 contains the result, DEP2 contains the undershifted value. */
1702    stmt( IRStmt_Put( OFFB_CC_OP,
1703                      IRExpr_Mux0X( mkexpr(guard),
1704                                    IRExpr_Get(OFFB_CC_OP,Ity_I64),
1705                                    mkU64(ccOp))) );
1706    stmt( IRStmt_Put( OFFB_CC_DEP1,
1707                      IRExpr_Mux0X( mkexpr(guard),
1708                                    IRExpr_Get(OFFB_CC_DEP1,Ity_I64),
1709                                    widenUto64(mkexpr(res)))) );
1710    stmt( IRStmt_Put( OFFB_CC_DEP2, 
1711                      IRExpr_Mux0X( mkexpr(guard),
1712                                    IRExpr_Get(OFFB_CC_DEP2,Ity_I64),
1713                                    widenUto64(mkexpr(resUS)))) );
1714 }
1715
1716
1717 /* For the inc/dec case, we store in DEP1 the result value and in NDEP
1718    the former value of the carry flag, which unfortunately we have to
1719    compute. */
1720
1721 static void setFlags_INC_DEC ( Bool inc, IRTemp res, IRType ty )
1722 {
1723    Int ccOp = inc ? AMD64G_CC_OP_INCB : AMD64G_CC_OP_DECB;
1724
1725    switch (ty) {
1726       case Ity_I8:  ccOp += 0; break;
1727       case Ity_I16: ccOp += 1; break;
1728       case Ity_I32: ccOp += 2; break;
1729       case Ity_I64: ccOp += 3; break;
1730       default: vassert(0);
1731    }
1732    
1733    /* This has to come first, because calculating the C flag 
1734       may require reading all four thunk fields. */
1735    stmt( IRStmt_Put( OFFB_CC_NDEP, mk_amd64g_calculate_rflags_c()) );
1736    stmt( IRStmt_Put( OFFB_CC_OP,   mkU64(ccOp)) );
1737    stmt( IRStmt_Put( OFFB_CC_DEP1, widenUto64(mkexpr(res))) );
1738    stmt( IRStmt_Put( OFFB_CC_DEP2, mkU64(0)) );
1739 }
1740
1741
1742 /* Multiplies are pretty much like add and sub: DEP1 and DEP2 hold the
1743    two arguments. */
1744
1745 static
1746 void setFlags_MUL ( IRType ty, IRTemp arg1, IRTemp arg2, ULong base_op )
1747 {
1748    switch (ty) {
1749       case Ity_I8:
1750          stmt( IRStmt_Put( OFFB_CC_OP, mkU64(base_op+0) ) );
1751          break;
1752       case Ity_I16:
1753          stmt( IRStmt_Put( OFFB_CC_OP, mkU64(base_op+1) ) );
1754          break;
1755       case Ity_I32:
1756          stmt( IRStmt_Put( OFFB_CC_OP, mkU64(base_op+2) ) );
1757          break;
1758       case Ity_I64:
1759          stmt( IRStmt_Put( OFFB_CC_OP, mkU64(base_op+3) ) );
1760          break;
1761       default:
1762          vpanic("setFlags_MUL(amd64)");
1763    }
1764    stmt( IRStmt_Put( OFFB_CC_DEP1, widenUto64(mkexpr(arg1)) ));
1765    stmt( IRStmt_Put( OFFB_CC_DEP2, widenUto64(mkexpr(arg2)) ));
1766 }
1767
1768
1769 /* -------------- Condition codes. -------------- */
1770
1771 /* Condition codes, using the AMD encoding.  */
1772
1773 static HChar* name_AMD64Condcode ( AMD64Condcode cond )
1774 {
1775    switch (cond) {
1776       case AMD64CondO:      return "o";
1777       case AMD64CondNO:     return "no";
1778       case AMD64CondB:      return "b";
1779       case AMD64CondNB:     return "ae"; /*"nb";*/
1780       case AMD64CondZ:      return "e"; /*"z";*/
1781       case AMD64CondNZ:     return "ne"; /*"nz";*/
1782       case AMD64CondBE:     return "be";
1783       case AMD64CondNBE:    return "a"; /*"nbe";*/
1784       case AMD64CondS:      return "s";
1785       case AMD64CondNS:     return "ns";
1786       case AMD64CondP:      return "p";
1787       case AMD64CondNP:     return "np";
1788       case AMD64CondL:      return "l";
1789       case AMD64CondNL:     return "ge"; /*"nl";*/
1790       case AMD64CondLE:     return "le";
1791       case AMD64CondNLE:    return "g"; /*"nle";*/
1792       case AMD64CondAlways: return "ALWAYS";
1793       default: vpanic("name_AMD64Condcode");
1794    }
1795 }
1796
1797 static 
1798 AMD64Condcode positiveIse_AMD64Condcode ( AMD64Condcode  cond,
1799                                           /*OUT*/Bool*   needInvert )
1800 {
1801    vassert(cond >= AMD64CondO && cond <= AMD64CondNLE);
1802    if (cond & 1) {
1803       *needInvert = True;
1804       return cond-1;
1805    } else {
1806       *needInvert = False;
1807       return cond;
1808    }
1809 }
1810
1811
1812 /* -------------- Helpers for ADD/SUB with carry. -------------- */
1813
1814 /* Given ta1, ta2 and tres, compute tres = ADC(ta1,ta2) and set flags
1815    appropriately.
1816
1817    Optionally, generate a store for the 'tres' value.  This can either
1818    be a normal store, or it can be a cas-with-possible-failure style
1819    store:
1820
1821    if taddr is IRTemp_INVALID, then no store is generated.
1822
1823    if taddr is not IRTemp_INVALID, then a store (using taddr as
1824    the address) is generated:
1825
1826      if texpVal is IRTemp_INVALID then a normal store is
1827      generated, and restart_point must be zero (it is irrelevant).
1828
1829      if texpVal is not IRTemp_INVALID then a cas-style store is
1830      generated.  texpVal is the expected value, restart_point
1831      is the restart point if the store fails, and texpVal must
1832      have the same type as tres.   
1833
1834 */
1835 static void helper_ADC ( Int sz,
1836                          IRTemp tres, IRTemp ta1, IRTemp ta2,
1837                          /* info about optional store: */
1838                          IRTemp taddr, IRTemp texpVal, Addr32 restart_point )
1839 {
1840    UInt    thunkOp;
1841    IRType  ty    = szToITy(sz);
1842    IRTemp  oldc  = newTemp(Ity_I64);
1843    IRTemp  oldcn = newTemp(ty);
1844    IROp    plus  = mkSizedOp(ty, Iop_Add8);
1845    IROp    xor   = mkSizedOp(ty, Iop_Xor8);
1846
1847    vassert(typeOfIRTemp(irsb->tyenv, tres) == ty);
1848
1849    switch (sz) {
1850       case 8:  thunkOp = AMD64G_CC_OP_ADCQ; break;
1851       case 4:  thunkOp = AMD64G_CC_OP_ADCL; break;
1852       case 2:  thunkOp = AMD64G_CC_OP_ADCW; break;
1853       case 1:  thunkOp = AMD64G_CC_OP_ADCB; break;
1854       default: vassert(0);
1855    }
1856
1857    /* oldc = old carry flag, 0 or 1 */
1858    assign( oldc,  binop(Iop_And64,
1859                         mk_amd64g_calculate_rflags_c(),
1860                         mkU64(1)) );
1861
1862    assign( oldcn, narrowTo(ty, mkexpr(oldc)) );
1863
1864    assign( tres, binop(plus,
1865                        binop(plus,mkexpr(ta1),mkexpr(ta2)),
1866                        mkexpr(oldcn)) );
1867
1868    /* Possibly generate a store of 'tres' to 'taddr'.  See comment at
1869       start of this function. */
1870    if (taddr != IRTemp_INVALID) {
1871       if (texpVal == IRTemp_INVALID) {
1872          vassert(restart_point == 0);
1873          storeLE( mkexpr(taddr), mkexpr(tres) );
1874       } else {
1875          vassert(typeOfIRTemp(irsb->tyenv, texpVal) == ty);
1876          /* .. and hence 'texpVal' has the same type as 'tres'. */
1877          casLE( mkexpr(taddr),
1878                 mkexpr(texpVal), mkexpr(tres), restart_point );
1879       }
1880    }
1881
1882    stmt( IRStmt_Put( OFFB_CC_OP,   mkU64(thunkOp) ) );
1883    stmt( IRStmt_Put( OFFB_CC_DEP1, widenUto64(mkexpr(ta1))  ));
1884    stmt( IRStmt_Put( OFFB_CC_DEP2, widenUto64(binop(xor, mkexpr(ta2), 
1885                                                          mkexpr(oldcn)) )) );
1886    stmt( IRStmt_Put( OFFB_CC_NDEP, mkexpr(oldc) ) );
1887 }
1888
1889
1890 /* Given ta1, ta2 and tres, compute tres = SBB(ta1,ta2) and set flags
1891    appropriately.  As with helper_ADC, possibly generate a store of
1892    the result -- see comments on helper_ADC for details.
1893 */
1894 static void helper_SBB ( Int sz,
1895                          IRTemp tres, IRTemp ta1, IRTemp ta2,
1896                          /* info about optional store: */
1897                          IRTemp taddr, IRTemp texpVal, Addr32 restart_point )
1898 {
1899    UInt    thunkOp;
1900    IRType  ty    = szToITy(sz);
1901    IRTemp  oldc  = newTemp(Ity_I64);
1902    IRTemp  oldcn = newTemp(ty);
1903    IROp    minus = mkSizedOp(ty, Iop_Sub8);
1904    IROp    xor   = mkSizedOp(ty, Iop_Xor8);
1905
1906    vassert(typeOfIRTemp(irsb->tyenv, tres) == ty);
1907
1908    switch (sz) {
1909       case 8:  thunkOp = AMD64G_CC_OP_SBBQ; break;
1910       case 4:  thunkOp = AMD64G_CC_OP_SBBL; break;
1911       case 2:  thunkOp = AMD64G_CC_OP_SBBW; break;
1912       case 1:  thunkOp = AMD64G_CC_OP_SBBB; break;
1913       default: vassert(0);
1914    }
1915
1916    /* oldc = old carry flag, 0 or 1 */
1917    assign( oldc, binop(Iop_And64,
1918                        mk_amd64g_calculate_rflags_c(),
1919                        mkU64(1)) );
1920
1921    assign( oldcn, narrowTo(ty, mkexpr(oldc)) );
1922
1923    assign( tres, binop(minus,
1924                        binop(minus,mkexpr(ta1),mkexpr(ta2)),
1925                        mkexpr(oldcn)) );
1926
1927    /* Possibly generate a store of 'tres' to 'taddr'.  See comment at
1928       start of this function. */
1929    if (taddr != IRTemp_INVALID) {
1930       if (texpVal == IRTemp_INVALID) {
1931          vassert(restart_point == 0);
1932          storeLE( mkexpr(taddr), mkexpr(tres) );
1933       } else {
1934          vassert(typeOfIRTemp(irsb->tyenv, texpVal) == ty);
1935          /* .. and hence 'texpVal' has the same type as 'tres'. */
1936          casLE( mkexpr(taddr),
1937                 mkexpr(texpVal), mkexpr(tres), restart_point );
1938       }
1939    }
1940
1941    stmt( IRStmt_Put( OFFB_CC_OP,   mkU64(thunkOp) ) );
1942    stmt( IRStmt_Put( OFFB_CC_DEP1, widenUto64(mkexpr(ta1) )) );
1943    stmt( IRStmt_Put( OFFB_CC_DEP2, widenUto64(binop(xor, mkexpr(ta2), 
1944                                                          mkexpr(oldcn)) )) );
1945    stmt( IRStmt_Put( OFFB_CC_NDEP, mkexpr(oldc) ) );
1946 }
1947
1948
1949 /* -------------- Helpers for disassembly printing. -------------- */
1950
1951 static HChar* nameGrp1 ( Int opc_aux )
1952 {
1953    static HChar* grp1_names[8] 
1954      = { "add", "or", "adc", "sbb", "and", "sub", "xor", "cmp" };
1955    if (opc_aux < 0 || opc_aux > 7) vpanic("nameGrp1(amd64)");
1956    return grp1_names[opc_aux];
1957 }
1958
1959 static HChar* nameGrp2 ( Int opc_aux )
1960 {
1961    static HChar* grp2_names[8] 
1962      = { "rol", "ror", "rcl", "rcr", "shl", "shr", "shl", "sar" };
1963    if (opc_aux < 0 || opc_aux > 7) vpanic("nameGrp2(amd64)");
1964    return grp2_names[opc_aux];
1965 }
1966
1967 static HChar* nameGrp4 ( Int opc_aux )
1968 {
1969    static HChar* grp4_names[8] 
1970      = { "inc", "dec", "???", "???", "???", "???", "???", "???" };
1971    if (opc_aux < 0 || opc_aux > 1) vpanic("nameGrp4(amd64)");
1972    return grp4_names[opc_aux];
1973 }
1974
1975 static HChar* nameGrp5 ( Int opc_aux )
1976 {
1977    static HChar* grp5_names[8] 
1978      = { "inc", "dec", "call*", "call*", "jmp*", "jmp*", "push", "???" };
1979    if (opc_aux < 0 || opc_aux > 6) vpanic("nameGrp5(amd64)");
1980    return grp5_names[opc_aux];
1981 }
1982
1983 static HChar* nameGrp8 ( Int opc_aux )
1984 {
1985    static HChar* grp8_names[8] 
1986       = { "???", "???", "???", "???", "bt", "bts", "btr", "btc" };
1987    if (opc_aux < 4 || opc_aux > 7) vpanic("nameGrp8(amd64)");
1988    return grp8_names[opc_aux];
1989 }
1990
1991 //.. static HChar* nameSReg ( UInt sreg )
1992 //.. {
1993 //..    switch (sreg) {
1994 //..       case R_ES: return "%es";
1995 //..       case R_CS: return "%cs";
1996 //..       case R_SS: return "%ss";
1997 //..       case R_DS: return "%ds";
1998 //..       case R_FS: return "%fs";
1999 //..       case R_GS: return "%gs";
2000 //..       default: vpanic("nameSReg(x86)");
2001 //..    }
2002 //.. }
2003
2004 static HChar* nameMMXReg ( Int mmxreg )
2005 {
2006    static HChar* mmx_names[8] 
2007      = { "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7" };
2008    if (mmxreg < 0 || mmxreg > 7) vpanic("nameMMXReg(amd64,guest)");
2009    return mmx_names[mmxreg];
2010 }
2011
2012 static HChar* nameXMMReg ( Int xmmreg )
2013 {
2014    static HChar* xmm_names[16] 
2015      = { "%xmm0",  "%xmm1",  "%xmm2",  "%xmm3", 
2016          "%xmm4",  "%xmm5",  "%xmm6",  "%xmm7", 
2017          "%xmm8",  "%xmm9",  "%xmm10", "%xmm11", 
2018          "%xmm12", "%xmm13", "%xmm14", "%xmm15" };
2019    if (xmmreg < 0 || xmmreg > 15) vpanic("nameXMMReg(amd64)");
2020    return xmm_names[xmmreg];
2021 }
2022  
2023 static HChar* nameMMXGran ( Int gran )
2024 {
2025    switch (gran) {
2026       case 0: return "b";
2027       case 1: return "w";
2028       case 2: return "d";
2029       case 3: return "q";
2030       default: vpanic("nameMMXGran(amd64,guest)");
2031    }
2032 }
2033
2034 static HChar nameISize ( Int size )
2035 {
2036    switch (size) {
2037       case 8: return 'q';
2038       case 4: return 'l';
2039       case 2: return 'w';
2040       case 1: return 'b';
2041       default: vpanic("nameISize(amd64)");
2042    }
2043 }
2044
2045
2046 /*------------------------------------------------------------*/
2047 /*--- JMP helpers                                          ---*/
2048 /*------------------------------------------------------------*/
2049
2050 static void jmp_lit( IRJumpKind kind, Addr64 d64 )
2051 {
2052    irsb->next     = mkU64(d64);
2053    irsb->jumpkind = kind;
2054 }
2055
2056 static void jmp_treg( IRJumpKind kind, IRTemp t )
2057 {
2058    irsb->next     = mkexpr(t);
2059    irsb->jumpkind = kind;
2060 }
2061
2062 static 
2063 void jcc_01 ( AMD64Condcode cond, Addr64 d64_false, Addr64 d64_true )
2064 {
2065    Bool          invert;
2066    AMD64Condcode condPos;
2067    condPos = positiveIse_AMD64Condcode ( cond, &invert );
2068    if (invert) {
2069       stmt( IRStmt_Exit( mk_amd64g_calculate_condition(condPos),
2070                          Ijk_Boring,
2071                          IRConst_U64(d64_false) ) );
2072       irsb->next     = mkU64(d64_true);
2073       irsb->jumpkind = Ijk_Boring;
2074    } else {
2075       stmt( IRStmt_Exit( mk_amd64g_calculate_condition(condPos),
2076                          Ijk_Boring,
2077                          IRConst_U64(d64_true) ) );
2078       irsb->next     = mkU64(d64_false);
2079       irsb->jumpkind = Ijk_Boring;
2080    }
2081 }
2082
2083 /* Let new_rsp be the %rsp value after a call/return.  Let nia be the
2084    guest address of the next instruction to be executed.
2085
2086    This function generates an AbiHint to say that -128(%rsp)
2087    .. -1(%rsp) should now be regarded as uninitialised.
2088 */
2089 static 
2090 void make_redzone_AbiHint ( VexAbiInfo* vbi,
2091                             IRTemp new_rsp, IRTemp nia, HChar* who )
2092 {
2093    Int szB = vbi->guest_stack_redzone_size;
2094    vassert(szB >= 0);
2095
2096    /* A bit of a kludge.  Currently the only AbI we've guested AMD64
2097       for is ELF.  So just check it's the expected 128 value
2098       (paranoia). */
2099    vassert(szB == 128);
2100
2101    if (0) vex_printf("AbiHint: %s\n", who);
2102    vassert(typeOfIRTemp(irsb->tyenv, new_rsp) == Ity_I64);
2103    vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I64);
2104    if (szB > 0)
2105       stmt( IRStmt_AbiHint( 
2106                binop(Iop_Sub64, mkexpr(new_rsp), mkU64(szB)), 
2107                szB,
2108                mkexpr(nia)
2109             ));
2110 }
2111
2112
2113 /*------------------------------------------------------------*/
2114 /*--- Disassembling addressing modes                       ---*/
2115 /*------------------------------------------------------------*/
2116
2117 static 
2118 HChar* segRegTxt ( Prefix pfx )
2119 {
2120    if (pfx & PFX_CS) return "%cs:";
2121    if (pfx & PFX_DS) return "%ds:";
2122    if (pfx & PFX_ES) return "%es:";
2123    if (pfx & PFX_FS) return "%fs:";
2124    if (pfx & PFX_GS) return "%gs:";
2125    if (pfx & PFX_SS) return "%ss:";
2126    return ""; /* no override */
2127 }
2128
2129
2130 /* 'virtual' is an IRExpr* holding a virtual address.  Convert it to a
2131    linear address by adding any required segment override as indicated
2132    by sorb, and also dealing with any address size override
2133    present. */
2134 static
2135 IRExpr* handleAddrOverrides ( VexAbiInfo* vbi, 
2136                               Prefix pfx, IRExpr* virtual )
2137 {
2138    /* --- segment overrides --- */
2139    if (pfx & PFX_FS) {
2140       if (vbi->guest_amd64_assume_fs_is_zero) {
2141          /* Note that this is a linux-kernel specific hack that relies
2142             on the assumption that %fs is always zero. */
2143          /* return virtual + guest_FS_ZERO. */
2144          virtual = binop(Iop_Add64, virtual,
2145                                     IRExpr_Get(OFFB_FS_ZERO, Ity_I64));
2146       } else {
2147          unimplemented("amd64 %fs segment override");
2148       }
2149    }
2150
2151    if (pfx & PFX_GS) {
2152       if (vbi->guest_amd64_assume_gs_is_0x60) {
2153          /* Note that this is a darwin-kernel specific hack that relies
2154             on the assumption that %gs is always 0x60. */
2155          /* return virtual + guest_GS_0x60. */
2156          virtual = binop(Iop_Add64, virtual,
2157                                     IRExpr_Get(OFFB_GS_0x60, Ity_I64));
2158       } else {
2159          unimplemented("amd64 %gs segment override");
2160       }
2161    }
2162
2163    /* cs, ds, es and ss are simply ignored in 64-bit mode. */
2164
2165    /* --- address size override --- */
2166    if (haveASO(pfx))
2167       virtual = unop(Iop_32Uto64, unop(Iop_64to32, virtual));
2168
2169    return virtual;
2170 }
2171
2172 //.. {
2173 //..    Int    sreg;
2174 //..    IRType hWordTy;
2175 //..    IRTemp ldt_ptr, gdt_ptr, seg_selector, r64;
2176 //.. 
2177 //..    if (sorb == 0)
2178 //..       /* the common case - no override */
2179 //..       return virtual;
2180 //.. 
2181 //..    switch (sorb) {
2182 //..       case 0x3E: sreg = R_DS; break;
2183 //..       case 0x26: sreg = R_ES; break;
2184 //..       case 0x64: sreg = R_FS; break;
2185 //..       case 0x65: sreg = R_GS; break;
2186 //..       default: vpanic("handleAddrOverrides(x86,guest)");
2187 //..    }
2188 //.. 
2189 //..    hWordTy = sizeof(HWord)==4 ? Ity_I32 : Ity_I64;
2190 //.. 
2191 //..    seg_selector = newTemp(Ity_I32);
2192 //..    ldt_ptr      = newTemp(hWordTy);
2193 //..    gdt_ptr      = newTemp(hWordTy);
2194 //..    r64          = newTemp(Ity_I64);
2195 //.. 
2196 //..    assign( seg_selector, unop(Iop_16Uto32, getSReg(sreg)) );
2197 //..    assign( ldt_ptr, IRExpr_Get( OFFB_LDT, hWordTy ));
2198 //..    assign( gdt_ptr, IRExpr_Get( OFFB_GDT, hWordTy ));
2199 //.. 
2200 //..    /*
2201 //..    Call this to do the translation and limit checks: 
2202 //..    ULong x86g_use_seg_selector ( HWord ldt, HWord gdt,
2203 //..                                  UInt seg_selector, UInt virtual_addr )
2204 //..    */
2205 //..    assign( 
2206 //..       r64, 
2207 //..       mkIRExprCCall( 
2208 //..          Ity_I64, 
2209 //..          0/*regparms*/, 
2210 //..          "x86g_use_seg_selector", 
2211 //..          &x86g_use_seg_selector, 
2212 //..          mkIRExprVec_4( mkexpr(ldt_ptr), mkexpr(gdt_ptr), 
2213 //..                         mkexpr(seg_selector), virtual)
2214 //..       )
2215 //..    );
2216 //.. 
2217 //..    /* If the high 32 of the result are non-zero, there was a 
2218 //..       failure in address translation.  In which case, make a
2219 //..       quick exit.
2220 //..    */
2221 //..    stmt( 
2222 //..       IRStmt_Exit(
2223 //..          binop(Iop_CmpNE32, unop(Iop_64HIto32, mkexpr(r64)), mkU32(0)),
2224 //..          Ijk_MapFail,
2225 //..          IRConst_U32( guest_eip_curr_instr )
2226 //..       )
2227 //..    );
2228 //.. 
2229 //..    /* otherwise, here's the translated result. */
2230 //..    return unop(Iop_64to32, mkexpr(r64));
2231 //.. }
2232
2233
2234 /* Generate IR to calculate an address indicated by a ModRM and
2235    following SIB bytes.  The expression, and the number of bytes in
2236    the address mode, are returned (the latter in *len).  Note that
2237    this fn should not be called if the R/M part of the address denotes
2238    a register instead of memory.  If print_codegen is true, text of
2239    the addressing mode is placed in buf.
2240
2241    The computed address is stored in a new tempreg, and the
2242    identity of the tempreg is returned.
2243
2244    extra_bytes holds the number of bytes after the amode, as supplied
2245    by the caller.  This is needed to make sense of %rip-relative
2246    addresses.  Note that the value that *len is set to is only the
2247    length of the amode itself and does not include the value supplied
2248    in extra_bytes.
2249  */
2250
2251 static IRTemp disAMode_copy2tmp ( IRExpr* addr64 )
2252 {
2253    IRTemp tmp = newTemp(Ity_I64);
2254    assign( tmp, addr64 );
2255    return tmp;
2256 }
2257
2258 static 
2259 IRTemp disAMode ( /*OUT*/Int* len,
2260                   VexAbiInfo* vbi, Prefix pfx, Long delta, 
2261                   /*OUT*/HChar* buf, Int extra_bytes )
2262 {
2263    UChar mod_reg_rm = getUChar(delta);
2264    delta++;
2265
2266    buf[0] = (UChar)0;
2267    vassert(extra_bytes >= 0 && extra_bytes < 10);
2268
2269    /* squeeze out the reg field from mod_reg_rm, since a 256-entry
2270       jump table seems a bit excessive. 
2271    */
2272    mod_reg_rm &= 0xC7;                         /* is now XX000YYY */
2273    mod_reg_rm  = toUChar(mod_reg_rm | (mod_reg_rm >> 3));
2274                                                /* is now XX0XXYYY */
2275    mod_reg_rm &= 0x1F;                         /* is now 000XXYYY */
2276    switch (mod_reg_rm) {
2277
2278       /* REX.B==0: (%rax) .. (%rdi), not including (%rsp) or (%rbp).
2279          REX.B==1: (%r8)  .. (%r15), not including (%r12) or (%r13).
2280       */
2281       case 0x00: case 0x01: case 0x02: case 0x03: 
2282       /* ! 04 */ /* ! 05 */ case 0x06: case 0x07:
2283          { UChar rm = toUChar(mod_reg_rm & 7);
2284            DIS(buf, "%s(%s)", segRegTxt(pfx), nameIRegRexB(8,pfx,rm));
2285            *len = 1;
2286            return disAMode_copy2tmp(
2287                   handleAddrOverrides(vbi, pfx, getIRegRexB(8,pfx,rm)));
2288          }
2289
2290       /* REX.B==0: d8(%rax) ... d8(%rdi), not including d8(%rsp) 
2291          REX.B==1: d8(%r8)  ... d8(%r15), not including d8(%r12) 
2292       */
2293       case 0x08: case 0x09: case 0x0A: case 0x0B: 
2294       /* ! 0C */ case 0x0D: case 0x0E: case 0x0F:
2295          { UChar rm = toUChar(mod_reg_rm & 7);
2296            Long d   = getSDisp8(delta);
2297            if (d == 0) {
2298               DIS(buf, "%s(%s)", segRegTxt(pfx), nameIRegRexB(8,pfx,rm));
2299            } else {
2300               DIS(buf, "%s%lld(%s)", segRegTxt(pfx), d, nameIRegRexB(8,pfx,rm));
2301            }
2302            *len = 2;
2303            return disAMode_copy2tmp(
2304                   handleAddrOverrides(vbi, pfx,
2305                      binop(Iop_Add64,getIRegRexB(8,pfx,rm),mkU64(d))));
2306          }
2307
2308       /* REX.B==0: d32(%rax) ... d32(%rdi), not including d32(%rsp)
2309          REX.B==1: d32(%r8)  ... d32(%r15), not including d32(%r12)
2310       */
2311       case 0x10: case 0x11: case 0x12: case 0x13: 
2312       /* ! 14 */ case 0x15: case 0x16: case 0x17:
2313          { UChar rm = toUChar(mod_reg_rm & 7);
2314            Long  d  = getSDisp32(delta);
2315            DIS(buf, "%s%lld(%s)", segRegTxt(pfx), d, nameIRegRexB(8,pfx,rm));
2316            *len = 5;
2317            return disAMode_copy2tmp(
2318                   handleAddrOverrides(vbi, pfx,
2319                      binop(Iop_Add64,getIRegRexB(8,pfx,rm),mkU64(d))));
2320          }
2321
2322       /* REX.B==0: a register, %rax .. %rdi.  This shouldn't happen. */
2323       /* REX.B==1: a register, %r8  .. %r16.  This shouldn't happen. */
2324       case 0x18: case 0x19: case 0x1A: case 0x1B:
2325       case 0x1C: case 0x1D: case 0x1E: case 0x1F:
2326          vpanic("disAMode(amd64): not an addr!");
2327
2328       /* RIP + disp32.  This assumes that guest_RIP_curr_instr is set
2329          correctly at the start of handling each instruction. */
2330       case 0x05: 
2331          { Long d = getSDisp32(delta);
2332            *len = 5;
2333            DIS(buf, "%s%lld(%%rip)", segRegTxt(pfx), d);
2334            /* We need to know the next instruction's start address.
2335               Try and figure out what it is, record the guess, and ask
2336               the top-level driver logic (bbToIR_AMD64) to check we
2337               guessed right, after the instruction is completely
2338               decoded. */
2339            guest_RIP_next_mustcheck = True;
2340            guest_RIP_next_assumed = guest_RIP_bbstart 
2341                                     + delta+4 + extra_bytes;
2342            return disAMode_copy2tmp( 
2343                      handleAddrOverrides(vbi, pfx, 
2344                         binop(Iop_Add64, mkU64(guest_RIP_next_assumed), 
2345                                          mkU64(d))));
2346          }
2347
2348       case 0x04: {
2349          /* SIB, with no displacement.  Special cases:
2350             -- %rsp cannot act as an index value.  
2351                If index_r indicates %rsp, zero is used for the index.
2352             -- when mod is zero and base indicates RBP or R13, base is 
2353                instead a 32-bit sign-extended literal.
2354             It's all madness, I tell you.  Extract %index, %base and 
2355             scale from the SIB byte.  The value denoted is then:
2356                | %index == %RSP && (%base == %RBP || %base == %R13)
2357                = d32 following SIB byte
2358                | %index == %RSP && !(%base == %RBP || %base == %R13)
2359                = %base
2360                | %index != %RSP && (%base == %RBP || %base == %R13)
2361                = d32 following SIB byte + (%index << scale)
2362                | %index != %RSP && !(%base == %RBP || %base == %R13)
2363                = %base + (%index << scale)
2364          */
2365          UChar sib     = getUChar(delta);
2366          UChar scale   = toUChar((sib >> 6) & 3);
2367          UChar index_r = toUChar((sib >> 3) & 7);
2368          UChar base_r  = toUChar(sib & 7);
2369          /* correct since #(R13) == 8 + #(RBP) */
2370          Bool  base_is_BPor13 = toBool(base_r == R_RBP);
2371          Bool  index_is_SP    = toBool(index_r == R_RSP && 0==getRexX(pfx));
2372          delta++;
2373
2374          if ((!index_is_SP) && (!base_is_BPor13)) {
2375             if (scale == 0) {
2376                DIS(buf, "%s(%s,%s)", segRegTxt(pfx), 
2377                          nameIRegRexB(8,pfx,base_r), 
2378                          nameIReg64rexX(pfx,index_r));
2379             } else {
2380                DIS(buf, "%s(%s,%s,%d)", segRegTxt(pfx), 
2381                          nameIRegRexB(8,pfx,base_r), 
2382                          nameIReg64rexX(pfx,index_r), 1<<scale);
2383             }
2384             *len = 2;
2385             return
2386                disAMode_copy2tmp( 
2387                handleAddrOverrides(vbi, pfx,
2388                   binop(Iop_Add64, 
2389                         getIRegRexB(8,pfx,base_r),
2390                         binop(Iop_Shl64, getIReg64rexX(pfx,index_r),
2391                               mkU8(scale)))));
2392          }
2393
2394          if ((!index_is_SP) && base_is_BPor13) {
2395             Long d = getSDisp32(delta);
2396             DIS(buf, "%s%lld(,%s,%d)", segRegTxt(pfx), d, 
2397                       nameIReg64rexX(pfx,index_r), 1<<scale);
2398             *len = 6;
2399             return
2400                disAMode_copy2tmp(
2401                handleAddrOverrides(vbi, pfx, 
2402                   binop(Iop_Add64,
2403                         binop(Iop_Shl64, getIReg64rexX(pfx,index_r), 
2404                                          mkU8(scale)),
2405                         mkU64(d))));
2406          }
2407
2408          if (index_is_SP && (!base_is_BPor13)) {
2409             DIS(buf, "%s(%s)", segRegTxt(pfx), nameIRegRexB(8,pfx,base_r));
2410             *len = 2;
2411             return disAMode_copy2tmp(
2412                    handleAddrOverrides(vbi, pfx, getIRegRexB(8,pfx,base_r)));
2413          }
2414
2415          if (index_is_SP && base_is_BPor13) {
2416             Long d = getSDisp32(delta);
2417             DIS(buf, "%s%lld", segRegTxt(pfx), d);
2418             *len = 6;
2419             return disAMode_copy2tmp(
2420                    handleAddrOverrides(vbi, pfx, mkU64(d)));
2421          }
2422
2423          vassert(0);
2424       }
2425
2426       /* SIB, with 8-bit displacement.  Special cases:
2427          -- %esp cannot act as an index value.  
2428             If index_r indicates %esp, zero is used for the index.
2429          Denoted value is:
2430             | %index == %ESP
2431             = d8 + %base
2432             | %index != %ESP
2433             = d8 + %base + (%index << scale)
2434       */
2435       case 0x0C: {
2436          UChar sib     = getUChar(delta);
2437          UChar scale   = toUChar((sib >> 6) & 3);
2438          UChar index_r = toUChar((sib >> 3) & 7);
2439          UChar base_r  = toUChar(sib & 7);
2440          Long d        = getSDisp8(delta+1);
2441
2442          if (index_r == R_RSP && 0==getRexX(pfx)) {
2443             DIS(buf, "%s%lld(%s)", segRegTxt(pfx), 
2444                                    d, nameIRegRexB(8,pfx,base_r));
2445             *len = 3;
2446             return disAMode_copy2tmp(
2447                    handleAddrOverrides(vbi, pfx, 
2448                       binop(Iop_Add64, getIRegRexB(8,pfx,base_r), mkU64(d)) ));
2449          } else {
2450             if (scale == 0) {
2451                DIS(buf, "%s%lld(%s,%s)", segRegTxt(pfx), d, 
2452                          nameIRegRexB(8,pfx,base_r), 
2453                          nameIReg64rexX(pfx,index_r));
2454             } else {
2455                DIS(buf, "%s%lld(%s,%s,%d)", segRegTxt(pfx), d, 
2456                          nameIRegRexB(8,pfx,base_r), 
2457                          nameIReg64rexX(pfx,index_r), 1<<scale);
2458             }
2459             *len = 3;
2460             return 
2461                 disAMode_copy2tmp(
2462                 handleAddrOverrides(vbi, pfx,
2463                   binop(Iop_Add64,
2464                         binop(Iop_Add64, 
2465                               getIRegRexB(8,pfx,base_r), 
2466                               binop(Iop_Shl64, 
2467                                     getIReg64rexX(pfx,index_r), mkU8(scale))),
2468                         mkU64(d))));
2469          }
2470          vassert(0); /*NOTREACHED*/
2471       }
2472
2473       /* SIB, with 32-bit displacement.  Special cases:
2474          -- %rsp cannot act as an index value.  
2475             If index_r indicates %rsp, zero is used for the index.
2476          Denoted value is:
2477             | %index == %RSP
2478             = d32 + %base
2479             | %index != %RSP
2480             = d32 + %base + (%index << scale)
2481       */
2482       case 0x14: {
2483          UChar sib     = getUChar(delta);
2484          UChar scale   = toUChar((sib >> 6) & 3);
2485          UChar index_r = toUChar((sib >> 3) & 7);
2486          UChar base_r  = toUChar(sib & 7);
2487          Long d        = getSDisp32(delta+1);
2488
2489          if (index_r == R_RSP && 0==getRexX(pfx)) {
2490             DIS(buf, "%s%lld(%s)", segRegTxt(pfx), 
2491                                    d, nameIRegRexB(8,pfx,base_r));
2492             *len = 6;
2493             return disAMode_copy2tmp(
2494                    handleAddrOverrides(vbi, pfx, 
2495                       binop(Iop_Add64, getIRegRexB(8,pfx,base_r), mkU64(d)) ));
2496          } else {
2497             if (scale == 0) {
2498                DIS(buf, "%s%lld(%s,%s)", segRegTxt(pfx), d, 
2499                          nameIRegRexB(8,pfx,base_r), 
2500                          nameIReg64rexX(pfx,index_r));
2501             } else {
2502                DIS(buf, "%s%lld(%s,%s,%d)", segRegTxt(pfx), d, 
2503                          nameIRegRexB(8,pfx,base_r), 
2504                          nameIReg64rexX(pfx,index_r), 1<<scale);
2505             }
2506             *len = 6;
2507             return 
2508                 disAMode_copy2tmp(
2509                 handleAddrOverrides(vbi, pfx,
2510                   binop(Iop_Add64,
2511                         binop(Iop_Add64, 
2512                               getIRegRexB(8,pfx,base_r), 
2513                               binop(Iop_Shl64, 
2514                                     getIReg64rexX(pfx,index_r), mkU8(scale))),
2515                         mkU64(d))));
2516          }
2517          vassert(0); /*NOTREACHED*/
2518       }
2519
2520       default:
2521          vpanic("disAMode(amd64)");
2522          return 0; /*notreached*/
2523    }
2524 }
2525
2526
2527 /* Figure out the number of (insn-stream) bytes constituting the amode
2528    beginning at delta.  Is useful for getting hold of literals beyond
2529    the end of the amode before it has been disassembled.  */
2530
2531 static UInt lengthAMode ( Prefix pfx, Long delta )
2532 {
2533    UChar mod_reg_rm = getUChar(delta);
2534    delta++;
2535
2536    /* squeeze out the reg field from mod_reg_rm, since a 256-entry
2537       jump table seems a bit excessive. 
2538    */
2539    mod_reg_rm &= 0xC7;                         /* is now XX000YYY */
2540    mod_reg_rm  = toUChar(mod_reg_rm | (mod_reg_rm >> 3));
2541                                                /* is now XX0XXYYY */
2542    mod_reg_rm &= 0x1F;                         /* is now 000XXYYY */
2543    switch (mod_reg_rm) {
2544
2545       /* REX.B==0: (%rax) .. (%rdi), not including (%rsp) or (%rbp).
2546          REX.B==1: (%r8)  .. (%r15), not including (%r12) or (%r13).
2547       */
2548       case 0x00: case 0x01: case 0x02: case 0x03: 
2549       /* ! 04 */ /* ! 05 */ case 0x06: case 0x07:
2550          return 1;
2551
2552       /* REX.B==0: d8(%rax) ... d8(%rdi), not including d8(%rsp) 
2553          REX.B==1: d8(%r8)  ... d8(%r15), not including d8(%r12) 
2554       */
2555       case 0x08: case 0x09: case 0x0A: case 0x0B: 
2556       /* ! 0C */ case 0x0D: case 0x0E: case 0x0F:
2557          return 2;
2558
2559       /* REX.B==0: d32(%rax) ... d32(%rdi), not including d32(%rsp)
2560          REX.B==1: d32(%r8)  ... d32(%r15), not including d32(%r12)
2561       */
2562       case 0x10: case 0x11: case 0x12: case 0x13: 
2563       /* ! 14 */ case 0x15: case 0x16: case 0x17:
2564          return 5;
2565
2566       /* REX.B==0: a register, %rax .. %rdi.  This shouldn't happen. */
2567       /* REX.B==1: a register, %r8  .. %r16.  This shouldn't happen. */
2568       /* Not an address, but still handled. */
2569       case 0x18: case 0x19: case 0x1A: case 0x1B:
2570       case 0x1C: case 0x1D: case 0x1E: case 0x1F:
2571          return 1;
2572
2573       /* RIP + disp32. */
2574       case 0x05: 
2575          return 5;
2576
2577       case 0x04: {
2578          /* SIB, with no displacement. */
2579          UChar sib     = getUChar(delta);
2580          UChar base_r  = toUChar(sib & 7);
2581          /* correct since #(R13) == 8 + #(RBP) */
2582          Bool  base_is_BPor13 = toBool(base_r == R_RBP);
2583
2584          if (base_is_BPor13) {
2585             return 6;
2586          } else {
2587             return 2;
2588          }
2589       }
2590
2591       /* SIB, with 8-bit displacement. */
2592       case 0x0C:
2593          return 3;
2594
2595       /* SIB, with 32-bit displacement. */
2596       case 0x14:
2597          return 6;
2598
2599       default:
2600          vpanic("lengthAMode(amd64)");
2601          return 0; /*notreached*/
2602    }
2603 }
2604
2605
2606 /*------------------------------------------------------------*/
2607 /*--- Disassembling common idioms                          ---*/
2608 /*------------------------------------------------------------*/
2609
2610 /* Handle binary integer instructions of the form
2611       op E, G  meaning
2612       op reg-or-mem, reg
2613    Is passed the a ptr to the modRM byte, the actual operation, and the
2614    data size.  Returns the address advanced completely over this
2615    instruction.
2616
2617    E(src) is reg-or-mem
2618    G(dst) is reg.
2619
2620    If E is reg, -->    GET %G,  tmp
2621                        OP %E,   tmp
2622                        PUT tmp, %G
2623  
2624    If E is mem and OP is not reversible, 
2625                 -->    (getAddr E) -> tmpa
2626                        LD (tmpa), tmpa
2627                        GET %G, tmp2
2628                        OP tmpa, tmp2
2629                        PUT tmp2, %G
2630
2631    If E is mem and OP is reversible
2632                 -->    (getAddr E) -> tmpa
2633                        LD (tmpa), tmpa
2634                        OP %G, tmpa
2635                        PUT tmpa, %G
2636 */
2637 static
2638 ULong dis_op2_E_G ( VexAbiInfo* vbi,
2639                     Prefix      pfx,
2640                     Bool        addSubCarry,
2641                     IROp        op8, 
2642                     Bool        keep,
2643                     Int         size, 
2644                     Long        delta0,
2645                     HChar*      t_amd64opc )
2646 {
2647    HChar   dis_buf[50];
2648    Int     len;
2649    IRType  ty   = szToITy(size);
2650    IRTemp  dst1 = newTemp(ty);
2651    IRTemp  src  = newTemp(ty);
2652    IRTemp  dst0 = newTemp(ty);
2653    UChar   rm   = getUChar(delta0);
2654    IRTemp  addr = IRTemp_INVALID;
2655
2656    /* addSubCarry == True indicates the intended operation is
2657       add-with-carry or subtract-with-borrow. */
2658    if (addSubCarry) {
2659       vassert(op8 == Iop_Add8 || op8 == Iop_Sub8);
2660       vassert(keep);
2661    }
2662
2663    if (epartIsReg(rm)) {
2664       /* Specially handle XOR reg,reg, because that doesn't really
2665          depend on reg, and doing the obvious thing potentially
2666          generates a spurious value check failure due to the bogus
2667          dependency. */
2668       if ((op8 == Iop_Xor8 || (op8 == Iop_Sub8 && addSubCarry))
2669           && offsetIRegG(size,pfx,rm) == offsetIRegE(size,pfx,rm)) {
2670          if (False && op8 == Iop_Sub8)
2671             vex_printf("vex amd64->IR: sbb %%r,%%r optimisation(1)\n");
2672          putIRegG(size,pfx,rm, mkU(ty,0));
2673       }
2674
2675       assign( dst0, getIRegG(size,pfx,rm) );
2676       assign( src,  getIRegE(size,pfx,rm) );
2677
2678       if (addSubCarry && op8 == Iop_Add8) {
2679          helper_ADC( size, dst1, dst0, src,
2680                      /*no store*/IRTemp_INVALID, IRTemp_INVALID, 0 );
2681          putIRegG(size, pfx, rm, mkexpr(dst1));
2682       } else
2683       if (addSubCarry && op8 == Iop_Sub8) {
2684          helper_SBB( size, dst1, dst0, src,
2685                      /*no store*/IRTemp_INVALID, IRTemp_INVALID, 0 );
2686          putIRegG(size, pfx, rm, mkexpr(dst1));
2687       } else {
2688          assign( dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)) );
2689          if (isAddSub(op8))
2690             setFlags_DEP1_DEP2(op8, dst0, src, ty);
2691          else
2692             setFlags_DEP1(op8, dst1, ty);
2693          if (keep)
2694             putIRegG(size, pfx, rm, mkexpr(dst1));
2695       }
2696
2697       DIP("%s%c %s,%s\n", t_amd64opc, nameISize(size), 
2698                           nameIRegE(size,pfx,rm),
2699                           nameIRegG(size,pfx,rm));
2700       return 1+delta0;
2701    } else {
2702       /* E refers to memory */
2703       addr = disAMode ( &len, vbi, pfx, delta0, dis_buf, 0 );
2704       assign( dst0, getIRegG(size,pfx,rm) );
2705       assign( src,  loadLE(szToITy(size), mkexpr(addr)) );
2706
2707       if (addSubCarry && op8 == Iop_Add8) {
2708          helper_ADC( size, dst1, dst0, src,
2709                      /*no store*/IRTemp_INVALID, IRTemp_INVALID, 0 );
2710          putIRegG(size, pfx, rm, mkexpr(dst1));
2711       } else
2712       if (addSubCarry && op8 == Iop_Sub8) {
2713          helper_SBB( size, dst1, dst0, src,
2714                      /*no store*/IRTemp_INVALID, IRTemp_INVALID, 0 );
2715          putIRegG(size, pfx, rm, mkexpr(dst1));
2716       } else {
2717          assign( dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)) );
2718          if (isAddSub(op8))
2719             setFlags_DEP1_DEP2(op8, dst0, src, ty);
2720          else
2721             setFlags_DEP1(op8, dst1, ty);
2722          if (keep)
2723             putIRegG(size, pfx, rm, mkexpr(dst1));
2724       }
2725
2726       DIP("%s%c %s,%s\n", t_amd64opc, nameISize(size), 
2727                           dis_buf, nameIRegG(size, pfx, rm));
2728       return len+delta0;
2729    }
2730 }
2731
2732
2733
2734 /* Handle binary integer instructions of the form
2735       op G, E  meaning
2736       op reg, reg-or-mem
2737    Is passed the a ptr to the modRM byte, the actual operation, and the
2738    data size.  Returns the address advanced completely over this
2739    instruction.
2740
2741    G(src) is reg.
2742    E(dst) is reg-or-mem
2743
2744    If E is reg, -->    GET %E,  tmp
2745                        OP %G,   tmp
2746                        PUT tmp, %E
2747  
2748    If E is mem, -->    (getAddr E) -> tmpa
2749                        LD (tmpa), tmpv
2750                        OP %G, tmpv
2751                        ST tmpv, (tmpa)
2752 */
2753 static
2754 ULong dis_op2_G_E ( VexAbiInfo* vbi,
2755                     Prefix      pfx,
2756                     Bool        addSubCarry,
2757                     IROp        op8, 
2758                     Bool        keep,
2759                     Int         size, 
2760                     Long        delta0,
2761                     HChar*      t_amd64opc )
2762 {
2763    HChar   dis_buf[50];
2764    Int     len;
2765    IRType  ty   = szToITy(size);
2766    IRTemp  dst1 = newTemp(ty);
2767    IRTemp  src  = newTemp(ty);
2768    IRTemp  dst0 = newTemp(ty);
2769    UChar   rm   = getUChar(delta0);
2770    IRTemp  addr = IRTemp_INVALID;
2771
2772    /* addSubCarry == True indicates the intended operation is
2773       add-with-carry or subtract-with-borrow. */
2774    if (addSubCarry) {
2775       vassert(op8 == Iop_Add8 || op8 == Iop_Sub8);
2776       vassert(keep);
2777    }
2778
2779    if (epartIsReg(rm)) {
2780       /* Specially handle XOR reg,reg, because that doesn't really
2781          depend on reg, and doing the obvious thing potentially
2782          generates a spurious value check failure due to the bogus
2783          dependency.  Ditto SBB reg,reg. */
2784       if ((op8 == Iop_Xor8 || (op8 == Iop_Sub8 && addSubCarry))
2785           && offsetIRegG(size,pfx,rm) == offsetIRegE(size,pfx,rm)) {
2786          putIRegE(size,pfx,rm, mkU(ty,0));
2787       }
2788
2789       assign(dst0, getIRegE(size,pfx,rm));
2790       assign(src,  getIRegG(size,pfx,rm));
2791
2792       if (addSubCarry && op8 == Iop_Add8) {
2793          helper_ADC( size, dst1, dst0, src,
2794                      /*no store*/IRTemp_INVALID, IRTemp_INVALID, 0 );
2795          putIRegE(size, pfx, rm, mkexpr(dst1));
2796       } else
2797       if (addSubCarry && op8 == Iop_Sub8) {
2798          helper_SBB( size, dst1, dst0, src,
2799                      /*no store*/IRTemp_INVALID, IRTemp_INVALID, 0 );
2800          putIRegE(size, pfx, rm, mkexpr(dst1));
2801       } else {
2802          assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)));
2803          if (isAddSub(op8))
2804             setFlags_DEP1_DEP2(op8, dst0, src, ty);
2805          else
2806             setFlags_DEP1(op8, dst1, ty);
2807          if (keep)
2808             putIRegE(size, pfx, rm, mkexpr(dst1));
2809       }
2810
2811       DIP("%s%c %s,%s\n", t_amd64opc, nameISize(size), 
2812                           nameIRegG(size,pfx,rm),
2813                           nameIRegE(size,pfx,rm));
2814       return 1+delta0;
2815    }
2816
2817    /* E refers to memory */    
2818    {
2819       addr = disAMode ( &len, vbi, pfx, delta0, dis_buf, 0 );
2820       assign(dst0, loadLE(ty,mkexpr(addr)));
2821       assign(src,  getIRegG(size,pfx,rm));
2822
2823       if (addSubCarry && op8 == Iop_Add8) {
2824          if (pfx & PFX_LOCK) {
2825             /* cas-style store */
2826             helper_ADC( size, dst1, dst0, src,
2827                         /*store*/addr, dst0/*expVal*/, guest_RIP_curr_instr );
2828          } else {
2829             /* normal store */
2830             helper_ADC( size, dst1, dst0, src,
2831                         /*store*/addr, IRTemp_INVALID, 0 );
2832          }
2833       } else
2834       if (addSubCarry && op8 == Iop_Sub8) {
2835          if (pfx & PFX_LOCK) {
2836             /* cas-style store */
2837             helper_SBB( size, dst1, dst0, src,
2838                         /*store*/addr, dst0/*expVal*/, guest_RIP_curr_instr );
2839          } else {
2840             /* normal store */
2841             helper_SBB( size, dst1, dst0, src,
2842                         /*store*/addr, IRTemp_INVALID, 0 );
2843          }
2844       } else {
2845          assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)));
2846          if (keep) {
2847             if (pfx & PFX_LOCK) {
2848                if (0) vex_printf("locked case\n" );
2849                casLE( mkexpr(addr),
2850                       mkexpr(dst0)/*expval*/, 
2851                       mkexpr(dst1)/*newval*/, guest_RIP_curr_instr );
2852             } else {
2853                if (0) vex_printf("nonlocked case\n");
2854                storeLE(mkexpr(addr), mkexpr(dst1));
2855             }
2856          }
2857          if (isAddSub(op8))
2858             setFlags_DEP1_DEP2(op8, dst0, src, ty);
2859          else
2860             setFlags_DEP1(op8, dst1, ty);
2861       }
2862
2863       DIP("%s%c %s,%s\n", t_amd64opc, nameISize(size), 
2864                           nameIRegG(size,pfx,rm), dis_buf);
2865       return len+delta0;
2866    }
2867 }
2868
2869
2870 /* Handle move instructions of the form
2871       mov E, G  meaning
2872       mov reg-or-mem, reg
2873    Is passed the a ptr to the modRM byte, and the data size.  Returns
2874    the address advanced completely over this instruction.
2875
2876    E(src) is reg-or-mem
2877    G(dst) is reg.
2878
2879    If E is reg, -->    GET %E,  tmpv
2880                        PUT tmpv, %G
2881  
2882    If E is mem  -->    (getAddr E) -> tmpa
2883                        LD (tmpa), tmpb
2884                        PUT tmpb, %G
2885 */
2886 static
2887 ULong dis_mov_E_G ( VexAbiInfo* vbi,
2888                     Prefix      pfx,
2889                     Int         size, 
2890                     Long        delta0 )
2891 {
2892    Int len;
2893    UChar rm = getUChar(delta0);
2894    HChar dis_buf[50];
2895
2896    if (epartIsReg(rm)) {
2897       putIRegG(size, pfx, rm, getIRegE(size, pfx, rm));
2898       DIP("mov%c %s,%s\n", nameISize(size),
2899                            nameIRegE(size,pfx,rm),
2900                            nameIRegG(size,pfx,rm));
2901       return 1+delta0;
2902    }
2903
2904    /* E refers to memory */    
2905    {
2906       IRTemp addr = disAMode ( &len, vbi, pfx, delta0, dis_buf, 0 );
2907       putIRegG(size, pfx, rm, loadLE(szToITy(size), mkexpr(addr)));
2908       DIP("mov%c %s,%s\n", nameISize(size), 
2909                            dis_buf,
2910                            nameIRegG(size,pfx,rm));
2911       return delta0+len;
2912    }
2913 }
2914
2915
2916 /* Handle move instructions of the form
2917       mov G, E  meaning
2918       mov reg, reg-or-mem
2919    Is passed the a ptr to the modRM byte, and the data size.  Returns
2920    the address advanced completely over this instruction.
2921
2922    G(src) is reg.
2923    E(dst) is reg-or-mem
2924
2925    If E is reg, -->    GET %G,  tmp
2926                        PUT tmp, %E
2927  
2928    If E is mem, -->    (getAddr E) -> tmpa
2929                        GET %G, tmpv
2930                        ST tmpv, (tmpa) 
2931 */
2932 static
2933 ULong dis_mov_G_E ( VexAbiInfo* vbi,
2934                     Prefix      pfx,
2935                     Int         size, 
2936                     Long        delta0 )
2937 {
2938    Int len;
2939    UChar rm = getUChar(delta0);
2940    HChar dis_buf[50];
2941
2942    if (epartIsReg(rm)) {
2943       putIRegE(size, pfx, rm, getIRegG(size, pfx, rm));
2944       DIP("mov%c %s,%s\n", nameISize(size),
2945                            nameIRegG(size,pfx,rm),
2946                            nameIRegE(size,pfx,rm));
2947       return 1+delta0;
2948    }
2949
2950    /* E refers to memory */    
2951    {
2952       IRTemp addr = disAMode ( &len, vbi, pfx, delta0, dis_buf, 0 );
2953       storeLE( mkexpr(addr), getIRegG(size, pfx, rm) );
2954       DIP("mov%c %s,%s\n", nameISize(size), 
2955                            nameIRegG(size,pfx,rm), 
2956                            dis_buf);
2957       return len+delta0;
2958    }
2959 }
2960
2961
2962 /* op $immediate, AL/AX/EAX/RAX. */
2963 static
2964 ULong dis_op_imm_A ( Int    size,
2965                      Bool   carrying,
2966                      IROp   op8,
2967                      Bool   keep,
2968                      Long   delta,
2969                      HChar* t_amd64opc )
2970 {
2971    Int    size4 = imin(size,4);
2972    IRType ty    = szToITy(size);
2973    IRTemp dst0  = newTemp(ty);
2974    IRTemp src   = newTemp(ty);
2975    IRTemp dst1  = newTemp(ty);
2976    Long  lit    = getSDisp(size4,delta);
2977    assign(dst0, getIRegRAX(size));
2978    assign(src,  mkU(ty,lit & mkSizeMask(size)));
2979
2980    if (isAddSub(op8) && !carrying) {
2981       assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)) );
2982       setFlags_DEP1_DEP2(op8, dst0, src, ty);
2983    }
2984    else
2985    if (isLogic(op8)) {
2986       vassert(!carrying);
2987       assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)) );
2988       setFlags_DEP1(op8, dst1, ty);
2989    }
2990    else
2991    if (op8 == Iop_Add8 && carrying) {
2992       helper_ADC( size, dst1, dst0, src,
2993                   /*no store*/IRTemp_INVALID, IRTemp_INVALID, 0 );
2994    }
2995    else
2996    if (op8 == Iop_Sub8 && carrying) {
2997       helper_SBB( size, dst1, dst0, src,
2998                   /*no store*/IRTemp_INVALID, IRTemp_INVALID, 0 );
2999    }
3000    else
3001       vpanic("dis_op_imm_A(amd64,guest)");
3002
3003    if (keep)
3004       putIRegRAX(size, mkexpr(dst1));
3005
3006    DIP("%s%c $%lld, %s\n", t_amd64opc, nameISize(size), 
3007                            lit, nameIRegRAX(size));
3008    return delta+size4;
3009 }
3010
3011
3012 /* Sign- and Zero-extending moves. */
3013 static
3014 ULong dis_movx_E_G ( VexAbiInfo* vbi,
3015                      Prefix pfx,
3016                      Long delta, Int szs, Int szd, Bool sign_extend )
3017 {
3018    UChar rm = getUChar(delta);
3019    if (epartIsReg(rm)) {
3020       putIRegG(szd, pfx, rm,
3021                     doScalarWidening(
3022                        szs,szd,sign_extend,
3023                        getIRegE(szs,pfx,rm)));
3024       DIP("mov%c%c%c %s,%s\n", sign_extend ? 's' : 'z',
3025                                nameISize(szs), 
3026                                nameISize(szd),
3027                                nameIRegE(szs,pfx,rm),
3028                                nameIRegG(szd,pfx,rm));
3029       return 1+delta;
3030    }
3031
3032    /* E refers to memory */    
3033    {
3034       Int    len;
3035       HChar  dis_buf[50];
3036       IRTemp addr = disAMode ( &len, vbi, pfx, delta, dis_buf, 0 );
3037       putIRegG(szd, pfx, rm,
3038                     doScalarWidening(
3039                        szs,szd,sign_extend, 
3040                        loadLE(szToITy(szs),mkexpr(addr))));
3041       DIP("mov%c%c%c %s,%s\n", sign_extend ? 's' : 'z',
3042                                nameISize(szs), 
3043                                nameISize(szd),
3044                                dis_buf, 
3045                                nameIRegG(szd,pfx,rm));
3046       return len+delta;
3047    }
3048 }
3049
3050
3051 /* Generate code to divide ArchRegs RDX:RAX / EDX:EAX / DX:AX / AX by
3052    the 64 / 32 / 16 / 8 bit quantity in the given IRTemp.  */
3053 static
3054 void codegen_div ( Int sz, IRTemp t, Bool signed_divide )
3055 {
3056    /* special-case the 64-bit case */
3057    if (sz == 8) {
3058       IROp   op     = signed_divide ? Iop_DivModS128to64 
3059                                     : Iop_DivModU128to64;
3060       IRTemp src128 = newTemp(Ity_I128);
3061       IRTemp dst128 = newTemp(Ity_I128);
3062       assign( src128, binop(Iop_64HLto128, 
3063                             getIReg64(R_RDX), 
3064                             getIReg64(R_RAX)) );
3065       assign( dst128, binop(op, mkexpr(src128), mkexpr(t)) );
3066       putIReg64( R_RAX, unop(Iop_128to64,mkexpr(dst128)) );
3067       putIReg64( R_RDX, unop(Iop_128HIto64,mkexpr(dst128)) );
3068    } else {
3069       IROp   op    = signed_divide ? Iop_DivModS64to32 
3070                                    : Iop_DivModU64to32;
3071       IRTemp src64 = newTemp(Ity_I64);
3072       IRTemp dst64 = newTemp(Ity_I64);
3073       switch (sz) {
3074       case 4:
3075          assign( src64, 
3076                  binop(Iop_32HLto64, getIRegRDX(4), getIRegRAX(4)) );
3077          assign( dst64, 
3078                  binop(op, mkexpr(src64), mkexpr(t)) );
3079          putIRegRAX( 4, unop(Iop_64to32,mkexpr(dst64)) );
3080          putIRegRDX( 4, unop(Iop_64HIto32,mkexpr(dst64)) );
3081          break;
3082       case 2: {
3083          IROp widen3264 = signed_divide ? Iop_32Sto64 : Iop_32Uto64;
3084          IROp widen1632 = signed_divide ? Iop_16Sto32 : Iop_16Uto32;
3085          assign( src64, unop(widen3264,
3086                              binop(Iop_16HLto32, 
3087                                    getIRegRDX(2), 
3088                                    getIRegRAX(2))) );
3089          assign( dst64, binop(op, mkexpr(src64), unop(widen1632,mkexpr(t))) );
3090          putIRegRAX( 2, unop(Iop_32to16,unop(Iop_64to32,mkexpr(dst64))) );
3091          putIRegRDX( 2, unop(Iop_32to16,unop(Iop_64HIto32,mkexpr(dst64))) );
3092          break;
3093       }
3094       case 1: {
3095          IROp widen3264 = signed_divide ? Iop_32Sto64 : Iop_32Uto64;
3096          IROp widen1632 = signed_divide ? Iop_16Sto32 : Iop_16Uto32;
3097          IROp widen816  = signed_divide ? Iop_8Sto16  : Iop_8Uto16;
3098          assign( src64, unop(widen3264, 
3099                         unop(widen1632, getIRegRAX(2))) );
3100          assign( dst64, 
3101                  binop(op, mkexpr(src64), 
3102                            unop(widen1632, unop(widen816, mkexpr(t)))) );
3103          putIRegRAX( 1, unop(Iop_16to8, 
3104                         unop(Iop_32to16,
3105                         unop(Iop_64to32,mkexpr(dst64)))) );
3106          putIRegAH( unop(Iop_16to8, 
3107                     unop(Iop_32to16,
3108                     unop(Iop_64HIto32,mkexpr(dst64)))) );
3109          break;
3110       }
3111       default: 
3112          vpanic("codegen_div(amd64)");
3113       }
3114    }
3115 }
3116
3117 static 
3118 ULong dis_Grp1 ( VexAbiInfo* vbi,
3119                  Prefix pfx,
3120                  Long delta, UChar modrm, 
3121                  Int am_sz, Int d_sz, Int sz, Long d64 )
3122 {
3123    Int     len;
3124    HChar   dis_buf[50];
3125    IRType  ty   = szToITy(sz);
3126    IRTemp  dst1 = newTemp(ty);
3127    IRTemp  src  = newTemp(ty);
3128    IRTemp  dst0 = newTemp(ty);
3129    IRTemp  addr = IRTemp_INVALID;
3130    IROp    op8  = Iop_INVALID;
3131    ULong   mask = mkSizeMask(sz);
3132
3133    switch (gregLO3ofRM(modrm)) {
3134       case 0: op8 = Iop_Add8; break;  case 1: op8 = Iop_Or8;  break;
3135       case 2: break;  // ADC
3136       case 3: break;  // SBB
3137       case 4: op8 = Iop_And8; break;  case 5: op8 = Iop_Sub8; break;
3138       case 6: op8 = Iop_Xor8; break;  case 7: op8 = Iop_Sub8; break;
3139       /*NOTREACHED*/
3140       default: vpanic("dis_Grp1(amd64): unhandled case");
3141    }
3142
3143    if (epartIsReg(modrm)) {
3144       vassert(am_sz == 1);
3145
3146       assign(dst0, getIRegE(sz,pfx,modrm));
3147       assign(src,  mkU(ty,d64 & mask));
3148
3149       if (gregLO3ofRM(modrm) == 2 /* ADC */) {
3150          helper_ADC( sz, dst1, dst0, src,
3151                      /*no store*/IRTemp_INVALID, IRTemp_INVALID, 0 );
3152       } else 
3153       if (gregLO3ofRM(modrm) == 3 /* SBB */) {
3154          helper_SBB( sz, dst1, dst0, src,
3155                      /*no store*/IRTemp_INVALID, IRTemp_INVALID, 0 );
3156       } else {
3157          assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)));
3158          if (isAddSub(op8))
3159             setFlags_DEP1_DEP2(op8, dst0, src, ty);
3160          else
3161             setFlags_DEP1(op8, dst1, ty);
3162       }
3163
3164       if (gregLO3ofRM(modrm) < 7)
3165          putIRegE(sz, pfx, modrm, mkexpr(dst1));
3166
3167       delta += (am_sz + d_sz);
3168       DIP("%s%c $%lld, %s\n", 
3169           nameGrp1(gregLO3ofRM(modrm)), nameISize(sz), d64, 
3170           nameIRegE(sz,pfx,modrm));
3171    } else {
3172       addr = disAMode ( &len, vbi, pfx, delta, dis_buf, /*xtra*/d_sz );
3173
3174       assign(dst0, loadLE(ty,mkexpr(addr)));
3175       assign(src, mkU(ty,d64 & mask));
3176
3177       if (gregLO3ofRM(modrm) == 2 /* ADC */) {
3178          if (pfx & PFX_LOCK) {
3179             /* cas-style store */
3180             helper_ADC( sz, dst1, dst0, src,
3181                        /*store*/addr, dst0/*expVal*/, guest_RIP_curr_instr );
3182          } else {
3183             /* normal store */
3184             helper_ADC( sz, dst1, dst0, src,
3185                         /*store*/addr, IRTemp_INVALID, 0 );
3186          }
3187       } else 
3188       if (gregLO3ofRM(modrm) == 3 /* SBB */) {
3189          if (pfx & PFX_LOCK) {
3190             /* cas-style store */
3191             helper_SBB( sz, dst1, dst0, src,
3192                        /*store*/addr, dst0/*expVal*/, guest_RIP_curr_instr );
3193          } else {
3194             /* normal store */
3195             helper_SBB( sz, dst1, dst0, src,
3196                         /*store*/addr, IRTemp_INVALID, 0 );
3197          }
3198       } else {
3199          assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)));
3200          if (gregLO3ofRM(modrm) < 7) {
3201             if (pfx & PFX_LOCK) {
3202                casLE( mkexpr(addr), mkexpr(dst0)/*expVal*/, 
3203                                     mkexpr(dst1)/*newVal*/,
3204                                     guest_RIP_curr_instr );
3205             } else {
3206                storeLE(mkexpr(addr), mkexpr(dst1));
3207             }
3208          }
3209          if (isAddSub(op8))
3210             setFlags_DEP1_DEP2(op8, dst0, src, ty);
3211          else
3212             setFlags_DEP1(op8, dst1, ty);
3213       }
3214
3215       delta += (len+d_sz);
3216       DIP("%s%c $%lld, %s\n", 
3217           nameGrp1(gregLO3ofRM(modrm)), nameISize(sz),
3218           d64, dis_buf);
3219    }
3220    return delta;
3221 }
3222
3223
3224 /* Group 2 extended opcodes.  shift_expr must be an 8-bit typed
3225    expression. */
3226
3227 static
3228 ULong dis_Grp2 ( VexAbiInfo* vbi,
3229                  Prefix pfx,
3230                  Long delta, UChar modrm,
3231                  Int am_sz, Int d_sz, Int sz, IRExpr* shift_expr,
3232                  HChar* shift_expr_txt, Bool* decode_OK )
3233 {
3234    /* delta on entry points at the modrm byte. */
3235    HChar  dis_buf[50];
3236    Int    len;
3237    Bool   isShift, isRotate, isRotateC;
3238    IRType ty    = szToITy(sz);
3239    IRTemp dst0  = newTemp(ty);
3240    IRTemp dst1  = newTemp(ty);
3241    IRTemp addr  = IRTemp_INVALID;
3242
3243    *decode_OK = True;
3244
3245    vassert(sz == 1 || sz == 2 || sz == 4 || sz == 8);
3246
3247    /* Put value to shift/rotate in dst0. */
3248    if (epartIsReg(modrm)) {
3249       assign(dst0, getIRegE(sz, pfx, modrm));
3250       delta += (am_sz + d_sz);
3251    } else {
3252       addr = disAMode ( &len, vbi, pfx, delta, dis_buf, /*xtra*/d_sz );
3253       assign(dst0, loadLE(ty,mkexpr(addr)));
3254       delta += len + d_sz;
3255    }
3256
3257    isShift = False;
3258    switch (gregLO3ofRM(modrm)) { case 4: case 5: case 7: isShift = True; }
3259
3260    isRotate = False;
3261    switch (gregLO3ofRM(modrm)) { case 0: case 1: isRotate = True; }
3262
3263    isRotateC = False;
3264    switch (gregLO3ofRM(modrm)) { case 2: case 3: isRotateC = True; }
3265
3266    if (gregLO3ofRM(modrm) == 6) {
3267       *decode_OK = False;
3268       return delta;
3269    }
3270
3271    if (!isShift && !isRotate && !isRotateC) {
3272       /*NOTREACHED*/
3273       vpanic("dis_Grp2(Reg): unhandled case(amd64)");
3274    }
3275
3276    if (isRotateC) {
3277       /* Call a helper; this insn is so ridiculous it does not deserve
3278          better.  One problem is, the helper has to calculate both the
3279          new value and the new flags.  This is more than 64 bits, and
3280          there is no way to return more than 64 bits from the helper.
3281          Hence the crude and obvious solution is to call it twice,
3282          using the sign of the sz field to indicate whether it is the
3283          value or rflags result we want.
3284       */
3285       Bool     left = toBool(gregLO3ofRM(modrm) == 2);
3286       IRExpr** argsVALUE;
3287       IRExpr** argsRFLAGS;
3288
3289       IRTemp new_value  = newTemp(Ity_I64);
3290       IRTemp new_rflags = newTemp(Ity_I64);
3291       IRTemp old_rflags = newTemp(Ity_I64);
3292
3293       assign( old_rflags, widenUto64(mk_amd64g_calculate_rflags_all()) );
3294
3295       argsVALUE
3296          = mkIRExprVec_4( widenUto64(mkexpr(dst0)), /* thing to rotate */
3297                           widenUto64(shift_expr),   /* rotate amount */
3298                           mkexpr(old_rflags),
3299                           mkU64(sz) );
3300       assign( new_value, 
3301                  mkIRExprCCall(
3302                     Ity_I64, 
3303                     0/*regparm*/, 
3304                     left ? "amd64g_calculate_RCL" : "amd64g_calculate_RCR",
3305                     left ? &amd64g_calculate_RCL  : &amd64g_calculate_RCR,
3306                     argsVALUE
3307                  )
3308             );
3309       
3310       argsRFLAGS
3311          = mkIRExprVec_4( widenUto64(mkexpr(dst0)), /* thing to rotate */
3312                           widenUto64(shift_expr),   /* rotate amount */
3313                           mkexpr(old_rflags),
3314                           mkU64(-sz) );
3315       assign( new_rflags, 
3316                  mkIRExprCCall(
3317                     Ity_I64, 
3318                     0/*regparm*/, 
3319                     left ? "amd64g_calculate_RCL" : "amd64g_calculate_RCR",
3320                     left ? &amd64g_calculate_RCL  : &amd64g_calculate_RCR,
3321                     argsRFLAGS
3322                  )
3323             );
3324
3325       assign( dst1, narrowTo(ty, mkexpr(new_value)) );
3326       stmt( IRStmt_Put( OFFB_CC_OP,   mkU64(AMD64G_CC_OP_COPY) ));
3327       stmt( IRStmt_Put( OFFB_CC_DEP1, mkexpr(new_rflags) ));
3328       stmt( IRStmt_Put( OFFB_CC_DEP2, mkU64(0) ));
3329       stmt( IRStmt_Put( OFFB_CC_NDEP, mkU64(0) ));
3330    }
3331
3332    else
3333    if (isShift) {
3334
3335       IRTemp pre64     = newTemp(Ity_I64);
3336       IRTemp res64     = newTemp(Ity_I64);
3337       IRTemp res64ss   = newTemp(Ity_I64);
3338       IRTemp shift_amt = newTemp(Ity_I8);
3339       UChar  mask      = toUChar(sz==8 ? 63 : 31);
3340       IROp   op64;
3341
3342       switch (gregLO3ofRM(modrm)) { 
3343          case 4: op64 = Iop_Shl64; break;
3344          case 5: op64 = Iop_Shr64; break;
3345          case 7: op64 = Iop_Sar64; break;
3346          /*NOTREACHED*/
3347          default: vpanic("dis_Grp2:shift"); break;
3348       }
3349
3350       /* Widen the value to be shifted to 64 bits, do the shift, and
3351          narrow back down.  This seems surprisingly long-winded, but
3352          unfortunately the AMD semantics requires that 8/16/32-bit
3353          shifts give defined results for shift values all the way up
3354          to 32, and this seems the simplest way to do it.  It has the
3355          advantage that the only IR level shifts generated are of 64
3356          bit values, and the shift amount is guaranteed to be in the
3357          range 0 .. 63, thereby observing the IR semantics requiring
3358          all shift values to be in the range 0 .. 2^word_size-1. 
3359
3360          Therefore the shift amount is masked with 63 for 64-bit shifts
3361          and 31 for all others.
3362       */
3363       /* shift_amt = shift_expr & MASK, regardless of operation size */
3364       assign( shift_amt, binop(Iop_And8, shift_expr, mkU8(mask)) );
3365
3366       /* suitably widen the value to be shifted to 64 bits. */
3367       assign( pre64, op64==Iop_Sar64 ? widenSto64(mkexpr(dst0))
3368                                      : widenUto64(mkexpr(dst0)) );
3369
3370       /* res64 = pre64 `shift` shift_amt */
3371       assign( res64, binop(op64, mkexpr(pre64), mkexpr(shift_amt)) );
3372
3373       /* res64ss = pre64 `shift` ((shift_amt - 1) & MASK) */
3374       assign( res64ss,
3375               binop(op64,
3376                     mkexpr(pre64), 
3377                     binop(Iop_And8,
3378                           binop(Iop_Sub8,
3379                                 mkexpr(shift_amt), mkU8(1)),
3380                           mkU8(mask))) );
3381
3382       /* Build the flags thunk. */
3383       setFlags_DEP1_DEP2_shift(op64, res64, res64ss, ty, shift_amt);
3384
3385       /* Narrow the result back down. */
3386       assign( dst1, narrowTo(ty, mkexpr(res64)) );
3387
3388    } /* if (isShift) */
3389
3390    else 
3391    if (isRotate) {
3392       Int    ccOp      = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 
3393                                         : (ty==Ity_I32 ? 2 : 3));
3394       Bool   left      = toBool(gregLO3ofRM(modrm) == 0);
3395       IRTemp rot_amt   = newTemp(Ity_I8);
3396       IRTemp rot_amt64 = newTemp(Ity_I8);
3397       IRTemp oldFlags  = newTemp(Ity_I64);
3398       UChar  mask      = toUChar(sz==8 ? 63 : 31);
3399
3400       /* rot_amt = shift_expr & mask */
3401       /* By masking the rotate amount thusly, the IR-level Shl/Shr
3402          expressions never shift beyond the word size and thus remain
3403          well defined. */
3404       assign(rot_amt64, binop(Iop_And8, shift_expr, mkU8(mask)));
3405
3406       if (ty == Ity_I64)
3407          assign(rot_amt, mkexpr(rot_amt64));
3408       else
3409          assign(rot_amt, binop(Iop_And8, mkexpr(rot_amt64), mkU8(8*sz-1)));
3410
3411       if (left) {
3412
3413          /* dst1 = (dst0 << rot_amt) | (dst0 >>u (wordsize-rot_amt)) */
3414          assign(dst1, 
3415             binop( mkSizedOp(ty,Iop_Or8),
3416                    binop( mkSizedOp(ty,Iop_Shl8), 
3417                           mkexpr(dst0),
3418                           mkexpr(rot_amt)
3419                    ),
3420                    binop( mkSizedOp(ty,Iop_Shr8), 
3421                           mkexpr(dst0), 
3422                           binop(Iop_Sub8,mkU8(8*sz), mkexpr(rot_amt))
3423                    )
3424             )
3425          );
3426          ccOp += AMD64G_CC_OP_ROLB;
3427
3428       } else { /* right */
3429
3430          /* dst1 = (dst0 >>u rot_amt) | (dst0 << (wordsize-rot_amt)) */
3431          assign(dst1, 
3432             binop( mkSizedOp(ty,Iop_Or8),
3433                    binop( mkSizedOp(ty,Iop_Shr8), 
3434                           mkexpr(dst0),
3435                           mkexpr(rot_amt)
3436                    ),
3437                    binop( mkSizedOp(ty,Iop_Shl8), 
3438                           mkexpr(dst0), 
3439                           binop(Iop_Sub8,mkU8(8*sz), mkexpr(rot_amt))
3440                    )
3441             )
3442          );
3443          ccOp += AMD64G_CC_OP_RORB;
3444
3445       }
3446
3447       /* dst1 now holds the rotated value.  Build flag thunk.  We
3448          need the resulting value for this, and the previous flags.
3449          Except don't set it if the rotate count is zero. */
3450
3451       assign(oldFlags, mk_amd64g_calculate_rflags_all());
3452
3453       /* CC_DEP1 is the rotated value.  CC_NDEP is flags before. */
3454       stmt( IRStmt_Put( OFFB_CC_OP,
3455                         IRExpr_Mux0X( mkexpr(rot_amt64),
3456                                       IRExpr_Get(OFFB_CC_OP,Ity_I64),
3457                                       mkU64(ccOp))) );
3458       stmt( IRStmt_Put( OFFB_CC_DEP1, 
3459                         IRExpr_Mux0X( mkexpr(rot_amt64),
3460                                       IRExpr_Get(OFFB_CC_DEP1,Ity_I64),
3461                                       widenUto64(mkexpr(dst1)))) );
3462       stmt( IRStmt_Put( OFFB_CC_DEP2, 
3463                         IRExpr_Mux0X( mkexpr(rot_amt64),
3464                                       IRExpr_Get(OFFB_CC_DEP2,Ity_I64),
3465                                       mkU64(0))) );
3466       stmt( IRStmt_Put( OFFB_CC_NDEP, 
3467                         IRExpr_Mux0X( mkexpr(rot_amt64),
3468                                       IRExpr_Get(OFFB_CC_NDEP,Ity_I64),
3469                                       mkexpr(oldFlags))) );
3470    } /* if (isRotate) */
3471
3472    /* Save result, and finish up. */
3473    if (epartIsReg(modrm)) {
3474       putIRegE(sz, pfx, modrm, mkexpr(dst1));
3475       if (vex_traceflags & VEX_TRACE_FE) {
3476          vex_printf("%s%c ",
3477                     nameGrp2(gregLO3ofRM(modrm)), nameISize(sz) );
3478          if (shift_expr_txt)
3479             vex_printf("%s", shift_expr_txt);
3480          else
3481             ppIRExpr(shift_expr);
3482          vex_printf(", %s\n", nameIRegE(sz,pfx,modrm));
3483       }
3484    } else {
3485       storeLE(mkexpr(addr), mkexpr(dst1));
3486       if (vex_traceflags & VEX_TRACE_FE) {
3487          vex_printf("%s%c ",
3488                     nameGrp2(gregLO3ofRM(modrm)), nameISize(sz) );
3489          if (shift_expr_txt)
3490             vex_printf("%s", shift_expr_txt);
3491          else
3492             ppIRExpr(shift_expr);
3493          vex_printf(", %s\n", dis_buf);
3494       }
3495    }
3496    return delta;
3497 }
3498
3499
3500 /* Group 8 extended opcodes (but BT/BTS/BTC/BTR only). */
3501 static
3502 ULong dis_Grp8_Imm ( VexAbiInfo* vbi,
3503                      Prefix pfx,
3504                      Long delta, UChar modrm,
3505                      Int am_sz, Int sz, ULong src_val,
3506                      Bool* decode_OK )
3507 {
3508    /* src_val denotes a d8.
3509       And delta on entry points at the modrm byte. */
3510
3511    IRType ty     = szToITy(sz);
3512    IRTemp t2     = newTemp(Ity_I64);
3513    IRTemp t2m    = newTemp(Ity_I64);
3514    IRTemp t_addr = IRTemp_INVALID;
3515    HChar  dis_buf[50];
3516    ULong  mask;
3517
3518    /* we're optimists :-) */
3519    *decode_OK = True;
3520
3521    /* Limit src_val -- the bit offset -- to something within a word.
3522       The Intel docs say that literal offsets larger than a word are
3523       masked in this way. */
3524    switch (sz) {
3525       case 2:  src_val &= 15; break;
3526       case 4:  src_val &= 31; break;
3527       case 8:  src_val &= 63; break;
3528       default: *decode_OK = False; return delta;
3529    }
3530
3531    /* Invent a mask suitable for the operation. */
3532    switch (gregLO3ofRM(modrm)) {
3533       case 4: /* BT */  mask = 0;                  break;
3534       case 5: /* BTS */ mask = 1ULL << src_val;    break;
3535       case 6: /* BTR */ mask = ~(1ULL << src_val); break;
3536       case 7: /* BTC */ mask = 1ULL << src_val;    break;
3537          /* If this needs to be extended, probably simplest to make a
3538             new function to handle the other cases (0 .. 3).  The
3539             Intel docs do however not indicate any use for 0 .. 3, so
3540             we don't expect this to happen. */
3541       default: *decode_OK = False; return delta;
3542    }
3543
3544    /* Fetch the value to be tested and modified into t2, which is
3545       64-bits wide regardless of sz. */
3546    if (epartIsReg(modrm)) {
3547       vassert(am_sz == 1);
3548       assign( t2, widenUto64(getIRegE(sz, pfx, modrm)) );
3549       delta += (am_sz + 1);
3550       DIP("%s%c $0x%llx, %s\n", nameGrp8(gregLO3ofRM(modrm)), 
3551                                 nameISize(sz),
3552                                 src_val, nameIRegE(sz,pfx,modrm));
3553    } else {
3554       Int len;
3555       t_addr = disAMode ( &len, vbi, pfx, delta, dis_buf, 1 );
3556       delta  += (len+1);
3557       assign( t2, widenUto64(loadLE(ty, mkexpr(t_addr))) );
3558       DIP("%s%c $0x%llx, %s\n", nameGrp8(gregLO3ofRM(modrm)), 
3559                                 nameISize(sz),
3560                                 src_val, dis_buf);
3561    }
3562
3563    /* Compute the new value into t2m, if non-BT. */
3564    switch (gregLO3ofRM(modrm)) {
3565       case 4: /* BT */
3566          break;
3567       case 5: /* BTS */
3568          assign( t2m, binop(Iop_Or64, mkU64(mask), mkexpr(t2)) );
3569          break;
3570       case 6: /* BTR */
3571          assign( t2m, binop(Iop_And64, mkU64(mask), mkexpr(t2)) );
3572          break;
3573       case 7: /* BTC */
3574          assign( t2m, binop(Iop_Xor64, mkU64(mask), mkexpr(t2)) );
3575          break;
3576      default: 
3577          /*NOTREACHED*/ /*the previous switch guards this*/
3578          vassert(0);
3579    }
3580
3581    /* Write the result back, if non-BT. */
3582    if (gregLO3ofRM(modrm) != 4 /* BT */) {
3583       if (epartIsReg(modrm)) {
3584         putIRegE(sz, pfx, modrm, narrowTo(ty, mkexpr(t2m)));
3585       } else {
3586          if (pfx & PFX_LOCK) {
3587             casLE( mkexpr(t_addr),
3588                    narrowTo(ty, mkexpr(t2))/*expd*/,
3589                    narrowTo(ty, mkexpr(t2m))/*new*/,
3590                    guest_RIP_curr_instr );
3591          } else {
3592             storeLE(mkexpr(t_addr), narrowTo(ty, mkexpr(t2m)));
3593          }
3594       }
3595    }
3596
3597    /* Copy relevant bit from t2 into the carry flag. */
3598    /* Flags: C=selected bit, O,S,Z,A,P undefined, so are set to zero. */
3599    stmt( IRStmt_Put( OFFB_CC_OP,   mkU64(AMD64G_CC_OP_COPY) ));
3600    stmt( IRStmt_Put( OFFB_CC_DEP2, mkU64(0) ));
3601    stmt( IRStmt_Put( 
3602             OFFB_CC_DEP1,
3603             binop(Iop_And64,
3604                   binop(Iop_Shr64, mkexpr(t2), mkU8(src_val)),
3605                   mkU64(1))
3606        ));
3607    /* Set NDEP even though it isn't used.  This makes redundant-PUT
3608       elimination of previous stores to this field work better. */
3609    stmt( IRStmt_Put( OFFB_CC_NDEP, mkU64(0) ));
3610
3611    return delta;
3612 }
3613
3614
3615 /* Signed/unsigned widening multiply.  Generate IR to multiply the
3616    value in RAX/EAX/AX/AL by the given IRTemp, and park the result in
3617    RDX:RAX/EDX:EAX/DX:AX/AX.
3618 */
3619 static void codegen_mulL_A_D ( Int sz, Bool syned, 
3620                                IRTemp tmp, HChar* tmp_txt )
3621 {
3622    IRType ty = szToITy(sz);
3623    IRTemp t1 = newTemp(ty);
3624
3625    assign( t1, getIRegRAX(sz) );
3626
3627    switch (ty) {
3628       case Ity_I64: {
3629          IRTemp res128  = newTemp(Ity_I128);
3630          IRTemp resHi   = newTemp(Ity_I64);
3631          IRTemp resLo   = newTemp(Ity_I64);
3632          IROp   mulOp   = syned ? Iop_MullS64 : Iop_MullU64;
3633          UInt   tBaseOp = syned ? AMD64G_CC_OP_SMULB : AMD64G_CC_OP_UMULB;
3634          setFlags_MUL ( Ity_I64, t1, tmp, tBaseOp );
3635          assign( res128, binop(mulOp, mkexpr(t1), mkexpr(tmp)) );
3636          assign( resHi, unop(Iop_128HIto64,mkexpr(res128)));
3637          assign( resLo, unop(Iop_128to64,mkexpr(res128)));
3638          putIReg64(R_RDX, mkexpr(resHi));
3639          putIReg64(R_RAX, mkexpr(resLo));
3640          break;
3641       }
3642       case Ity_I32: {
3643          IRTemp res64   = newTemp(Ity_I64);
3644          IRTemp resHi   = newTemp(Ity_I32);
3645          IRTemp resLo   = newTemp(Ity_I32);
3646          IROp   mulOp   = syned ? Iop_MullS32 : Iop_MullU32;
3647          UInt   tBaseOp = syned ? AMD64G_CC_OP_SMULB : AMD64G_CC_OP_UMULB;
3648          setFlags_MUL ( Ity_I32, t1, tmp, tBaseOp );
3649          assign( res64, binop(mulOp, mkexpr(t1), mkexpr(tmp)) );
3650          assign( resHi, unop(Iop_64HIto32,mkexpr(res64)));
3651          assign( resLo, unop(Iop_64to32,mkexpr(res64)));
3652          putIRegRDX(4, mkexpr(resHi));
3653          putIRegRAX(4, mkexpr(resLo));
3654          break;
3655       }
3656       case Ity_I16: {
3657          IRTemp res32   = newTemp(Ity_I32);
3658          IRTemp resHi   = newTemp(Ity_I16);
3659          IRTemp resLo   = newTemp(Ity_I16);
3660          IROp   mulOp   = syned ? Iop_MullS16 : Iop_MullU16;
3661          UInt   tBaseOp = syned ? AMD64G_CC_OP_SMULB : AMD64G_CC_OP_UMULB;
3662          setFlags_MUL ( Ity_I16, t1, tmp, tBaseOp );
3663          assign( res32, binop(mulOp, mkexpr(t1), mkexpr(tmp)) );
3664          assign( resHi, unop(Iop_32HIto16,mkexpr(res32)));
3665          assign( resLo, unop(Iop_32to16,mkexpr(res32)));
3666          putIRegRDX(2, mkexpr(resHi));
3667          putIRegRAX(2, mkexpr(resLo));
3668          break;
3669       }
3670       case Ity_I8: {
3671          IRTemp res16   = newTemp(Ity_I16);
3672          IRTemp resHi   = newTemp(Ity_I8);
3673          IRTemp resLo   = newTemp(Ity_I8);
3674          IROp   mulOp   = syned ? Iop_MullS8 : Iop_MullU8;
3675          UInt   tBaseOp = syned ? AMD64G_CC_OP_SMULB : AMD64G_CC_OP_UMULB;
3676          setFlags_MUL ( Ity_I8, t1, tmp, tBaseOp );
3677          assign( res16, binop(mulOp, mkexpr(t1), mkexpr(tmp)) );
3678          assign( resHi, unop(Iop_16HIto8,mkexpr(res16)));
3679          assign( resLo, unop(Iop_16to8,mkexpr(res16)));
3680          putIRegRAX(2, mkexpr(res16));
3681          break;
3682       }
3683       default:
3684          ppIRType(ty);
3685          vpanic("codegen_mulL_A_D(amd64)");
3686    }
3687    DIP("%s%c %s\n", syned ? "imul" : "mul", nameISize(sz), tmp_txt);
3688 }
3689
3690
3691 /* Group 3 extended opcodes. */
3692 static 
3693 ULong dis_Grp3 ( VexAbiInfo* vbi, 
3694                  Prefix pfx, Int sz, Long delta, Bool* decode_OK )
3695 {
3696    Long    d64;
3697    UChar   modrm;
3698    HChar   dis_buf[50];
3699    Int     len;
3700    IRTemp  addr;
3701    IRType  ty = szToITy(sz);
3702    IRTemp  t1 = newTemp(ty);
3703    IRTemp dst1, src, dst0;
3704    *decode_OK = True;
3705    modrm = getUChar(delta);
3706    if (epartIsReg(modrm)) {
3707       switch (gregLO3ofRM(modrm)) {
3708          case 0: { /* TEST */
3709             delta++; 
3710             d64 = getSDisp(imin(4,sz), delta); 
3711             delta += imin(4,sz);
3712             dst1 = newTemp(ty);
3713             assign(dst1, binop(mkSizedOp(ty,Iop_And8),
3714                                getIRegE(sz,pfx,modrm),
3715                                mkU(ty, d64 & mkSizeMask(sz))));
3716             setFlags_DEP1( Iop_And8, dst1, ty );
3717             DIP("test%c $%lld, %s\n", 
3718                 nameISize(sz), d64, 
3719                 nameIRegE(sz, pfx, modrm));
3720             break;
3721          }
3722          case 1:
3723             *decode_OK = False;
3724             return delta;
3725          case 2: /* NOT */
3726             delta++;
3727             putIRegE(sz, pfx, modrm,
3728                               unop(mkSizedOp(ty,Iop_Not8),
3729                                    getIRegE(sz, pfx, modrm)));
3730             DIP("not%c %s\n", nameISize(sz), 
3731                               nameIRegE(sz, pfx, modrm));
3732             break;
3733          case 3: /* NEG */
3734             delta++;
3735             dst0 = newTemp(ty);
3736             src  = newTemp(ty);
3737             dst1 = newTemp(ty);
3738             assign(dst0, mkU(ty,0));
3739             assign(src,  getIRegE(sz, pfx, modrm));
3740             assign(dst1, binop(mkSizedOp(ty,Iop_Sub8), mkexpr(dst0),
3741                                                        mkexpr(src)));
3742             setFlags_DEP1_DEP2(Iop_Sub8, dst0, src, ty);
3743             putIRegE(sz, pfx, modrm, mkexpr(dst1));
3744             DIP("neg%c %s\n", nameISize(sz), nameIRegE(sz, pfx, modrm));
3745             break;
3746          case 4: /* MUL (unsigned widening) */
3747             delta++;
3748             src = newTemp(ty);
3749             assign(src, getIRegE(sz,pfx,modrm));
3750             codegen_mulL_A_D ( sz, False, src,
3751                                nameIRegE(sz,pfx,modrm) );
3752             break;
3753          case 5: /* IMUL (signed widening) */
3754             delta++;
3755             src = newTemp(ty);
3756             assign(src, getIRegE(sz,pfx,modrm));
3757             codegen_mulL_A_D ( sz, True, src,
3758                                nameIRegE(sz,pfx,modrm) );
3759             break;
3760          case 6: /* DIV */
3761             delta++;
3762             assign( t1, getIRegE(sz, pfx, modrm) );
3763             codegen_div ( sz, t1, False );
3764             DIP("div%c %s\n", nameISize(sz), 
3765                               nameIRegE(sz, pfx, modrm));
3766             break;
3767          case 7: /* IDIV */
3768             delta++;
3769             assign( t1, getIRegE(sz, pfx, modrm) );
3770             codegen_div ( sz, t1, True );
3771             DIP("idiv%c %s\n", nameISize(sz), 
3772                                nameIRegE(sz, pfx, modrm));
3773             break;
3774          default: 
3775             /*NOTREACHED*/
3776             vpanic("Grp3(amd64,R)");
3777       }
3778    } else {
3779       addr = disAMode ( &len, vbi, pfx, delta, dis_buf,
3780                         /* we have to inform disAMode of any immediate
3781                            bytes used */
3782                         gregLO3ofRM(modrm)==0/*TEST*/
3783                            ? imin(4,sz)
3784                            : 0
3785                       );
3786       t1   = newTemp(ty);
3787       delta += len;
3788       assign(t1, loadLE(ty,mkexpr(addr)));
3789       switch (gregLO3ofRM(modrm)) {
3790          case 0: { /* TEST */
3791             d64 = getSDisp(imin(4,sz), delta); 
3792             delta += imin(4,sz);
3793             dst1 = newTemp(ty);
3794             assign(dst1, binop(mkSizedOp(ty,Iop_And8),
3795                                mkexpr(t1), 
3796                                mkU(ty, d64 & mkSizeMask(sz))));
3797             setFlags_DEP1( Iop_And8, dst1, ty );
3798             DIP("test%c $%lld, %s\n", nameISize(sz), d64, dis_buf);
3799             break;
3800          }
3801          case 1:
3802             *decode_OK = False;
3803             return delta;
3804          case 2: /* NOT */
3805             dst1 = newTemp(ty);
3806             assign(dst1, unop(mkSizedOp(ty,Iop_Not8), mkexpr(t1)));
3807             if (pfx & PFX_LOCK) {
3808                casLE( mkexpr(addr), mkexpr(t1)/*expd*/, mkexpr(dst1)/*new*/,
3809                                     guest_RIP_curr_instr );
3810             } else {
3811                storeLE( mkexpr(addr), mkexpr(dst1) );
3812             }
3813             DIP("not%c %s\n", nameISize(sz), dis_buf);
3814             break;
3815          case 3: /* NEG */
3816             dst0 = newTemp(ty);
3817             src  = newTemp(ty);
3818             dst1 = newTemp(ty);
3819             assign(dst0, mkU(ty,0));
3820             assign(src,  mkexpr(t1));
3821             assign(dst1, binop(mkSizedOp(ty,Iop_Sub8), mkexpr(dst0),
3822                                                        mkexpr(src)));
3823             if (pfx & PFX_LOCK) {
3824                casLE( mkexpr(addr), mkexpr(t1)/*expd*/, mkexpr(dst1)/*new*/,
3825                                     guest_RIP_curr_instr );
3826             } else {
3827                storeLE( mkexpr(addr), mkexpr(dst1) );
3828             }
3829             setFlags_DEP1_DEP2(Iop_Sub8, dst0, src, ty);
3830             DIP("neg%c %s\n", nameISize(sz), dis_buf);
3831             break;
3832          case 4: /* MUL (unsigned widening) */
3833             codegen_mulL_A_D ( sz, False, t1, dis_buf );
3834             break;
3835          case 5: /* IMUL */
3836             codegen_mulL_A_D ( sz, True, t1, dis_buf );
3837             break;
3838          case 6: /* DIV */
3839             codegen_div ( sz, t1, False );
3840             DIP("div%c %s\n", nameISize(sz), dis_buf);
3841             break;
3842          case 7: /* IDIV */
3843             codegen_div ( sz, t1, True );
3844             DIP("idiv%c %s\n", nameISize(sz), dis_buf);
3845             break;
3846          default: 
3847             /*NOTREACHED*/
3848             vpanic("Grp3(amd64,M)");
3849       }
3850    }
3851    return delta;
3852 }
3853
3854
3855 /* Group 4 extended opcodes. */
3856 static
3857 ULong dis_Grp4 ( VexAbiInfo* vbi,
3858                  Prefix pfx, Long delta, Bool* decode_OK )
3859 {
3860    Int   alen;
3861    UChar modrm;
3862    HChar dis_buf[50];
3863    IRType ty = Ity_I8;
3864    IRTemp t1 = newTemp(ty);
3865    IRTemp t2 = newTemp(ty);
3866
3867    *decode_OK = True;
3868
3869    modrm = getUChar(delta);
3870    if (epartIsReg(modrm)) {
3871       assign(t1, getIRegE(1, pfx, modrm));
3872       switch (gregLO3ofRM(modrm)) {
3873          case 0: /* INC */
3874             assign(t2, binop(Iop_Add8, mkexpr(t1), mkU8(1)));
3875             putIRegE(1, pfx, modrm, mkexpr(t2));
3876             setFlags_INC_DEC( True, t2, ty );
3877             break;
3878          case 1: /* DEC */
3879             assign(t2, binop(Iop_Sub8, mkexpr(t1), mkU8(1)));
3880             putIRegE(1, pfx, modrm, mkexpr(t2));
3881             setFlags_INC_DEC( False, t2, ty );
3882             break;
3883          default: 
3884             *decode_OK = False;
3885             return delta;
3886       }
3887       delta++;
3888       DIP("%sb %s\n", nameGrp4(gregLO3ofRM(modrm)),
3889                       nameIRegE(1, pfx, modrm));
3890    } else {
3891       IRTemp addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
3892       assign( t1, loadLE(ty, mkexpr(addr)) );
3893       switch (gregLO3ofRM(modrm)) {
3894          case 0: /* INC */
3895             assign(t2, binop(Iop_Add8, mkexpr(t1), mkU8(1)));
3896             if (pfx & PFX_LOCK) {
3897                casLE( mkexpr(addr), mkexpr(t1)/*expd*/, mkexpr(t2)/*new*/, 
3898                       guest_RIP_curr_instr );
3899             } else {
3900                storeLE( mkexpr(addr), mkexpr(t2) );
3901             }
3902             setFlags_INC_DEC( True, t2, ty );
3903             break;
3904          case 1: /* DEC */
3905             assign(t2, binop(Iop_Sub8, mkexpr(t1), mkU8(1)));
3906             if (pfx & PFX_LOCK) {
3907                casLE( mkexpr(addr), mkexpr(t1)/*expd*/, mkexpr(t2)/*new*/, 
3908                       guest_RIP_curr_instr );
3909             } else {
3910                storeLE( mkexpr(addr), mkexpr(t2) );
3911             }
3912             setFlags_INC_DEC( False, t2, ty );
3913             break;
3914          default: 
3915             *decode_OK = False;
3916             return delta;
3917       }
3918       delta += alen;
3919       DIP("%sb %s\n", nameGrp4(gregLO3ofRM(modrm)), dis_buf);
3920    }
3921    return delta;
3922 }
3923
3924
3925 /* Group 5 extended opcodes. */
3926 static
3927 ULong dis_Grp5 ( VexAbiInfo* vbi,
3928                  Prefix pfx, Int sz, Long delta,
3929                  DisResult* dres, Bool* decode_OK )
3930 {
3931    Int     len;
3932    UChar   modrm;
3933    HChar   dis_buf[50];
3934    IRTemp  addr = IRTemp_INVALID;
3935    IRType  ty = szToITy(sz);
3936    IRTemp  t1 = newTemp(ty);
3937    IRTemp  t2 = IRTemp_INVALID;
3938    IRTemp  t3 = IRTemp_INVALID;
3939    Bool    showSz = True;
3940
3941    *decode_OK = True;
3942
3943    modrm = getUChar(delta);
3944    if (epartIsReg(modrm)) {
3945       assign(t1, getIRegE(sz,pfx,modrm));
3946       switch (gregLO3ofRM(modrm)) {
3947          case 0: /* INC */
3948             t2 = newTemp(ty);
3949             assign(t2, binop(mkSizedOp(ty,Iop_Add8),
3950                              mkexpr(t1), mkU(ty,1)));
3951             setFlags_INC_DEC( True, t2, ty );
3952             putIRegE(sz,pfx,modrm, mkexpr(t2));
3953             break;
3954          case 1: /* DEC */
3955             t2 = newTemp(ty);
3956             assign(t2, binop(mkSizedOp(ty,Iop_Sub8),
3957                              mkexpr(t1), mkU(ty,1)));
3958             setFlags_INC_DEC( False, t2, ty );
3959             putIRegE(sz,pfx,modrm, mkexpr(t2));
3960             break;
3961          case 2: /* call Ev */
3962             /* Ignore any sz value and operate as if sz==8. */
3963             if (!(sz == 4 || sz == 8)) goto unhandled;
3964             sz = 8;
3965             t3 = newTemp(Ity_I64);
3966             assign(t3, getIRegE(sz,pfx,modrm));
3967             t2 = newTemp(Ity_I64);
3968             assign(t2, binop(Iop_Sub64, getIReg64(R_RSP), mkU64(8)));
3969             putIReg64(R_RSP, mkexpr(t2));
3970             storeLE( mkexpr(t2), mkU64(guest_RIP_bbstart+delta+1));
3971             make_redzone_AbiHint(vbi, t2, t3/*nia*/, "call-Ev(reg)");
3972             jmp_treg(Ijk_Call,t3);
3973             dres->whatNext = Dis_StopHere;
3974             showSz = False;
3975             break;
3976          case 4: /* jmp Ev */
3977             /* Ignore any sz value and operate as if sz==8. */
3978             if (!(sz == 4 || sz == 8)) goto unhandled;
3979             sz = 8;
3980             t3 = newTemp(Ity_I64);
3981             assign(t3, getIRegE(sz,pfx,modrm));
3982             jmp_treg(Ijk_Boring,t3);
3983             dres->whatNext = Dis_StopHere;
3984             showSz = False;
3985             break;
3986          default: 
3987             *decode_OK = False;
3988             return delta;
3989       }
3990       delta++;
3991       DIP("%s%c %s\n", nameGrp5(gregLO3ofRM(modrm)),
3992                        showSz ? nameISize(sz) : ' ', 
3993                        nameIRegE(sz, pfx, modrm));
3994    } else {
3995       addr = disAMode ( &len, vbi, pfx, delta, dis_buf, 0 );
3996       if (gregLO3ofRM(modrm) != 2 && gregLO3ofRM(modrm) != 4
3997                                   && gregLO3ofRM(modrm) != 6) {
3998          assign(t1, loadLE(ty,mkexpr(addr)));
3999       }
4000       switch (gregLO3ofRM(modrm)) {
4001          case 0: /* INC */ 
4002             t2 = newTemp(ty);
4003             assign(t2, binop(mkSizedOp(ty,Iop_Add8),
4004                              mkexpr(t1), mkU(ty,1)));
4005             if (pfx & PFX_LOCK) {
4006                casLE( mkexpr(addr),
4007                       mkexpr(t1), mkexpr(t2), guest_RIP_curr_instr );
4008             } else {
4009                storeLE(mkexpr(addr),mkexpr(t2));
4010             }
4011             setFlags_INC_DEC( True, t2, ty );
4012             break;
4013          case 1: /* DEC */ 
4014             t2 = newTemp(ty);
4015             assign(t2, binop(mkSizedOp(ty,Iop_Sub8),
4016                              mkexpr(t1), mkU(ty,1)));
4017             if (pfx & PFX_LOCK) {
4018                casLE( mkexpr(addr),
4019                       mkexpr(t1), mkexpr(t2), guest_RIP_curr_instr );
4020             } else {
4021                storeLE(mkexpr(addr),mkexpr(t2));
4022             }
4023             setFlags_INC_DEC( False, t2, ty );
4024             break;
4025          case 2: /* call Ev */
4026             /* Ignore any sz value and operate as if sz==8. */
4027             if (!(sz == 4 || sz == 8)) goto unhandled;
4028             sz = 8;
4029             t3 = newTemp(Ity_I64);
4030             assign(t3, loadLE(Ity_I64,mkexpr(addr)));
4031             t2 = newTemp(Ity_I64);
4032             assign(t2, binop(Iop_Sub64, getIReg64(R_RSP), mkU64(8)));
4033             putIReg64(R_RSP, mkexpr(t2));
4034             storeLE( mkexpr(t2), mkU64(guest_RIP_bbstart+delta+len));
4035             make_redzone_AbiHint(vbi, t2, t3/*nia*/, "call-Ev(mem)");
4036             jmp_treg(Ijk_Call,t3);
4037             dres->whatNext = Dis_StopHere;
4038             showSz = False;
4039             break;
4040          case 4: /* JMP Ev */
4041             /* Ignore any sz value and operate as if sz==8. */
4042             if (!(sz == 4 || sz == 8)) goto unhandled;
4043             sz = 8;
4044             t3 = newTemp(Ity_I64);
4045             assign(t3, loadLE(Ity_I64,mkexpr(addr)));
4046             jmp_treg(Ijk_Boring,t3);
4047             dres->whatNext = Dis_StopHere;
4048             showSz = False;
4049             break;
4050          case 6: /* PUSH Ev */
4051             /* There is no encoding for 32-bit operand size; hence ... */
4052             if (sz == 4) sz = 8;
4053             if (!(sz == 8 || sz == 2)) goto unhandled;
4054             if (sz == 8) {
4055                t3 = newTemp(Ity_I64);
4056                assign(t3, loadLE(Ity_I64,mkexpr(addr)));
4057                t2 = newTemp(Ity_I64);
4058                assign( t2, binop(Iop_Sub64,getIReg64(R_RSP),mkU64(sz)) );
4059                putIReg64(R_RSP, mkexpr(t2) );
4060                storeLE( mkexpr(t2), mkexpr(t3) );
4061                break;
4062             } else {
4063                goto unhandled; /* awaiting test case */
4064             }
4065          default: 
4066          unhandled:
4067             *decode_OK = False;
4068             return delta;
4069       }
4070       delta += len;
4071       DIP("%s%c %s\n", nameGrp5(gregLO3ofRM(modrm)),
4072                        showSz ? nameISize(sz) : ' ', 
4073                        dis_buf);
4074    }
4075    return delta;
4076 }
4077
4078
4079 /*------------------------------------------------------------*/
4080 /*--- Disassembling string ops (including REP prefixes)    ---*/
4081 /*------------------------------------------------------------*/
4082
4083 /* Code shared by all the string ops */
4084 static
4085 void dis_string_op_increment ( Int sz, IRTemp t_inc )
4086 {
4087    UChar logSz;
4088    if (sz == 8 || sz == 4 || sz == 2) {
4089       logSz = 1;
4090       if (sz == 4) logSz = 2;
4091       if (sz == 8) logSz = 3;
4092       assign( t_inc, 
4093               binop(Iop_Shl64, IRExpr_Get( OFFB_DFLAG, Ity_I64 ),
4094                                mkU8(logSz) ) );
4095    } else {
4096       assign( t_inc, 
4097               IRExpr_Get( OFFB_DFLAG, Ity_I64 ) );
4098    }
4099 }
4100
4101 static
4102 void dis_string_op( void (*dis_OP)( Int, IRTemp ), 
4103                     Int sz, HChar* name, Prefix pfx )
4104 {
4105    IRTemp t_inc = newTemp(Ity_I64);
4106    /* Really we ought to inspect the override prefixes, but we don't.
4107       The following assertion catches any resulting sillyness. */
4108    vassert(pfx == clearSegBits(pfx));
4109    dis_string_op_increment(sz, t_inc);
4110    dis_OP( sz, t_inc );
4111    DIP("%s%c\n", name, nameISize(sz));
4112 }
4113
4114 static 
4115 void dis_MOVS ( Int sz, IRTemp t_inc )
4116 {
4117    IRType ty = szToITy(sz);
4118    IRTemp td = newTemp(Ity_I64);   /* RDI */
4119    IRTemp ts = newTemp(Ity_I64);   /* RSI */
4120
4121    assign( td, getIReg64(R_RDI) );
4122    assign( ts, getIReg64(R_RSI) );
4123
4124    storeLE( mkexpr(td), loadLE(ty,mkexpr(ts)) );
4125
4126    putIReg64( R_RDI, binop(Iop_Add64, mkexpr(td), mkexpr(t_inc)) );
4127    putIReg64( R_RSI, binop(Iop_Add64, mkexpr(ts), mkexpr(t_inc)) );
4128 }
4129
4130 static 
4131 void dis_LODS ( Int sz, IRTemp t_inc )
4132 {
4133    IRType ty = szToITy(sz);
4134    IRTemp ts = newTemp(Ity_I64);   /* RSI */
4135
4136    assign( ts, getIReg64(R_RSI) );
4137
4138    putIRegRAX ( sz, loadLE(ty, mkexpr(ts)) );
4139
4140    putIReg64( R_RSI, binop(Iop_Add64, mkexpr(ts), mkexpr(t_inc)) );
4141 }
4142
4143 static 
4144 void dis_STOS ( Int sz, IRTemp t_inc )
4145 {
4146    IRType ty = szToITy(sz);
4147    IRTemp ta = newTemp(ty);        /* rAX */
4148    IRTemp td = newTemp(Ity_I64);   /* RDI */
4149
4150    assign( ta, getIRegRAX(sz) );
4151
4152    assign( td, getIReg64(R_RDI) );
4153
4154    storeLE( mkexpr(td), mkexpr(ta) );
4155
4156    putIReg64( R_RDI, binop(Iop_Add64, mkexpr(td), mkexpr(t_inc)) );
4157 }
4158
4159 static 
4160 void dis_CMPS ( Int sz, IRTemp t_inc )
4161 {
4162    IRType ty  = szToITy(sz);
4163    IRTemp tdv = newTemp(ty);      /* (RDI) */
4164    IRTemp tsv = newTemp(ty);      /* (RSI) */
4165    IRTemp td  = newTemp(Ity_I64); /*  RDI  */
4166    IRTemp ts  = newTemp(Ity_I64); /*  RSI  */
4167
4168    assign( td, getIReg64(R_RDI) );
4169
4170    assign( ts, getIReg64(R_RSI) );
4171
4172    assign( tdv, loadLE(ty,mkexpr(td)) );
4173
4174    assign( tsv, loadLE(ty,mkexpr(ts)) );
4175
4176    setFlags_DEP1_DEP2 ( Iop_Sub8, tsv, tdv, ty );
4177
4178    putIReg64(R_RDI, binop(Iop_Add64, mkexpr(td), mkexpr(t_inc)) );
4179
4180    putIReg64(R_RSI, binop(Iop_Add64, mkexpr(ts), mkexpr(t_inc)) );
4181 }
4182
4183 static 
4184 void dis_SCAS ( Int sz, IRTemp t_inc )
4185 {
4186    IRType ty  = szToITy(sz);
4187    IRTemp ta  = newTemp(ty);       /*  rAX  */
4188    IRTemp td  = newTemp(Ity_I64);  /*  RDI  */
4189    IRTemp tdv = newTemp(ty);       /* (RDI) */
4190
4191    assign( ta, getIRegRAX(sz) );
4192
4193    assign( td, getIReg64(R_RDI) );
4194
4195    assign( tdv, loadLE(ty,mkexpr(td)) );
4196
4197    setFlags_DEP1_DEP2 ( Iop_Sub8, ta, tdv, ty );
4198
4199    putIReg64(R_RDI, binop(Iop_Add64, mkexpr(td), mkexpr(t_inc)) );
4200 }
4201
4202
4203 /* Wrap the appropriate string op inside a REP/REPE/REPNE.  We assume
4204    the insn is the last one in the basic block, and so emit a jump to
4205    the next insn, rather than just falling through. */
4206 static 
4207 void dis_REP_op ( AMD64Condcode cond,
4208                   void (*dis_OP)(Int, IRTemp),
4209                   Int sz, Addr64 rip, Addr64 rip_next, HChar* name,
4210                   Prefix pfx )
4211 {
4212    IRTemp t_inc = newTemp(Ity_I64);
4213    IRTemp tc    = newTemp(Ity_I64);  /*  RCX  */
4214
4215    /* Really we ought to inspect the override prefixes, but we don't.
4216       The following assertion catches any resulting sillyness. */
4217    vassert(pfx == clearSegBits(pfx));
4218
4219    assign( tc, getIReg64(R_RCX) );
4220
4221    stmt( IRStmt_Exit( binop(Iop_CmpEQ64,mkexpr(tc),mkU64(0)),
4222                       Ijk_Boring,
4223                       IRConst_U64(rip_next) ) );
4224
4225    putIReg64(R_RCX, binop(Iop_Sub64, mkexpr(tc), mkU64(1)) );
4226
4227    dis_string_op_increment(sz, t_inc);
4228    dis_OP (sz, t_inc);
4229
4230    if (cond == AMD64CondAlways) {
4231       jmp_lit(Ijk_Boring,rip);
4232    } else {
4233       stmt( IRStmt_Exit( mk_amd64g_calculate_condition(cond),
4234                          Ijk_Boring,
4235                          IRConst_U64(rip) ) );
4236       jmp_lit(Ijk_Boring,rip_next);
4237    }
4238    DIP("%s%c\n", name, nameISize(sz));
4239 }
4240
4241
4242 /*------------------------------------------------------------*/
4243 /*--- Arithmetic, etc.                                     ---*/
4244 /*------------------------------------------------------------*/
4245
4246 /* IMUL E, G.  Supplied eip points to the modR/M byte. */
4247 static
4248 ULong dis_mul_E_G ( VexAbiInfo* vbi,
4249                     Prefix      pfx,
4250                     Int         size, 
4251                     Long        delta0 )
4252 {
4253    Int    alen;
4254    HChar  dis_buf[50];
4255    UChar  rm = getUChar(delta0);
4256    IRType ty = szToITy(size);
4257    IRTemp te = newTemp(ty);
4258    IRTemp tg = newTemp(ty);
4259    IRTemp resLo = newTemp(ty);
4260
4261    assign( tg, getIRegG(size, pfx, rm) );
4262    if (epartIsReg(rm)) {
4263       assign( te, getIRegE(size, pfx, rm) );
4264    } else {
4265       IRTemp addr = disAMode( &alen, vbi, pfx, delta0, dis_buf, 0 );
4266       assign( te, loadLE(ty,mkexpr(addr)) );
4267    }
4268
4269    setFlags_MUL ( ty, te, tg, AMD64G_CC_OP_SMULB );
4270
4271    assign( resLo, binop( mkSizedOp(ty, Iop_Mul8), mkexpr(te), mkexpr(tg) ) );
4272
4273    putIRegG(size, pfx, rm, mkexpr(resLo) );
4274
4275    if (epartIsReg(rm)) {
4276       DIP("imul%c %s, %s\n", nameISize(size), 
4277                              nameIRegE(size,pfx,rm),
4278                              nameIRegG(size,pfx,rm));
4279       return 1+delta0;
4280    } else {
4281       DIP("imul%c %s, %s\n", nameISize(size), 
4282                              dis_buf, 
4283                              nameIRegG(size,pfx,rm));
4284       return alen+delta0;
4285    }
4286 }
4287
4288
4289 /* IMUL I * E -> G.  Supplied rip points to the modR/M byte. */
4290 static
4291 ULong dis_imul_I_E_G ( VexAbiInfo* vbi,
4292                        Prefix      pfx,
4293                        Int         size, 
4294                        Long        delta,
4295                        Int         litsize )
4296 {
4297    Long   d64;
4298    Int    alen;
4299    HChar  dis_buf[50];
4300    UChar  rm = getUChar(delta);
4301    IRType ty = szToITy(size);
4302    IRTemp te = newTemp(ty);
4303    IRTemp tl = newTemp(ty);
4304    IRTemp resLo = newTemp(ty);
4305
4306    vassert(/*size == 1 ||*/ size == 2 || size == 4 || size == 8);
4307
4308    if (epartIsReg(rm)) {
4309       assign(te, getIRegE(size, pfx, rm));
4310       delta++;
4311    } else {
4312       IRTemp addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 
4313                                      imin(4,litsize) );
4314       assign(te, loadLE(ty, mkexpr(addr)));
4315       delta += alen;
4316    }
4317    d64 = getSDisp(imin(4,litsize),delta);
4318    delta += imin(4,litsize);
4319
4320    d64 &= mkSizeMask(size);
4321    assign(tl, mkU(ty,d64));
4322
4323    assign( resLo, binop( mkSizedOp(ty, Iop_Mul8), mkexpr(te), mkexpr(tl) ));
4324
4325    setFlags_MUL ( ty, te, tl, AMD64G_CC_OP_SMULB );
4326
4327    putIRegG(size, pfx, rm, mkexpr(resLo));
4328
4329    DIP("imul%c $%lld, %s, %s\n", 
4330        nameISize(size), d64, 
4331        ( epartIsReg(rm) ? nameIRegE(size,pfx,rm) : dis_buf ),
4332        nameIRegG(size,pfx,rm) );
4333    return delta;
4334 }
4335
4336
4337 /*------------------------------------------------------------*/
4338 /*---                                                      ---*/
4339 /*--- x87 FLOATING POINT INSTRUCTIONS                      ---*/
4340 /*---                                                      ---*/
4341 /*------------------------------------------------------------*/
4342
4343 /* --- Helper functions for dealing with the register stack. --- */
4344
4345 /* --- Set the emulation-warning pseudo-register. --- */
4346
4347 static void put_emwarn ( IRExpr* e /* :: Ity_I32 */ )
4348 {
4349    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I32);
4350    stmt( IRStmt_Put( OFFB_EMWARN, e ) );
4351 }
4352
4353 /* --- Produce an IRExpr* denoting a 64-bit QNaN. --- */
4354
4355 static IRExpr* mkQNaN64 ( void )
4356 {
4357   /* QNaN is 0 2047 1 0(51times) 
4358      == 0b 11111111111b 1 0(51times)
4359      == 0x7FF8 0000 0000 0000
4360    */
4361    return IRExpr_Const(IRConst_F64i(0x7FF8000000000000ULL));
4362 }
4363
4364 /* --------- Get/put the top-of-stack pointer :: Ity_I32 --------- */
4365
4366 static IRExpr* get_ftop ( void )
4367 {
4368    return IRExpr_Get( OFFB_FTOP, Ity_I32 );
4369 }
4370
4371 static void put_ftop ( IRExpr* e )
4372 {
4373    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I32);
4374    stmt( IRStmt_Put( OFFB_FTOP, e ) );
4375 }
4376
4377 /* --------- Get/put the C3210 bits. --------- */
4378
4379 static IRExpr*  /* :: Ity_I64 */ get_C3210 ( void )
4380 {
4381    return IRExpr_Get( OFFB_FC3210, Ity_I64 );
4382 }
4383
4384 static void put_C3210 ( IRExpr* e  /* :: Ity_I64 */ )
4385 {
4386    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I64);
4387    stmt( IRStmt_Put( OFFB_FC3210, e ) );
4388 }
4389
4390 /* --------- Get/put the FPU rounding mode. --------- */
4391 static IRExpr* /* :: Ity_I32 */ get_fpround ( void )
4392 {
4393    return unop(Iop_64to32, IRExpr_Get( OFFB_FPROUND, Ity_I64 ));
4394 }
4395
4396 static void put_fpround ( IRExpr* /* :: Ity_I32 */ e )
4397 {
4398    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I32);
4399    stmt( IRStmt_Put( OFFB_FPROUND, unop(Iop_32Uto64,e) ) );
4400 }
4401
4402
4403 /* --------- Synthesise a 2-bit FPU rounding mode. --------- */
4404 /* Produces a value in 0 .. 3, which is encoded as per the type
4405    IRRoundingMode.  Since the guest_FPROUND value is also encoded as
4406    per IRRoundingMode, we merely need to get it and mask it for
4407    safety.
4408 */
4409 static IRExpr* /* :: Ity_I32 */ get_roundingmode ( void )
4410 {
4411    return binop( Iop_And32, get_fpround(), mkU32(3) );
4412 }
4413
4414 static IRExpr* /* :: Ity_I32 */ get_FAKE_roundingmode ( void )
4415 {
4416    return mkU32(Irrm_NEAREST);
4417 }
4418
4419
4420 /* --------- Get/set FP register tag bytes. --------- */
4421
4422 /* Given i, and some expression e, generate 'ST_TAG(i) = e'. */
4423
4424 static void put_ST_TAG ( Int i, IRExpr* value )
4425 {
4426    IRRegArray* descr;
4427    vassert(typeOfIRExpr(irsb->tyenv, value) == Ity_I8);
4428    descr = mkIRRegArray( OFFB_FPTAGS, Ity_I8, 8 );
4429    stmt( IRStmt_PutI( descr, get_ftop(), i, value ) );
4430 }
4431
4432 /* Given i, generate an expression yielding 'ST_TAG(i)'.  This will be
4433    zero to indicate "Empty" and nonzero to indicate "NonEmpty".  */
4434
4435 static IRExpr* get_ST_TAG ( Int i )
4436 {
4437    IRRegArray* descr = mkIRRegArray( OFFB_FPTAGS, Ity_I8, 8 );
4438    return IRExpr_GetI( descr, get_ftop(), i );
4439 }
4440
4441
4442 /* --------- Get/set FP registers. --------- */
4443
4444 /* Given i, and some expression e, emit 'ST(i) = e' and set the
4445    register's tag to indicate the register is full.  The previous
4446    state of the register is not checked. */
4447
4448 static void put_ST_UNCHECKED ( Int i, IRExpr* value )
4449 {
4450    IRRegArray* descr;
4451    vassert(typeOfIRExpr(irsb->tyenv, value) == Ity_F64);
4452    descr = mkIRRegArray( OFFB_FPREGS, Ity_F64, 8 );
4453    stmt( IRStmt_PutI( descr, get_ftop(), i, value ) );
4454    /* Mark the register as in-use. */
4455    put_ST_TAG(i, mkU8(1));
4456 }
4457
4458 /* Given i, and some expression e, emit
4459       ST(i) = is_full(i) ? NaN : e
4460    and set the tag accordingly.
4461 */
4462
4463 static void put_ST ( Int i, IRExpr* value )
4464 {
4465    put_ST_UNCHECKED( i,
4466                      IRExpr_Mux0X( get_ST_TAG(i),
4467                                    /* 0 means empty */
4468                                    value,
4469                                    /* non-0 means full */
4470                                    mkQNaN64()
4471                    )
4472    );
4473 }
4474
4475
4476 /* Given i, generate an expression yielding 'ST(i)'. */
4477
4478 static IRExpr* get_ST_UNCHECKED ( Int i )
4479 {
4480    IRRegArray* descr = mkIRRegArray( OFFB_FPREGS, Ity_F64, 8 );
4481    return IRExpr_GetI( descr, get_ftop(), i );
4482 }
4483
4484
4485 /* Given i, generate an expression yielding 
4486   is_full(i) ? ST(i) : NaN
4487 */
4488
4489 static IRExpr* get_ST ( Int i )
4490 {
4491    return
4492       IRExpr_Mux0X( get_ST_TAG(i),
4493                     /* 0 means empty */
4494                     mkQNaN64(),
4495                     /* non-0 means full */
4496                     get_ST_UNCHECKED(i));
4497 }
4498
4499
4500 /* Adjust FTOP downwards by one register. */
4501
4502 static void fp_push ( void )
4503 {
4504    put_ftop( binop(Iop_Sub32, get_ftop(), mkU32(1)) );
4505 }
4506
4507 /* Adjust FTOP upwards by one register, and mark the vacated register
4508    as empty.  */
4509
4510 static void fp_pop ( void )
4511 {
4512    put_ST_TAG(0, mkU8(0));
4513    put_ftop( binop(Iop_Add32, get_ftop(), mkU32(1)) );
4514 }
4515
4516 /* Clear the C2 bit of the FPU status register, for
4517    sin/cos/tan/sincos. */
4518
4519 static void clear_C2 ( void )
4520 {
4521    put_C3210( binop(Iop_And64, get_C3210(), mkU64(~AMD64G_FC_MASK_C2)) );
4522 }
4523
4524 /* Invent a plausible-looking FPU status word value:
4525       ((ftop & 7) << 11) | (c3210 & 0x4700)
4526  */
4527 static IRExpr* get_FPU_sw ( void )
4528 {
4529    return
4530       unop(Iop_32to16,
4531            binop(Iop_Or32,
4532                  binop(Iop_Shl32, 
4533                        binop(Iop_And32, get_ftop(), mkU32(7)), 
4534                              mkU8(11)),
4535                        binop(Iop_And32, unop(Iop_64to32, get_C3210()), 
4536                                         mkU32(0x4700))
4537       ));
4538 }
4539
4540
4541 /* ------------------------------------------------------- */
4542 /* Given all that stack-mangling junk, we can now go ahead
4543    and describe FP instructions. 
4544 */
4545
4546 /* ST(0) = ST(0) `op` mem64/32(addr)
4547    Need to check ST(0)'s tag on read, but not on write.
4548 */
4549 static
4550 void fp_do_op_mem_ST_0 ( IRTemp addr, HChar* op_txt, HChar* dis_buf, 
4551                          IROp op, Bool dbl )
4552 {
4553    DIP("f%s%c %s\n", op_txt, dbl?'l':'s', dis_buf);
4554    if (dbl) {
4555       put_ST_UNCHECKED(0, 
4556          triop( op, 
4557                 get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
4558                 get_ST(0), 
4559                 loadLE(Ity_F64,mkexpr(addr))
4560          ));
4561    } else {
4562       put_ST_UNCHECKED(0, 
4563          triop( op, 
4564                 get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
4565                 get_ST(0), 
4566                 unop(Iop_F32toF64, loadLE(Ity_F32,mkexpr(addr)))
4567          ));
4568    }
4569 }
4570
4571
4572 /* ST(0) = mem64/32(addr) `op` ST(0)
4573    Need to check ST(0)'s tag on read, but not on write.
4574 */
4575 static
4576 void fp_do_oprev_mem_ST_0 ( IRTemp addr, HChar* op_txt, HChar* dis_buf, 
4577                             IROp op, Bool dbl )
4578 {
4579    DIP("f%s%c %s\n", op_txt, dbl?'l':'s', dis_buf);
4580    if (dbl) {
4581       put_ST_UNCHECKED(0, 
4582          triop( op, 
4583                 get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
4584                 loadLE(Ity_F64,mkexpr(addr)),
4585                 get_ST(0)
4586          ));
4587    } else {
4588       put_ST_UNCHECKED(0, 
4589          triop( op, 
4590                 get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
4591                 unop(Iop_F32toF64, loadLE(Ity_F32,mkexpr(addr))),
4592                 get_ST(0)
4593          ));
4594    }
4595 }
4596
4597
4598 /* ST(dst) = ST(dst) `op` ST(src).
4599    Check dst and src tags when reading but not on write.
4600 */
4601 static
4602 void fp_do_op_ST_ST ( HChar* op_txt, IROp op, UInt st_src, UInt st_dst,
4603                       Bool pop_after )
4604 {
4605    DIP("f%s%s st(%u), st(%u)\n", op_txt, pop_after?"p":"", st_src, st_dst );
4606    put_ST_UNCHECKED( 
4607       st_dst, 
4608       triop( op, 
4609              get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
4610              get_ST(st_dst), 
4611              get_ST(st_src) ) 
4612    );
4613    if (pop_after)
4614       fp_pop();
4615 }
4616
4617 /* ST(dst) = ST(src) `op` ST(dst).
4618    Check dst and src tags when reading but not on write.
4619 */
4620 static
4621 void fp_do_oprev_ST_ST ( HChar* op_txt, IROp op, UInt st_src, UInt st_dst,
4622                          Bool pop_after )
4623 {
4624    DIP("f%s%s st(%u), st(%u)\n", op_txt, pop_after?"p":"", st_src, st_dst );
4625    put_ST_UNCHECKED( 
4626       st_dst, 
4627       triop( op, 
4628              get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
4629              get_ST(st_src), 
4630              get_ST(st_dst) ) 
4631    );
4632    if (pop_after)
4633       fp_pop();
4634 }
4635
4636 /* %rflags(Z,P,C) = UCOMI( st(0), st(i) ) */
4637 static void fp_do_ucomi_ST0_STi ( UInt i, Bool pop_after )
4638 {
4639    DIP("fucomi%s %%st(0),%%st(%u)\n", pop_after ? "p" : "", i);
4640    /* This is a bit of a hack (and isn't really right).  It sets
4641       Z,P,C,O correctly, but forces A and S to zero, whereas the Intel
4642       documentation implies A and S are unchanged. 
4643    */
4644    /* It's also fishy in that it is used both for COMIP and
4645       UCOMIP, and they aren't the same (although similar). */
4646    stmt( IRStmt_Put( OFFB_CC_OP,   mkU64(AMD64G_CC_OP_COPY) ));
4647    stmt( IRStmt_Put( OFFB_CC_DEP2, mkU64(0) ));
4648    stmt( IRStmt_Put( 
4649             OFFB_CC_DEP1,
4650             binop( Iop_And64,
4651                    unop( Iop_32Uto64,
4652                          binop(Iop_CmpF64, get_ST(0), get_ST(i))),
4653                    mkU64(0x45)
4654         )));
4655    if (pop_after)
4656       fp_pop();
4657 }
4658
4659
4660 /* returns 
4661    32to16( if e32 <s -32768 || e32 >s 32767 then -32768 else e32 )
4662 */
4663 static IRExpr* x87ishly_qnarrow_32_to_16 ( IRExpr* e32 )
4664 {
4665    IRTemp t32 = newTemp(Ity_I32);
4666    assign( t32, e32 );
4667    return
4668       IRExpr_Mux0X( 
4669          unop(Iop_1Uto8, 
4670               binop(Iop_CmpLT64U, 
4671                     unop(Iop_32Uto64, 
4672                          binop(Iop_Add32, mkexpr(t32), mkU32(32768))), 
4673                     mkU64(65536))),
4674          mkU16( 0x8000 ),
4675          unop(Iop_32to16, mkexpr(t32)));
4676 }
4677
4678
4679 static
4680 ULong dis_FPU ( /*OUT*/Bool* decode_ok, 
4681                 VexAbiInfo* vbi, Prefix pfx, Long delta )
4682 {
4683    Int    len;
4684    UInt   r_src, r_dst;
4685    HChar  dis_buf[50];
4686    IRTemp t1, t2;
4687
4688    /* On entry, delta points at the second byte of the insn (the modrm
4689       byte).*/
4690    UChar first_opcode = getUChar(delta-1);
4691    UChar modrm        = getUChar(delta+0);
4692
4693    /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xD8 opcodes +-+-+-+-+-+-+-+ */
4694
4695    if (first_opcode == 0xD8) {
4696       if (modrm < 0xC0) {
4697
4698          /* bits 5,4,3 are an opcode extension, and the modRM also
4699            specifies an address. */
4700          IRTemp addr = disAMode( &len, vbi, pfx, delta, dis_buf, 0 );
4701          delta += len;
4702
4703          switch (gregLO3ofRM(modrm)) {
4704
4705             case 0: /* FADD single-real */
4706                fp_do_op_mem_ST_0 ( addr, "add", dis_buf, Iop_AddF64, False );
4707                break;
4708
4709             case 1: /* FMUL single-real */
4710                fp_do_op_mem_ST_0 ( addr, "mul", dis_buf, Iop_MulF64, False );
4711                break;
4712
4713 //..             case 2: /* FCOM single-real */
4714 //..                DIP("fcoms %s\n", dis_buf);
4715 //..                /* This forces C1 to zero, which isn't right. */
4716 //..                put_C3210( 
4717 //..                    binop( Iop_And32,
4718 //..                           binop(Iop_Shl32, 
4719 //..                                 binop(Iop_CmpF64, 
4720 //..                                       get_ST(0),
4721 //..                                       unop(Iop_F32toF64, 
4722 //..                                            loadLE(Ity_F32,mkexpr(addr)))),
4723 //..                                 mkU8(8)),
4724 //..                           mkU32(0x4500)
4725 //..                    ));
4726 //..                break;  
4727 //.. 
4728 //..             case 3: /* FCOMP single-real */
4729 //..                DIP("fcomps %s\n", dis_buf);
4730 //..                /* This forces C1 to zero, which isn't right. */
4731 //..                put_C3210( 
4732 //..                    binop( Iop_And32,
4733 //..                           binop(Iop_Shl32, 
4734 //..                                 binop(Iop_CmpF64, 
4735 //..                                       get_ST(0),
4736 //..                                       unop(Iop_F32toF64, 
4737 //..                                            loadLE(Ity_F32,mkexpr(addr)))),
4738 //..                                 mkU8(8)),
4739 //..                           mkU32(0x4500)
4740 //..                    ));
4741 //..                fp_pop();
4742 //..                break;  
4743
4744             case 4: /* FSUB single-real */
4745                fp_do_op_mem_ST_0 ( addr, "sub", dis_buf, Iop_SubF64, False );
4746                break;
4747
4748             case 5: /* FSUBR single-real */
4749                fp_do_oprev_mem_ST_0 ( addr, "subr", dis_buf, Iop_SubF64, False );
4750                break;
4751
4752             case 6: /* FDIV single-real */
4753                fp_do_op_mem_ST_0 ( addr, "div", dis_buf, Iop_DivF64, False );
4754                break;
4755
4756             case 7: /* FDIVR single-real */
4757                fp_do_oprev_mem_ST_0 ( addr, "divr", dis_buf, Iop_DivF64, False );
4758                break;
4759
4760             default:
4761                vex_printf("unhandled opc_aux = 0x%2x\n", gregLO3ofRM(modrm));
4762                vex_printf("first_opcode == 0xD8\n");
4763                goto decode_fail;
4764          }
4765       } else {
4766          delta++;
4767          switch (modrm) {
4768
4769             case 0xC0 ... 0xC7: /* FADD %st(?),%st(0) */
4770                fp_do_op_ST_ST ( "add", Iop_AddF64, modrm - 0xC0, 0, False );
4771                break;
4772
4773             case 0xC8 ... 0xCF: /* FMUL %st(?),%st(0) */
4774                fp_do_op_ST_ST ( "mul", Iop_MulF64, modrm - 0xC8, 0, False );
4775                break;
4776
4777             /* Dunno if this is right */
4778             case 0xD0 ... 0xD7: /* FCOM %st(?),%st(0) */
4779                r_dst = (UInt)modrm - 0xD0;
4780                DIP("fcom %%st(0),%%st(%d)\n", r_dst);
4781                /* This forces C1 to zero, which isn't right. */
4782                put_C3210( 
4783                    unop(Iop_32Uto64,
4784                    binop( Iop_And32,
4785                           binop(Iop_Shl32, 
4786                                 binop(Iop_CmpF64, get_ST(0), get_ST(r_dst)),
4787                                 mkU8(8)),
4788                           mkU32(0x4500)
4789                    )));
4790                break;
4791
4792             /* Dunno if this is right */
4793             case 0xD8 ... 0xDF: /* FCOMP %st(?),%st(0) */
4794                r_dst = (UInt)modrm - 0xD8;
4795                DIP("fcomp %%st(0),%%st(%d)\n", r_dst);
4796                /* This forces C1 to zero, which isn't right. */
4797                put_C3210( 
4798                    unop(Iop_32Uto64,
4799                    binop( Iop_And32,
4800                           binop(Iop_Shl32, 
4801                                 binop(Iop_CmpF64, get_ST(0), get_ST(r_dst)),
4802                                 mkU8(8)),
4803                           mkU32(0x4500)
4804                    )));
4805                fp_pop();
4806                break;
4807
4808             case 0xE0 ... 0xE7: /* FSUB %st(?),%st(0) */
4809                fp_do_op_ST_ST ( "sub", Iop_SubF64, modrm - 0xE0, 0, False );
4810                break;
4811
4812             case 0xE8 ... 0xEF: /* FSUBR %st(?),%st(0) */
4813                fp_do_oprev_ST_ST ( "subr", Iop_SubF64, modrm - 0xE8, 0, False );
4814                break;
4815
4816             case 0xF0 ... 0xF7: /* FDIV %st(?),%st(0) */
4817                fp_do_op_ST_ST ( "div", Iop_DivF64, modrm - 0xF0, 0, False );
4818                break;
4819
4820             case 0xF8 ... 0xFF: /* FDIVR %st(?),%st(0) */
4821                fp_do_oprev_ST_ST ( "divr", Iop_DivF64, modrm - 0xF8, 0, False );
4822                break;
4823
4824             default:
4825                goto decode_fail;
4826          }
4827       }
4828    }
4829
4830    /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xD9 opcodes +-+-+-+-+-+-+-+ */
4831    else
4832    if (first_opcode == 0xD9) {
4833       if (modrm < 0xC0) {
4834
4835          /* bits 5,4,3 are an opcode extension, and the modRM also
4836             specifies an address. */
4837          IRTemp addr = disAMode( &len, vbi, pfx, delta, dis_buf, 0 );
4838          delta += len;
4839
4840          switch (gregLO3ofRM(modrm)) {
4841
4842             case 0: /* FLD single-real */
4843                DIP("flds %s\n", dis_buf);
4844                fp_push();
4845                put_ST(0, unop(Iop_F32toF64,
4846                               loadLE(Ity_F32, mkexpr(addr))));
4847                break;
4848
4849             case 2: /* FST single-real */
4850                DIP("fsts %s\n", dis_buf);
4851                storeLE(mkexpr(addr),
4852                        binop(Iop_F64toF32, get_roundingmode(), get_ST(0)));
4853                break;
4854
4855             case 3: /* FSTP single-real */
4856                DIP("fstps %s\n", dis_buf);
4857                storeLE(mkexpr(addr), 
4858                        binop(Iop_F64toF32, get_roundingmode(), get_ST(0)));
4859                fp_pop();
4860                break;
4861
4862             case 4: { /* FLDENV m28 */
4863                /* Uses dirty helper: 
4864                      VexEmWarn amd64g_do_FLDENV ( VexGuestX86State*, HWord ) */
4865                IRTemp    ew = newTemp(Ity_I32);
4866                IRTemp   w64 = newTemp(Ity_I64);
4867                IRDirty*   d = unsafeIRDirty_0_N ( 
4868                                  0/*regparms*/, 
4869                                  "amd64g_dirtyhelper_FLDENV", 
4870                                  &amd64g_dirtyhelper_FLDENV,
4871                                  mkIRExprVec_1( mkexpr(addr) )
4872                               );
4873                d->needsBBP = True;
4874                d->tmp      = w64;
4875                /* declare we're reading memory */
4876                d->mFx   = Ifx_Read;
4877                d->mAddr = mkexpr(addr);
4878                d->mSize = 28;
4879
4880                /* declare we're writing guest state */
4881                d->nFxState = 4;
4882
4883                d->fxState[0].fx     = Ifx_Write;
4884                d->fxState[0].offset = OFFB_FTOP;
4885                d->fxState[0].size   = sizeof(UInt);
4886
4887                d->fxState[1].fx     = Ifx_Write;
4888                d->fxState[1].offset = OFFB_FPTAGS;
4889                d->fxState[1].size   = 8 * sizeof(UChar);
4890
4891                d->fxState[2].fx     = Ifx_Write;
4892                d->fxState[2].offset = OFFB_FPROUND;
4893                d->fxState[2].size   = sizeof(ULong);
4894
4895                d->fxState[3].fx     = Ifx_Write;
4896                d->fxState[3].offset = OFFB_FC3210;
4897                d->fxState[3].size   = sizeof(ULong);
4898
4899                stmt( IRStmt_Dirty(d) );
4900
4901                /* ew contains any emulation warning we may need to
4902                   issue.  If needed, side-exit to the next insn,
4903                   reporting the warning, so that Valgrind's dispatcher
4904                   sees the warning. */
4905                assign(ew, unop(Iop_64to32,mkexpr(w64)) );
4906                put_emwarn( mkexpr(ew) );
4907                stmt( 
4908                   IRStmt_Exit(
4909                      binop(Iop_CmpNE32, mkexpr(ew), mkU32(0)),
4910                      Ijk_EmWarn,
4911                      IRConst_U64( guest_RIP_bbstart+delta )
4912                   )
4913                );
4914
4915                DIP("fldenv %s\n", dis_buf);
4916                break;
4917             }
4918
4919             case 5: {/* FLDCW */
4920                /* The only thing we observe in the control word is the
4921                   rounding mode.  Therefore, pass the 16-bit value
4922                   (x87 native-format control word) to a clean helper,
4923                   getting back a 64-bit value, the lower half of which
4924                   is the FPROUND value to store, and the upper half of
4925                   which is the emulation-warning token which may be
4926                   generated.
4927                */
4928                /* ULong amd64h_check_fldcw ( ULong ); */
4929                IRTemp t64 = newTemp(Ity_I64);
4930                IRTemp ew = newTemp(Ity_I32);
4931                DIP("fldcw %s\n", dis_buf);
4932                assign( t64, mkIRExprCCall(
4933                                Ity_I64, 0/*regparms*/, 
4934                                "amd64g_check_fldcw",
4935                                &amd64g_check_fldcw, 
4936                                mkIRExprVec_1( 
4937                                   unop( Iop_16Uto64, 
4938                                         loadLE(Ity_I16, mkexpr(addr)))
4939                                )
4940                             )
4941                      );
4942
4943                put_fpround( unop(Iop_64to32, mkexpr(t64)) );
4944                assign( ew, unop(Iop_64HIto32, mkexpr(t64) ) );
4945                put_emwarn( mkexpr(ew) );
4946                /* Finally, if an emulation warning was reported,
4947                   side-exit to the next insn, reporting the warning,
4948                   so that Valgrind's dispatcher sees the warning. */
4949                stmt( 
4950                   IRStmt_Exit(
4951                      binop(Iop_CmpNE32, mkexpr(ew), mkU32(0)),
4952                      Ijk_EmWarn,
4953                      IRConst_U64( guest_RIP_bbstart+delta )
4954                   )
4955                );
4956                break;
4957             }
4958
4959             case 6: { /* FNSTENV m28 */
4960                /* Uses dirty helper: 
4961                      void amd64g_do_FSTENV ( VexGuestAMD64State*, HWord ) */
4962                IRDirty* d = unsafeIRDirty_0_N ( 
4963                                0/*regparms*/, 
4964                                "amd64g_dirtyhelper_FSTENV", 
4965                                &amd64g_dirtyhelper_FSTENV,
4966                                mkIRExprVec_1( mkexpr(addr) )
4967                             );
4968                d->needsBBP = True;
4969                /* declare we're writing memory */
4970                d->mFx   = Ifx_Write;
4971                d->mAddr = mkexpr(addr);
4972                d->mSize = 28;
4973
4974                /* declare we're reading guest state */
4975                d->nFxState = 4;
4976
4977                d->fxState[0].fx     = Ifx_Read;
4978                d->fxState[0].offset = OFFB_FTOP;
4979                d->fxState[0].size   = sizeof(UInt);
4980
4981                d->fxState[1].fx     = Ifx_Read;
4982                d->fxState[1].offset = OFFB_FPTAGS;
4983                d->fxState[1].size   = 8 * sizeof(UChar);
4984
4985                d->fxState[2].fx     = Ifx_Read;
4986                d->fxState[2].offset = OFFB_FPROUND;
4987                d->fxState[2].size   = sizeof(ULong);
4988
4989                d->fxState[3].fx     = Ifx_Read;
4990                d->fxState[3].offset = OFFB_FC3210;
4991                d->fxState[3].size   = sizeof(ULong);
4992
4993                stmt( IRStmt_Dirty(d) );
4994
4995                DIP("fnstenv %s\n", dis_buf);
4996                break;
4997             }
4998
4999             case 7: /* FNSTCW */
5000                /* Fake up a native x87 FPU control word.  The only
5001                   thing it depends on is FPROUND[1:0], so call a clean
5002                   helper to cook it up. */
5003                /* ULong amd64g_create_fpucw ( ULong fpround ) */
5004                DIP("fnstcw %s\n", dis_buf);
5005                storeLE(
5006                   mkexpr(addr), 
5007                   unop( Iop_64to16, 
5008                         mkIRExprCCall(
5009                            Ity_I64, 0/*regp*/,
5010                            "amd64g_create_fpucw", &amd64g_create_fpucw, 
5011                            mkIRExprVec_1( unop(Iop_32Uto64, get_fpround()) ) 
5012                         ) 
5013                   ) 
5014                );
5015                break;
5016
5017             default:
5018                vex_printf("unhandled opc_aux = 0x%2x\n", gregLO3ofRM(modrm));
5019                vex_printf("first_opcode == 0xD9\n");
5020                goto decode_fail;
5021          }
5022
5023       } else {
5024          delta++;
5025          switch (modrm) {
5026
5027             case 0xC0 ... 0xC7: /* FLD %st(?) */
5028                r_src = (UInt)modrm - 0xC0;
5029                DIP("fld %%st(%u)\n", r_src);
5030                t1 = newTemp(Ity_F64);
5031                assign(t1, get_ST(r_src));
5032                fp_push();
5033                put_ST(0, mkexpr(t1));
5034                break;
5035
5036             case 0xC8 ... 0xCF: /* FXCH %st(?) */
5037                r_src = (UInt)modrm - 0xC8;
5038                DIP("fxch %%st(%u)\n", r_src);
5039                t1 = newTemp(Ity_F64);
5040                t2 = newTemp(Ity_F64);
5041                assign(t1, get_ST(0));
5042                assign(t2, get_ST(r_src));
5043                put_ST_UNCHECKED(0, mkexpr(t2));
5044                put_ST_UNCHECKED(r_src, mkexpr(t1));
5045                break;
5046
5047             case 0xE0: /* FCHS */
5048                DIP("fchs\n");
5049                put_ST_UNCHECKED(0, unop(Iop_NegF64, get_ST(0)));
5050                break;
5051
5052             case 0xE1: /* FABS */
5053                DIP("fabs\n");
5054                put_ST_UNCHECKED(0, unop(Iop_AbsF64, get_ST(0)));
5055                break;
5056
5057             case 0xE5: { /* FXAM */
5058                /* This is an interesting one.  It examines %st(0),
5059                   regardless of whether the tag says it's empty or not.
5060                   Here, just pass both the tag (in our format) and the
5061                   value (as a double, actually a ULong) to a helper
5062                   function. */
5063                IRExpr** args
5064                   = mkIRExprVec_2( unop(Iop_8Uto64, get_ST_TAG(0)),
5065                                    unop(Iop_ReinterpF64asI64, 
5066                                         get_ST_UNCHECKED(0)) );
5067                put_C3210(mkIRExprCCall(
5068                             Ity_I64, 
5069                             0/*regparm*/, 
5070                             "amd64g_calculate_FXAM", &amd64g_calculate_FXAM,
5071                             args
5072                         ));
5073                DIP("fxam\n");
5074                break;
5075             }
5076
5077             case 0xE8: /* FLD1 */
5078                DIP("fld1\n");
5079                fp_push();
5080                /* put_ST(0, IRExpr_Const(IRConst_F64(1.0))); */
5081                put_ST(0, IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)));
5082                break;
5083
5084             case 0xE9: /* FLDL2T */
5085                DIP("fldl2t\n");
5086                fp_push();
5087                /* put_ST(0, IRExpr_Const(IRConst_F64(3.32192809488736234781))); */
5088                put_ST(0, IRExpr_Const(IRConst_F64i(0x400a934f0979a371ULL)));
5089                break;
5090
5091             case 0xEA: /* FLDL2E */
5092                DIP("fldl2e\n");
5093                fp_push();
5094                /* put_ST(0, IRExpr_Const(IRConst_F64(1.44269504088896340739))); */
5095                put_ST(0, IRExpr_Const(IRConst_F64i(0x3ff71547652b82feULL)));
5096                break;
5097
5098             case 0xEB: /* FLDPI */
5099                DIP("fldpi\n");
5100                fp_push();
5101                /* put_ST(0, IRExpr_Const(IRConst_F64(3.14159265358979323851))); */
5102                put_ST(0, IRExpr_Const(IRConst_F64i(0x400921fb54442d18ULL)));
5103                break;
5104
5105             case 0xEC: /* FLDLG2 */
5106                DIP("fldlg2\n");
5107                fp_push();
5108                /* put_ST(0, IRExpr_Const(IRConst_F64(0.301029995663981143))); */
5109                put_ST(0, IRExpr_Const(IRConst_F64i(0x3fd34413509f79ffULL)));
5110                break;
5111
5112             case 0xED: /* FLDLN2 */
5113                DIP("fldln2\n");
5114                fp_push();
5115                /* put_ST(0, IRExpr_Const(IRConst_F64(0.69314718055994530942))); */
5116                put_ST(0, IRExpr_Const(IRConst_F64i(0x3fe62e42fefa39efULL)));
5117                break;
5118
5119             case 0xEE: /* FLDZ */
5120                DIP("fldz\n");
5121                fp_push();
5122                /* put_ST(0, IRExpr_Const(IRConst_F64(0.0))); */
5123                put_ST(0, IRExpr_Const(IRConst_F64i(0x0000000000000000ULL)));
5124                break;
5125
5126             case 0xF0: /* F2XM1 */
5127                DIP("f2xm1\n");
5128                put_ST_UNCHECKED(0, 
5129                   binop(Iop_2xm1F64, 
5130                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
5131                         get_ST(0)));
5132                break;
5133
5134             case 0xF1: /* FYL2X */
5135                DIP("fyl2x\n");
5136                put_ST_UNCHECKED(1, 
5137                   triop(Iop_Yl2xF64,
5138                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
5139                         get_ST(1), 
5140                         get_ST(0)));
5141                fp_pop();
5142                break;
5143
5144             case 0xF2: /* FPTAN */
5145                DIP("ftan\n");
5146                put_ST_UNCHECKED(0, 
5147                   binop(Iop_TanF64, 
5148                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
5149                         get_ST(0)));
5150                fp_push();
5151                put_ST(0, IRExpr_Const(IRConst_F64(1.0)));
5152                clear_C2(); /* HACK */
5153                break;
5154
5155             case 0xF3: /* FPATAN */
5156                DIP("fpatan\n");
5157                put_ST_UNCHECKED(1, 
5158                   triop(Iop_AtanF64,
5159                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
5160                         get_ST(1), 
5161                         get_ST(0)));
5162                fp_pop();
5163                break;
5164
5165             case 0xF4: { /* FXTRACT */
5166                IRTemp argF = newTemp(Ity_F64);
5167                IRTemp sigF = newTemp(Ity_F64);
5168                IRTemp expF = newTemp(Ity_F64);
5169                IRTemp argI = newTemp(Ity_I64);
5170                IRTemp sigI = newTemp(Ity_I64);
5171                IRTemp expI = newTemp(Ity_I64);
5172                DIP("fxtract\n");
5173                assign( argF, get_ST(0) );
5174                assign( argI, unop(Iop_ReinterpF64asI64, mkexpr(argF)));
5175                assign( sigI, 
5176                        mkIRExprCCall(
5177                           Ity_I64, 0/*regparms*/, 
5178                           "x86amd64g_calculate_FXTRACT", 
5179                           &x86amd64g_calculate_FXTRACT, 
5180                           mkIRExprVec_2( mkexpr(argI), 
5181                                          mkIRExpr_HWord(0)/*sig*/ )) 
5182                );
5183                assign( expI, 
5184                        mkIRExprCCall(
5185                           Ity_I64, 0/*regparms*/, 
5186                           "x86amd64g_calculate_FXTRACT", 
5187                           &x86amd64g_calculate_FXTRACT, 
5188                           mkIRExprVec_2( mkexpr(argI), 
5189                                          mkIRExpr_HWord(1)/*exp*/ )) 
5190                );
5191                assign( sigF, unop(Iop_ReinterpI64asF64, mkexpr(sigI)) );
5192                assign( expF, unop(Iop_ReinterpI64asF64, mkexpr(expI)) );
5193                /* exponent */
5194                put_ST_UNCHECKED(0, mkexpr(expF) );
5195                fp_push();
5196                /* significand */
5197                put_ST(0, mkexpr(sigF) );
5198                break;
5199             }
5200
5201             case 0xF5: { /* FPREM1 -- IEEE compliant */
5202                IRTemp a1 = newTemp(Ity_F64);
5203                IRTemp a2 = newTemp(Ity_F64);
5204                DIP("fprem1\n");
5205                /* Do FPREM1 twice, once to get the remainder, and once
5206                   to get the C3210 flag values. */
5207                assign( a1, get_ST(0) );
5208                assign( a2, get_ST(1) );
5209                put_ST_UNCHECKED(0,
5210                   triop(Iop_PRem1F64,
5211                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
5212                         mkexpr(a1),
5213                         mkexpr(a2)));
5214                put_C3210(
5215                   unop(Iop_32Uto64,
5216                   triop(Iop_PRem1C3210F64,
5217                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
5218                         mkexpr(a1),
5219                         mkexpr(a2)) ));
5220                break;
5221             }
5222
5223             case 0xF7: /* FINCSTP */
5224                DIP("fincstp\n");
5225                put_ftop( binop(Iop_Add32, get_ftop(), mkU32(1)) );
5226                break;
5227
5228             case 0xF8: { /* FPREM -- not IEEE compliant */
5229                IRTemp a1 = newTemp(Ity_F64);
5230                IRTemp a2 = newTemp(Ity_F64);
5231                DIP("fprem\n");
5232                /* Do FPREM twice, once to get the remainder, and once
5233                   to get the C3210 flag values. */
5234                assign( a1, get_ST(0) );
5235                assign( a2, get_ST(1) );
5236                put_ST_UNCHECKED(0,
5237                   triop(Iop_PRemF64,
5238                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
5239                         mkexpr(a1),
5240                         mkexpr(a2)));
5241                put_C3210(
5242                   unop(Iop_32Uto64,
5243                   triop(Iop_PRemC3210F64,
5244                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
5245                         mkexpr(a1),
5246                         mkexpr(a2)) ));
5247                break;
5248             }
5249
5250             case 0xF9: /* FYL2XP1 */
5251                DIP("fyl2xp1\n");
5252                put_ST_UNCHECKED(1, 
5253                   triop(Iop_Yl2xp1F64,
5254                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
5255                         get_ST(1), 
5256                         get_ST(0)));
5257                fp_pop();
5258                break;
5259
5260             case 0xFA: /* FSQRT */
5261                DIP("fsqrt\n");
5262                put_ST_UNCHECKED(0, 
5263                   binop(Iop_SqrtF64, 
5264                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
5265                         get_ST(0)));
5266                break;
5267
5268             case 0xFB: { /* FSINCOS */
5269                IRTemp a1 = newTemp(Ity_F64);
5270                assign( a1, get_ST(0) );
5271                DIP("fsincos\n");
5272                put_ST_UNCHECKED(0, 
5273                   binop(Iop_SinF64, 
5274                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
5275                         mkexpr(a1)));
5276                fp_push();
5277                put_ST(0, 
5278                   binop(Iop_CosF64, 
5279                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
5280                         mkexpr(a1)));
5281                clear_C2(); /* HACK */
5282                break;
5283             }
5284
5285             case 0xFC: /* FRNDINT */
5286                DIP("frndint\n");
5287                put_ST_UNCHECKED(0,
5288                   binop(Iop_RoundF64toInt, get_roundingmode(), get_ST(0)) );
5289                break;
5290
5291             case 0xFD: /* FSCALE */
5292                DIP("fscale\n");
5293                put_ST_UNCHECKED(0, 
5294                   triop(Iop_ScaleF64,
5295                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
5296                         get_ST(0), 
5297                         get_ST(1)));
5298                break;
5299
5300             case 0xFE: /* FSIN */
5301                DIP("fsin\n");
5302                put_ST_UNCHECKED(0, 
5303                   binop(Iop_SinF64, 
5304                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
5305                         get_ST(0)));
5306                clear_C2(); /* HACK */
5307                break;
5308
5309             case 0xFF: /* FCOS */
5310                DIP("fcos\n");
5311                put_ST_UNCHECKED(0, 
5312                   binop(Iop_CosF64, 
5313                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
5314                         get_ST(0)));
5315                clear_C2(); /* HACK */
5316                break;
5317
5318             default:
5319                goto decode_fail;
5320          }
5321       }
5322    }
5323
5324    /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDA opcodes +-+-+-+-+-+-+-+ */
5325    else
5326    if (first_opcode == 0xDA) {
5327
5328       if (modrm < 0xC0) {
5329
5330          /* bits 5,4,3 are an opcode extension, and the modRM also
5331             specifies an address. */
5332          IROp   fop;
5333          IRTemp addr = disAMode( &len, vbi, pfx, delta, dis_buf, 0 );
5334          delta += len;
5335          switch (gregLO3ofRM(modrm)) {
5336
5337             case 0: /* FIADD m32int */ /* ST(0) += m32int */
5338                DIP("fiaddl %s\n", dis_buf);
5339                fop = Iop_AddF64;
5340                goto do_fop_m32;
5341
5342             case 1: /* FIMUL m32int */ /* ST(0) *= m32int */
5343                DIP("fimull %s\n", dis_buf);
5344                fop = Iop_MulF64;
5345                goto do_fop_m32;
5346
5347             case 4: /* FISUB m32int */ /* ST(0) -= m32int */
5348                DIP("fisubl %s\n", dis_buf);
5349                fop = Iop_SubF64;
5350                goto do_fop_m32;
5351
5352             case 5: /* FISUBR m32int */ /* ST(0) = m32int - ST(0) */
5353                DIP("fisubrl %s\n", dis_buf);
5354                fop = Iop_SubF64;
5355                goto do_foprev_m32;
5356
5357             case 6: /* FIDIV m32int */ /* ST(0) /= m32int */
5358                DIP("fisubl %s\n", dis_buf);
5359                fop = Iop_DivF64;
5360                goto do_fop_m32;
5361
5362             case 7: /* FIDIVR m32int */ /* ST(0) = m32int / ST(0) */
5363                DIP("fidivrl %s\n", dis_buf);
5364                fop = Iop_DivF64;
5365                goto do_foprev_m32;
5366
5367             do_fop_m32:
5368                put_ST_UNCHECKED(0, 
5369                   triop(fop, 
5370                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
5371                         get_ST(0),
5372                         unop(Iop_I32StoF64,
5373                              loadLE(Ity_I32, mkexpr(addr)))));
5374                break;
5375
5376             do_foprev_m32:
5377                put_ST_UNCHECKED(0, 
5378                   triop(fop, 
5379                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
5380                         unop(Iop_I32StoF64,
5381                              loadLE(Ity_I32, mkexpr(addr))),
5382                         get_ST(0)));
5383                break;
5384
5385             default:
5386                vex_printf("unhandled opc_aux = 0x%2x\n", gregLO3ofRM(modrm));
5387                vex_printf("first_opcode == 0xDA\n");
5388                goto decode_fail;
5389          }
5390
5391       } else {
5392
5393          delta++;
5394          switch (modrm) {
5395
5396             case 0xC0 ... 0xC7: /* FCMOVB ST(i), ST(0) */
5397                r_src = (UInt)modrm - 0xC0;
5398                DIP("fcmovb %%st(%u), %%st(0)\n", r_src);
5399                put_ST_UNCHECKED(0, 
5400                                 IRExpr_Mux0X( 
5401                                     unop(Iop_1Uto8,
5402                                          mk_amd64g_calculate_condition(AMD64CondB)), 
5403                                     get_ST(0), get_ST(r_src)) );
5404                break;
5405
5406             case 0xC8 ... 0xCF: /* FCMOVE(Z) ST(i), ST(0) */
5407                r_src = (UInt)modrm - 0xC8;
5408                DIP("fcmovz %%st(%u), %%st(0)\n", r_src);
5409                put_ST_UNCHECKED(0, 
5410                                 IRExpr_Mux0X( 
5411                                     unop(Iop_1Uto8,
5412                                          mk_amd64g_calculate_condition(AMD64CondZ)), 
5413                                     get_ST(0), get_ST(r_src)) );
5414                break;
5415
5416             case 0xD0 ... 0xD7: /* FCMOVBE ST(i), ST(0) */
5417                r_src = (UInt)modrm - 0xD0;
5418                DIP("fcmovbe %%st(%u), %%st(0)\n", r_src);
5419                put_ST_UNCHECKED(0, 
5420                                 IRExpr_Mux0X( 
5421                                     unop(Iop_1Uto8,
5422                                          mk_amd64g_calculate_condition(AMD64CondBE)), 
5423                                     get_ST(0), get_ST(r_src)) );
5424                break;
5425
5426             case 0xD8 ... 0xDF: /* FCMOVU ST(i), ST(0) */
5427                r_src = (UInt)modrm - 0xD8;
5428                DIP("fcmovu %%st(%u), %%st(0)\n", r_src);
5429                put_ST_UNCHECKED(0, 
5430                                 IRExpr_Mux0X( 
5431                                     unop(Iop_1Uto8,
5432                                          mk_amd64g_calculate_condition(AMD64CondP)), 
5433                                     get_ST(0), get_ST(r_src)) );
5434                break;
5435
5436             case 0xE9: /* FUCOMPP %st(0),%st(1) */
5437                DIP("fucompp %%st(0),%%st(1)\n");
5438                /* This forces C1 to zero, which isn't right. */
5439                put_C3210( 
5440                    unop(Iop_32Uto64,
5441                    binop( Iop_And32,
5442                           binop(Iop_Shl32, 
5443                                 binop(Iop_CmpF64, get_ST(0), get_ST(1)),
5444                                 mkU8(8)),
5445                           mkU32(0x4500)
5446                    )));
5447                fp_pop();
5448                fp_pop();
5449                break;
5450
5451             default:
5452                goto decode_fail;
5453          }
5454
5455       }
5456    }
5457
5458    /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDB opcodes +-+-+-+-+-+-+-+ */
5459    else
5460    if (first_opcode == 0xDB) {
5461       if (modrm < 0xC0) {
5462
5463          /* bits 5,4,3 are an opcode extension, and the modRM also
5464             specifies an address. */
5465          IRTemp addr = disAMode( &len, vbi, pfx, delta, dis_buf, 0 );
5466          delta += len;
5467
5468          switch (gregLO3ofRM(modrm)) {
5469
5470             case 0: /* FILD m32int */
5471                DIP("fildl %s\n", dis_buf);
5472                fp_push();
5473                put_ST(0, unop(Iop_I32StoF64,
5474                               loadLE(Ity_I32, mkexpr(addr))));
5475                break;
5476
5477             case 1: /* FISTTPL m32 (SSE3) */
5478                DIP("fisttpl %s\n", dis_buf);
5479                storeLE( mkexpr(addr), 
5480                         binop(Iop_F64toI32S, mkU32(Irrm_ZERO), get_ST(0)) );
5481                fp_pop();
5482                break;
5483
5484             case 2: /* FIST m32 */
5485                DIP("fistl %s\n", dis_buf);
5486                storeLE( mkexpr(addr), 
5487                         binop(Iop_F64toI32S, get_roundingmode(), get_ST(0)) );
5488                break;
5489
5490             case 3: /* FISTP m32 */
5491                DIP("fistpl %s\n", dis_buf);
5492                storeLE( mkexpr(addr), 
5493                         binop(Iop_F64toI32S, get_roundingmode(), get_ST(0)) );
5494                fp_pop();
5495                break;
5496
5497             case 5: { /* FLD extended-real */
5498                /* Uses dirty helper: 
5499                      ULong amd64g_loadF80le ( ULong )
5500                   addr holds the address.  First, do a dirty call to
5501                   get hold of the data. */
5502                IRTemp   val  = newTemp(Ity_I64);
5503                IRExpr** args = mkIRExprVec_1 ( mkexpr(addr) );
5504
5505                IRDirty* d = unsafeIRDirty_1_N ( 
5506                                val, 
5507                                0/*regparms*/, 
5508                                "amd64g_dirtyhelper_loadF80le", 
5509                                &amd64g_dirtyhelper_loadF80le, 
5510                                args 
5511                             );
5512                /* declare that we're reading memory */
5513                d->mFx   = Ifx_Read;
5514                d->mAddr = mkexpr(addr);
5515                d->mSize = 10;
5516
5517                /* execute the dirty call, dumping the result in val. */
5518                stmt( IRStmt_Dirty(d) );
5519                fp_push();
5520                put_ST(0, unop(Iop_ReinterpI64asF64, mkexpr(val)));
5521
5522                DIP("fldt %s\n", dis_buf);
5523                break;
5524             }
5525
5526             case 7: { /* FSTP extended-real */
5527                /* Uses dirty helper: 
5528                      void amd64g_storeF80le ( ULong addr, ULong data ) 
5529                */
5530                IRExpr** args 
5531                   = mkIRExprVec_2( mkexpr(addr), 
5532                                    unop(Iop_ReinterpF64asI64, get_ST(0)) );
5533
5534                IRDirty* d = unsafeIRDirty_0_N ( 
5535                                0/*regparms*/, 
5536                                "amd64g_dirtyhelper_storeF80le", 
5537                                &amd64g_dirtyhelper_storeF80le,
5538                                args 
5539                             );
5540                /* declare we're writing memory */
5541                d->mFx   = Ifx_Write;
5542                d->mAddr = mkexpr(addr);
5543                d->mSize = 10;
5544
5545                /* execute the dirty call. */
5546                stmt( IRStmt_Dirty(d) );
5547                fp_pop();
5548
5549                DIP("fstpt\n %s", dis_buf);
5550                break;
5551             }
5552
5553             default:
5554                vex_printf("unhandled opc_aux = 0x%2x\n", gregLO3ofRM(modrm));
5555                vex_printf("first_opcode == 0xDB\n");
5556                goto decode_fail;
5557          }
5558
5559       } else {
5560
5561          delta++;
5562          switch (modrm) {
5563
5564             case 0xC0 ... 0xC7: /* FCMOVNB ST(i), ST(0) */
5565                r_src = (UInt)modrm - 0xC0;
5566                DIP("fcmovnb %%st(%u), %%st(0)\n", r_src);
5567                put_ST_UNCHECKED(0, 
5568                                 IRExpr_Mux0X( 
5569                                     unop(Iop_1Uto8,
5570                                          mk_amd64g_calculate_condition(AMD64CondNB)), 
5571                                     get_ST(0), get_ST(r_src)) );
5572                break;
5573
5574             case 0xC8 ... 0xCF: /* FCMOVNE(NZ) ST(i), ST(0) */
5575                r_src = (UInt)modrm - 0xC8;
5576                DIP("fcmovnz %%st(%u), %%st(0)\n", r_src);
5577                put_ST_UNCHECKED(
5578                   0, 
5579                   IRExpr_Mux0X( 
5580                      unop(Iop_1Uto8,
5581                           mk_amd64g_calculate_condition(AMD64CondNZ)), 
5582                      get_ST(0), 
5583                      get_ST(r_src)
5584                   )
5585                );
5586                break;
5587
5588             case 0xD0 ... 0xD7: /* FCMOVNBE ST(i), ST(0) */
5589                r_src = (UInt)modrm - 0xD0;
5590                DIP("fcmovnbe %%st(%u), %%st(0)\n", r_src);
5591                put_ST_UNCHECKED(
5592                   0, 
5593                   IRExpr_Mux0X( 
5594                      unop(Iop_1Uto8,
5595                           mk_amd64g_calculate_condition(AMD64CondNBE)), 
5596                      get_ST(0), 
5597                      get_ST(r_src)
5598                   ) 
5599                );
5600                break;
5601
5602             case 0xD8 ... 0xDF: /* FCMOVNU ST(i), ST(0) */
5603                r_src = (UInt)modrm - 0xD8;
5604                DIP("fcmovnu %%st(%u), %%st(0)\n", r_src);
5605                put_ST_UNCHECKED(
5606                   0, 
5607                   IRExpr_Mux0X( 
5608                      unop(Iop_1Uto8,
5609                           mk_amd64g_calculate_condition(AMD64CondNP)), 
5610                      get_ST(0), 
5611                      get_ST(r_src)
5612                   )
5613                );
5614                break;
5615
5616             case 0xE2:
5617                DIP("fnclex\n");
5618                break;
5619
5620             case 0xE3: {
5621                /* Uses dirty helper: 
5622                      void amd64g_do_FINIT ( VexGuestAMD64State* ) */
5623                IRDirty* d  = unsafeIRDirty_0_N ( 
5624                                 0/*regparms*/, 
5625                                 "amd64g_dirtyhelper_FINIT", 
5626                                 &amd64g_dirtyhelper_FINIT,
5627                                 mkIRExprVec_0()
5628                              );
5629                d->needsBBP = True;
5630
5631                /* declare we're writing guest state */
5632                d->nFxState = 5;
5633
5634                d->fxState[0].fx     = Ifx_Write;
5635                d->fxState[0].offset = OFFB_FTOP;
5636                d->fxState[0].size   = sizeof(UInt);
5637
5638                d->fxState[1].fx     = Ifx_Write;
5639                d->fxState[1].offset = OFFB_FPREGS;
5640                d->fxState[1].size   = 8 * sizeof(ULong);
5641
5642                d->fxState[2].fx     = Ifx_Write;
5643                d->fxState[2].offset = OFFB_FPTAGS;
5644                d->fxState[2].size   = 8 * sizeof(UChar);
5645
5646                d->fxState[3].fx     = Ifx_Write;
5647                d->fxState[3].offset = OFFB_FPROUND;
5648                d->fxState[3].size   = sizeof(ULong);
5649
5650                d->fxState[4].fx     = Ifx_Write;
5651                d->fxState[4].offset = OFFB_FC3210;
5652                d->fxState[4].size   = sizeof(ULong);
5653
5654                stmt( IRStmt_Dirty(d) );
5655
5656                DIP("fninit\n");
5657                break;
5658             }
5659
5660             case 0xE8 ... 0xEF: /* FUCOMI %st(0),%st(?) */
5661                fp_do_ucomi_ST0_STi( (UInt)modrm - 0xE8, False );
5662                break;
5663
5664             case 0xF0 ... 0xF7: /* FCOMI %st(0),%st(?) */
5665                fp_do_ucomi_ST0_STi( (UInt)modrm - 0xF0, False );
5666                break;
5667
5668             default:
5669                goto decode_fail;
5670          }
5671       }
5672    }
5673
5674    /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDC opcodes +-+-+-+-+-+-+-+ */
5675    else
5676    if (first_opcode == 0xDC) {
5677       if (modrm < 0xC0) {
5678
5679          /* bits 5,4,3 are an opcode extension, and the modRM also
5680             specifies an address. */
5681          IRTemp addr = disAMode( &len, vbi, pfx, delta, dis_buf, 0 );
5682          delta += len;
5683
5684          switch (gregLO3ofRM(modrm)) {
5685
5686             case 0: /* FADD double-real */
5687                fp_do_op_mem_ST_0 ( addr, "add", dis_buf, Iop_AddF64, True );
5688                break;
5689
5690             case 1: /* FMUL double-real */
5691                fp_do_op_mem_ST_0 ( addr, "mul", dis_buf, Iop_MulF64, True );
5692                break;
5693
5694 //..             case 2: /* FCOM double-real */
5695 //..                DIP("fcoml %s\n", dis_buf);
5696 //..                /* This forces C1 to zero, which isn't right. */
5697 //..                put_C3210( 
5698 //..                    binop( Iop_And32,
5699 //..                           binop(Iop_Shl32, 
5700 //..                                 binop(Iop_CmpF64, 
5701 //..                                       get_ST(0),
5702 //..                                       loadLE(Ity_F64,mkexpr(addr))),
5703 //..                                 mkU8(8)),
5704 //..                           mkU32(0x4500)
5705 //..                    ));
5706 //..                break;  
5707
5708             case 3: /* FCOMP double-real */
5709                DIP("fcompl %s\n", dis_buf);
5710                /* This forces C1 to zero, which isn't right. */
5711                put_C3210( 
5712                    unop(Iop_32Uto64,
5713                    binop( Iop_And32,
5714                           binop(Iop_Shl32, 
5715                                 binop(Iop_CmpF64, 
5716                                       get_ST(0),
5717                                       loadLE(Ity_F64,mkexpr(addr))),
5718                                 mkU8(8)),
5719                           mkU32(0x4500)
5720                    )));
5721                fp_pop();
5722                break;  
5723
5724             case 4: /* FSUB double-real */
5725                fp_do_op_mem_ST_0 ( addr, "sub", dis_buf, Iop_SubF64, True );
5726                break;
5727
5728             case 5: /* FSUBR double-real */
5729                fp_do_oprev_mem_ST_0 ( addr, "subr", dis_buf, Iop_SubF64, True );
5730                break;
5731
5732             case 6: /* FDIV double-real */
5733                fp_do_op_mem_ST_0 ( addr, "div", dis_buf, Iop_DivF64, True );
5734                break;
5735
5736             case 7: /* FDIVR double-real */
5737                fp_do_oprev_mem_ST_0 ( addr, "divr", dis_buf, Iop_DivF64, True );
5738                break;
5739
5740             default:
5741                vex_printf("unhandled opc_aux = 0x%2x\n", gregLO3ofRM(modrm));
5742                vex_printf("first_opcode == 0xDC\n");
5743                goto decode_fail;
5744          }
5745
5746       } else {
5747
5748          delta++;
5749          switch (modrm) {
5750
5751             case 0xC0 ... 0xC7: /* FADD %st(0),%st(?) */
5752                fp_do_op_ST_ST ( "add", Iop_AddF64, 0, modrm - 0xC0, False );
5753                break;
5754
5755             case 0xC8 ... 0xCF: /* FMUL %st(0),%st(?) */
5756                fp_do_op_ST_ST ( "mul", Iop_MulF64, 0, modrm - 0xC8, False );
5757                break;
5758
5759             case 0xE0 ... 0xE7: /* FSUBR %st(0),%st(?) */
5760                fp_do_oprev_ST_ST ( "subr", Iop_SubF64, 0, modrm - 0xE0, False );
5761                break;
5762
5763             case 0xE8 ... 0xEF: /* FSUB %st(0),%st(?) */
5764                fp_do_op_ST_ST ( "sub", Iop_SubF64, 0, modrm - 0xE8, False );
5765                break;
5766
5767             case 0xF0 ... 0xF7: /* FDIVR %st(0),%st(?) */
5768                fp_do_oprev_ST_ST ( "divr", Iop_DivF64, 0, modrm - 0xF0, False );
5769                break;
5770
5771             case 0xF8 ... 0xFF: /* FDIV %st(0),%st(?) */
5772                fp_do_op_ST_ST ( "div", Iop_DivF64, 0, modrm - 0xF8, False );
5773                break;
5774
5775             default:
5776                goto decode_fail;
5777          }
5778
5779       }
5780    }
5781
5782    /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDD opcodes +-+-+-+-+-+-+-+ */
5783    else
5784    if (first_opcode == 0xDD) {
5785
5786       if (modrm < 0xC0) {
5787
5788          /* bits 5,4,3 are an opcode extension, and the modRM also
5789             specifies an address. */
5790          IRTemp addr = disAMode( &len, vbi, pfx, delta, dis_buf, 0 );
5791          delta += len;
5792
5793          switch (gregLO3ofRM(modrm)) {
5794
5795             case 0: /* FLD double-real */
5796                DIP("fldl %s\n", dis_buf);
5797                fp_push();
5798                put_ST(0, loadLE(Ity_F64, mkexpr(addr)));
5799                break;
5800
5801             case 1: /* FISTTPQ m64 (SSE3) */
5802                DIP("fistppll %s\n", dis_buf);
5803                storeLE( mkexpr(addr), 
5804                         binop(Iop_F64toI64S, mkU32(Irrm_ZERO), get_ST(0)) );
5805                fp_pop();
5806                break;
5807
5808             case 2: /* FST double-real */
5809                DIP("fstl %s\n", dis_buf);
5810                storeLE(mkexpr(addr), get_ST(0));
5811                break;
5812
5813             case 3: /* FSTP double-real */
5814                DIP("fstpl %s\n", dis_buf);
5815                storeLE(mkexpr(addr), get_ST(0));
5816                fp_pop();
5817                break;
5818
5819 //..             case 4: { /* FRSTOR m108 */
5820 //..                /* Uses dirty helper: 
5821 //..                      VexEmWarn x86g_do_FRSTOR ( VexGuestX86State*, Addr32 ) */
5822 //..                IRTemp   ew = newTemp(Ity_I32);
5823 //..                IRDirty* d  = unsafeIRDirty_0_N ( 
5824 //..                                 0/*regparms*/, 
5825 //..                                 "x86g_dirtyhelper_FRSTOR", 
5826 //..                                 &x86g_dirtyhelper_FRSTOR,
5827 //..                                 mkIRExprVec_1( mkexpr(addr) )
5828 //..                              );
5829 //..                d->needsBBP = True;
5830 //..                d->tmp      = ew;
5831 //..                /* declare we're reading memory */
5832 //..                d->mFx   = Ifx_Read;
5833 //..                d->mAddr = mkexpr(addr);
5834 //..                d->mSize = 108;
5835 //.. 
5836 //..                /* declare we're writing guest state */
5837 //..                d->nFxState = 5;
5838 //.. 
5839 //..                d->fxState[0].fx     = Ifx_Write;
5840 //..                d->fxState[0].offset = OFFB_FTOP;
5841 //..                d->fxState[0].size   = sizeof(UInt);
5842 //.. 
5843 //..                d->fxState[1].fx     = Ifx_Write;
5844 //..                d->fxState[1].offset = OFFB_FPREGS;
5845 //..                d->fxState[1].size   = 8 * sizeof(ULong);
5846 //.. 
5847 //..                d->fxState[2].fx     = Ifx_Write;
5848 //..                d->fxState[2].offset = OFFB_FPTAGS;
5849 //..                d->fxState[2].size   = 8 * sizeof(UChar);
5850 //.. 
5851 //..                d->fxState[3].fx     = Ifx_Write;
5852 //..                d->fxState[3].offset = OFFB_FPROUND;
5853 //..                d->fxState[3].size   = sizeof(UInt);
5854 //.. 
5855 //..                d->fxState[4].fx     = Ifx_Write;
5856 //..                d->fxState[4].offset = OFFB_FC3210;
5857 //..                d->fxState[4].size   = sizeof(UInt);
5858 //.. 
5859 //..                stmt( IRStmt_Dirty(d) );
5860 //.. 
5861 //..                /* ew contains any emulation warning we may need to
5862 //..                   issue.  If needed, side-exit to the next insn,
5863 //..                   reporting the warning, so that Valgrind's dispatcher
5864 //..                   sees the warning. */
5865 //..                put_emwarn( mkexpr(ew) );
5866 //..                stmt( 
5867 //..                   IRStmt_Exit(
5868 //..                      binop(Iop_CmpNE32, mkexpr(ew), mkU32(0)),
5869 //..                      Ijk_EmWarn,
5870 //..                      IRConst_U32( ((Addr32)guest_eip_bbstart)+delta)
5871 //..                   )
5872 //..                );
5873 //.. 
5874 //..                DIP("frstor %s\n", dis_buf);
5875 //..                break;
5876 //..             }
5877 //.. 
5878 //..             case 6: { /* FNSAVE m108 */
5879 //..                /* Uses dirty helper: 
5880 //..                      void x86g_do_FSAVE ( VexGuestX86State*, UInt ) */
5881 //..                IRDirty* d = unsafeIRDirty_0_N ( 
5882 //..                                0/*regparms*/, 
5883 //..                                "x86g_dirtyhelper_FSAVE", 
5884 //..                                &x86g_dirtyhelper_FSAVE,
5885 //..                                mkIRExprVec_1( mkexpr(addr) )
5886 //..                             );
5887 //..                d->needsBBP = True;
5888 //..                /* declare we're writing memory */
5889 //..                d->mFx   = Ifx_Write;
5890 //..                d->mAddr = mkexpr(addr);
5891 //..                d->mSize = 108;
5892 //.. 
5893 //..                /* declare we're reading guest state */
5894 //..                d->nFxState = 5;
5895 //.. 
5896 //..                d->fxState[0].fx     = Ifx_Read;
5897 //..                d->fxState[0].offset = OFFB_FTOP;
5898 //..                d->fxState[0].size   = sizeof(UInt);
5899 //.. 
5900 //..                d->fxState[1].fx     = Ifx_Read;
5901 //..                d->fxState[1].offset = OFFB_FPREGS;
5902 //..                d->fxState[1].size   = 8 * sizeof(ULong);
5903 //.. 
5904 //..                d->fxState[2].fx     = Ifx_Read;
5905 //..                d->fxState[2].offset = OFFB_FPTAGS;
5906 //..                d->fxState[2].size   = 8 * sizeof(UChar);
5907 //.. 
5908 //..                d->fxState[3].fx     = Ifx_Read;
5909 //..                d->fxState[3].offset = OFFB_FPROUND;
5910 //..                d->fxState[3].size   = sizeof(UInt);
5911 //.. 
5912 //..                d->fxState[4].fx     = Ifx_Read;
5913 //..                d->fxState[4].offset = OFFB_FC3210;
5914 //..                d->fxState[4].size   = sizeof(UInt);
5915 //.. 
5916 //..                stmt( IRStmt_Dirty(d) );
5917 //.. 
5918 //..                DIP("fnsave %s\n", dis_buf);
5919 //..                break;
5920 //..             }
5921
5922             case 7: { /* FNSTSW m16 */
5923                IRExpr* sw = get_FPU_sw();
5924                vassert(typeOfIRExpr(irsb->tyenv, sw) == Ity_I16);
5925                storeLE( mkexpr(addr), sw );
5926                DIP("fnstsw %s\n", dis_buf);
5927                break;
5928             }
5929
5930             default:
5931                vex_printf("unhandled opc_aux = 0x%2x\n", gregLO3ofRM(modrm));
5932                vex_printf("first_opcode == 0xDD\n");
5933                goto decode_fail;
5934          }
5935       } else {
5936          delta++;
5937          switch (modrm) {
5938
5939             case 0xC0 ... 0xC7: /* FFREE %st(?) */
5940                r_dst = (UInt)modrm - 0xC0;
5941                DIP("ffree %%st(%u)\n", r_dst);
5942                put_ST_TAG ( r_dst, mkU8(0) );
5943                break;
5944
5945             case 0xD0 ... 0xD7: /* FST %st(0),%st(?) */
5946                r_dst = (UInt)modrm - 0xD0;
5947                DIP("fst %%st(0),%%st(%u)\n", r_dst);
5948                /* P4 manual says: "If the destination operand is a
5949                   non-empty register, the invalid-operation exception
5950                   is not generated.  Hence put_ST_UNCHECKED. */
5951                put_ST_UNCHECKED(r_dst, get_ST(0));
5952                break;
5953
5954             case 0xD8 ... 0xDF: /* FSTP %st(0),%st(?) */
5955                r_dst = (UInt)modrm - 0xD8;
5956                DIP("fstp %%st(0),%%st(%u)\n", r_dst);
5957                /* P4 manual says: "If the destination operand is a
5958                   non-empty register, the invalid-operation exception
5959                   is not generated.  Hence put_ST_UNCHECKED. */
5960                put_ST_UNCHECKED(r_dst, get_ST(0));
5961                fp_pop();
5962                break;
5963
5964             case 0xE0 ... 0xE7: /* FUCOM %st(0),%st(?) */
5965                r_dst = (UInt)modrm - 0xE0;
5966                DIP("fucom %%st(0),%%st(%u)\n", r_dst);
5967                /* This forces C1 to zero, which isn't right. */
5968                put_C3210(
5969                    unop(Iop_32Uto64, 
5970                    binop( Iop_And32,
5971                           binop(Iop_Shl32, 
5972                                 binop(Iop_CmpF64, get_ST(0), get_ST(r_dst)),
5973                                 mkU8(8)),
5974                           mkU32(0x4500)
5975                    )));
5976                break;
5977
5978             case 0xE8 ... 0xEF: /* FUCOMP %st(0),%st(?) */
5979                r_dst = (UInt)modrm - 0xE8;
5980                DIP("fucomp %%st(0),%%st(%u)\n", r_dst);
5981                /* This forces C1 to zero, which isn't right. */
5982                put_C3210( 
5983                    unop(Iop_32Uto64, 
5984                    binop( Iop_And32,
5985                           binop(Iop_Shl32, 
5986                                 binop(Iop_CmpF64, get_ST(0), get_ST(r_dst)),
5987                                 mkU8(8)),
5988                           mkU32(0x4500)
5989                    )));
5990                fp_pop();
5991                break;
5992
5993             default:
5994                goto decode_fail;
5995          }
5996       }
5997    }
5998
5999    /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDE opcodes +-+-+-+-+-+-+-+ */
6000    else
6001    if (first_opcode == 0xDE) {
6002
6003       if (modrm < 0xC0) {
6004
6005          /* bits 5,4,3 are an opcode extension, and the modRM also
6006             specifies an address. */
6007          IROp   fop;
6008          IRTemp addr = disAMode( &len, vbi, pfx, delta, dis_buf, 0 );
6009          delta += len;
6010
6011          switch (gregLO3ofRM(modrm)) {
6012
6013             case 0: /* FIADD m16int */ /* ST(0) += m16int */
6014                DIP("fiaddw %s\n", dis_buf);
6015                fop = Iop_AddF64;
6016                goto do_fop_m16;
6017
6018             case 1: /* FIMUL m16int */ /* ST(0) *= m16int */
6019                DIP("fimulw %s\n", dis_buf);
6020                fop = Iop_MulF64;
6021                goto do_fop_m16;
6022
6023             case 4: /* FISUB m16int */ /* ST(0) -= m16int */
6024                DIP("fisubw %s\n", dis_buf);
6025                fop = Iop_SubF64;
6026                goto do_fop_m16;
6027
6028             case 5: /* FISUBR m16int */ /* ST(0) = m16int - ST(0) */
6029                DIP("fisubrw %s\n", dis_buf);
6030                fop = Iop_SubF64;
6031                goto do_foprev_m16;
6032
6033             case 6: /* FIDIV m16int */ /* ST(0) /= m16int */
6034                DIP("fisubw %s\n", dis_buf);
6035                fop = Iop_DivF64;
6036                goto do_fop_m16;
6037
6038             case 7: /* FIDIVR m16int */ /* ST(0) = m16int / ST(0) */
6039                DIP("fidivrw %s\n", dis_buf);
6040                fop = Iop_DivF64;
6041                goto do_foprev_m16;
6042
6043             do_fop_m16:
6044                put_ST_UNCHECKED(0, 
6045                   triop(fop, 
6046                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
6047                         get_ST(0),
6048                         unop(Iop_I32StoF64,
6049                              unop(Iop_16Sto32, 
6050                                   loadLE(Ity_I16, mkexpr(addr))))));
6051                break;
6052
6053             do_foprev_m16:
6054                put_ST_UNCHECKED(0, 
6055                   triop(fop, 
6056                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
6057                         unop(Iop_I32StoF64,
6058                              unop(Iop_16Sto32, 
6059                                   loadLE(Ity_I16, mkexpr(addr)))),
6060                         get_ST(0)));
6061                break;
6062
6063             default:
6064                vex_printf("unhandled opc_aux = 0x%2x\n", gregLO3ofRM(modrm));
6065                vex_printf("first_opcode == 0xDE\n");
6066                goto decode_fail;
6067          }
6068
6069       } else {
6070
6071          delta++;
6072          switch (modrm) {
6073
6074             case 0xC0 ... 0xC7: /* FADDP %st(0),%st(?) */
6075                fp_do_op_ST_ST ( "add", Iop_AddF64, 0, modrm - 0xC0, True );
6076                break;
6077
6078             case 0xC8 ... 0xCF: /* FMULP %st(0),%st(?) */
6079                fp_do_op_ST_ST ( "mul", Iop_MulF64, 0, modrm - 0xC8, True );
6080                break;
6081
6082             case 0xD9: /* FCOMPP %st(0),%st(1) */
6083                DIP("fcompp %%st(0),%%st(1)\n");
6084                /* This forces C1 to zero, which isn't right. */
6085                put_C3210( 
6086                    unop(Iop_32Uto64,
6087                    binop( Iop_And32,
6088                           binop(Iop_Shl32, 
6089                                 binop(Iop_CmpF64, get_ST(0), get_ST(1)),
6090                                 mkU8(8)),
6091                           mkU32(0x4500)
6092                    )));
6093                fp_pop();
6094                fp_pop();
6095                break;
6096
6097             case 0xE0 ... 0xE7: /* FSUBRP %st(0),%st(?) */
6098                fp_do_oprev_ST_ST ( "subr", Iop_SubF64, 0,  modrm - 0xE0, True );
6099                break;
6100
6101             case 0xE8 ... 0xEF: /* FSUBP %st(0),%st(?) */
6102                fp_do_op_ST_ST ( "sub", Iop_SubF64, 0,  modrm - 0xE8, True );
6103                break;
6104
6105             case 0xF0 ... 0xF7: /* FDIVRP %st(0),%st(?) */
6106                fp_do_oprev_ST_ST ( "divr", Iop_DivF64, 0, modrm - 0xF0, True );
6107                break;
6108
6109             case 0xF8 ... 0xFF: /* FDIVP %st(0),%st(?) */
6110                fp_do_op_ST_ST ( "div", Iop_DivF64, 0, modrm - 0xF8, True );
6111                break;
6112
6113             default: 
6114                goto decode_fail;
6115          }
6116
6117       }
6118    }
6119
6120    /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDF opcodes +-+-+-+-+-+-+-+ */
6121    else
6122    if (first_opcode == 0xDF) {
6123
6124       if (modrm < 0xC0) {
6125
6126          /* bits 5,4,3 are an opcode extension, and the modRM also
6127             specifies an address. */
6128          IRTemp addr = disAMode( &len, vbi, pfx, delta, dis_buf, 0 );
6129          delta += len;
6130
6131          switch (gregLO3ofRM(modrm)) {
6132
6133             case 0: /* FILD m16int */
6134                DIP("fildw %s\n", dis_buf);
6135                fp_push();
6136                put_ST(0, unop(Iop_I32StoF64,
6137                               unop(Iop_16Sto32,
6138                                    loadLE(Ity_I16, mkexpr(addr)))));
6139                break;
6140
6141             case 1: /* FISTTPS m16 (SSE3) */
6142                DIP("fisttps %s\n", dis_buf);
6143                storeLE( mkexpr(addr), 
6144                         x87ishly_qnarrow_32_to_16( 
6145                         binop(Iop_F64toI32S, mkU32(Irrm_ZERO), get_ST(0)) ));
6146                fp_pop();
6147                break;
6148
6149 //..             case 2: /* FIST m16 */
6150 //..                DIP("fistp %s\n", dis_buf);
6151 //..                storeLE( mkexpr(addr), 
6152 //..                         binop(Iop_F64toI16, get_roundingmode(), get_ST(0)) );
6153 //..                break;
6154
6155             case 3: /* FISTP m16 */
6156                DIP("fistps %s\n", dis_buf);
6157                storeLE( mkexpr(addr),
6158                         x87ishly_qnarrow_32_to_16( 
6159                         binop(Iop_F64toI32S, get_roundingmode(), get_ST(0)) ));
6160                fp_pop();
6161                break;
6162
6163             case 5: /* FILD m64 */
6164                DIP("fildll %s\n", dis_buf);
6165                fp_push();
6166                put_ST(0, binop(Iop_I64StoF64,
6167                                get_roundingmode(),
6168                                loadLE(Ity_I64, mkexpr(addr))));
6169                break;
6170
6171             case 7: /* FISTP m64 */
6172                DIP("fistpll %s\n", dis_buf);
6173                storeLE( mkexpr(addr), 
6174                         binop(Iop_F64toI64S, get_roundingmode(), get_ST(0)) );
6175                fp_pop();
6176                break;
6177
6178             default:
6179                vex_printf("unhandled opc_aux = 0x%2x\n", gregLO3ofRM(modrm));
6180                vex_printf("first_opcode == 0xDF\n");
6181                goto decode_fail;
6182          }
6183
6184       } else {
6185
6186          delta++;
6187          switch (modrm) {
6188
6189             case 0xC0: /* FFREEP %st(0) */
6190                DIP("ffreep %%st(%d)\n", 0);
6191                put_ST_TAG ( 0, mkU8(0) );
6192                fp_pop();
6193                break;
6194
6195             case 0xE0: /* FNSTSW %ax */
6196                DIP("fnstsw %%ax\n");
6197                /* Invent a plausible-looking FPU status word value and
6198                   dump it in %AX:
6199                      ((ftop & 7) << 11) | (c3210 & 0x4700)
6200                */
6201                putIRegRAX(
6202                   2,
6203                   unop(Iop_32to16,
6204                        binop(Iop_Or32,
6205                              binop(Iop_Shl32, 
6206                                    binop(Iop_And32, get_ftop(), mkU32(7)), 
6207                                    mkU8(11)),
6208                              binop(Iop_And32, 
6209                                    unop(Iop_64to32, get_C3210()), 
6210                                    mkU32(0x4700))
6211                )));
6212                break;
6213
6214             case 0xE8 ... 0xEF: /* FUCOMIP %st(0),%st(?) */
6215                fp_do_ucomi_ST0_STi( (UInt)modrm - 0xE8, True );
6216                break;
6217
6218             case 0xF0 ... 0xF7: /* FCOMIP %st(0),%st(?) */
6219                /* not really right since COMIP != UCOMIP */
6220                fp_do_ucomi_ST0_STi( (UInt)modrm - 0xF0, True );
6221                break;
6222
6223             default: 
6224                goto decode_fail;
6225          }
6226       }
6227
6228    }
6229
6230    else
6231       goto decode_fail;
6232
6233    *decode_ok = True;
6234    return delta;
6235
6236   decode_fail:
6237    *decode_ok = False;
6238    return delta;
6239 }
6240
6241
6242 /*------------------------------------------------------------*/
6243 /*---                                                      ---*/
6244 /*--- MMX INSTRUCTIONS                                     ---*/
6245 /*---                                                      ---*/
6246 /*------------------------------------------------------------*/
6247
6248 /* Effect of MMX insns on x87 FPU state (table 11-2 of 
6249    IA32 arch manual, volume 3):
6250
6251    Read from, or write to MMX register (viz, any insn except EMMS):
6252    * All tags set to Valid (non-empty) -- FPTAGS[i] := nonzero
6253    * FP stack pointer set to zero
6254
6255    EMMS:
6256    * All tags set to Invalid (empty) -- FPTAGS[i] := zero
6257    * FP stack pointer set to zero
6258 */
6259
6260 static void do_MMX_preamble ( void )
6261 {
6262    Int         i;
6263    IRRegArray* descr = mkIRRegArray( OFFB_FPTAGS, Ity_I8, 8 );
6264    IRExpr*     zero  = mkU32(0);
6265    IRExpr*     tag1  = mkU8(1);
6266    put_ftop(zero);
6267    for (i = 0; i < 8; i++)
6268       stmt( IRStmt_PutI( descr, zero, i, tag1 ) );
6269 }
6270
6271 static void do_EMMS_preamble ( void )
6272 {
6273    Int         i;
6274    IRRegArray* descr = mkIRRegArray( OFFB_FPTAGS, Ity_I8, 8 );
6275    IRExpr*     zero  = mkU32(0);
6276    IRExpr*     tag0  = mkU8(0);
6277    put_ftop(zero);
6278    for (i = 0; i < 8; i++)
6279       stmt( IRStmt_PutI( descr, zero, i, tag0 ) );
6280 }
6281
6282
6283 static IRExpr* getMMXReg ( UInt archreg )
6284 {
6285    vassert(archreg < 8);
6286    return IRExpr_Get( OFFB_FPREGS + 8 * archreg, Ity_I64 );
6287 }
6288
6289
6290 static void putMMXReg ( UInt archreg, IRExpr* e )
6291 {
6292    vassert(archreg < 8);
6293    vassert(typeOfIRExpr(irsb->tyenv,e) == Ity_I64);
6294    stmt( IRStmt_Put( OFFB_FPREGS + 8 * archreg, e ) );
6295 }
6296
6297
6298 /* Helper for non-shift MMX insns.  Note this is incomplete in the
6299    sense that it does not first call do_MMX_preamble() -- that is the
6300    responsibility of its caller. */
6301
6302 static 
6303 ULong dis_MMXop_regmem_to_reg ( VexAbiInfo* vbi,
6304                                 Prefix      pfx,
6305                                 Long        delta,
6306                                 UChar       opc,
6307                                 HChar*      name,
6308                                 Bool        show_granularity )
6309 {
6310    HChar   dis_buf[50];
6311    UChar   modrm = getUChar(delta);
6312    Bool    isReg = epartIsReg(modrm);
6313    IRExpr* argL  = NULL;
6314    IRExpr* argR  = NULL;
6315    IRExpr* argG  = NULL;
6316    IRExpr* argE  = NULL;
6317    IRTemp  res   = newTemp(Ity_I64);
6318
6319    Bool    invG  = False;
6320    IROp    op    = Iop_INVALID;
6321    void*   hAddr = NULL;
6322    HChar*  hName = NULL;
6323    Bool    eLeft = False;
6324
6325 #  define XXX(_name) do { hAddr = &_name; hName = #_name; } while (0)
6326
6327    switch (opc) {
6328       /* Original MMX ones */
6329       case 0xFC: op = Iop_Add8x8; break;
6330       case 0xFD: op = Iop_Add16x4; break;
6331       case 0xFE: op = Iop_Add32x2; break;
6332
6333       case 0xEC: op = Iop_QAdd8Sx8; break;
6334       case 0xED: op = Iop_QAdd16Sx4; break;
6335
6336       case 0xDC: op = Iop_QAdd8Ux8; break;
6337       case 0xDD: op = Iop_QAdd16Ux4; break;
6338
6339       case 0xF8: op = Iop_Sub8x8;  break;
6340       case 0xF9: op = Iop_Sub16x4; break;
6341       case 0xFA: op = Iop_Sub32x2; break;
6342
6343       case 0xE8: op = Iop_QSub8Sx8; break;
6344       case 0xE9: op = Iop_QSub16Sx4; break;
6345
6346       case 0xD8: op = Iop_QSub8Ux8; break;
6347       case 0xD9: op = Iop_QSub16Ux4; break;
6348
6349       case 0xE5: op = Iop_MulHi16Sx4; break;
6350       case 0xD5: op = Iop_Mul16x4; break;
6351       case 0xF5: XXX(amd64g_calculate_mmx_pmaddwd); break;
6352
6353       case 0x74: op = Iop_CmpEQ8x8; break;
6354       case 0x75: op = Iop_CmpEQ16x4; break;
6355       case 0x76: op = Iop_CmpEQ32x2; break;
6356
6357       case 0x64: op = Iop_CmpGT8Sx8; break;
6358       case 0x65: op = Iop_CmpGT16Sx4; break;
6359       case 0x66: op = Iop_CmpGT32Sx2; break;
6360
6361       case 0x6B: op = Iop_QNarrow32Sx2; eLeft = True; break;
6362       case 0x63: op = Iop_QNarrow16Sx4; eLeft = True; break;
6363       case 0x67: op = Iop_QNarrow16Ux4; eLeft = True; break;
6364
6365       case 0x68: op = Iop_InterleaveHI8x8;  eLeft = True; break;
6366       case 0x69: op = Iop_InterleaveHI16x4; eLeft = True; break;
6367       case 0x6A: op = Iop_InterleaveHI32x2; eLeft = True; break;
6368
6369       case 0x60: op = Iop_InterleaveLO8x8;  eLeft = True; break;
6370       case 0x61: op = Iop_InterleaveLO16x4; eLeft = True; break;
6371       case 0x62: op = Iop_InterleaveLO32x2; eLeft = True; break;
6372
6373       case 0xDB: op = Iop_And64; break;
6374       case 0xDF: op = Iop_And64; invG = True; break;
6375       case 0xEB: op = Iop_Or64; break;
6376       case 0xEF: /* Possibly do better here if argL and argR are the
6377                     same reg */
6378                  op = Iop_Xor64; break;
6379
6380       /* Introduced in SSE1 */
6381       case 0xE0: op = Iop_Avg8Ux8;    break;
6382       case 0xE3: op = Iop_Avg16Ux4;   break;
6383       case 0xEE: op = Iop_Max16Sx4;   break;
6384       case 0xDE: op = Iop_Max8Ux8;    break;
6385       case 0xEA: op = Iop_Min16Sx4;   break;
6386       case 0xDA: op = Iop_Min8Ux8;    break;
6387       case 0xE4: op = Iop_MulHi16Ux4; break;
6388       case 0xF6: XXX(amd64g_calculate_mmx_psadbw); break;
6389
6390       /* Introduced in SSE2 */
6391       case 0xD4: op = Iop_Add64; break;
6392       case 0xFB: op = Iop_Sub64; break;
6393
6394       default: 
6395          vex_printf("\n0x%x\n", (Int)opc);
6396          vpanic("dis_MMXop_regmem_to_reg");
6397    }
6398
6399 #  undef XXX
6400
6401    argG = getMMXReg(gregLO3ofRM(modrm));
6402    if (invG)
6403       argG = unop(Iop_Not64, argG);
6404
6405    if (isReg) {
6406       delta++;
6407       argE = getMMXReg(eregLO3ofRM(modrm));
6408    } else {
6409       Int    len;
6410       IRTemp addr = disAMode( &len, vbi, pfx, delta, dis_buf, 0 );
6411       delta += len;
6412       argE = loadLE(Ity_I64, mkexpr(addr));
6413    }
6414
6415    if (eLeft) {
6416       argL = argE;
6417       argR = argG;
6418    } else {
6419       argL = argG;
6420       argR = argE;
6421    }
6422
6423    if (op != Iop_INVALID) {
6424       vassert(hName == NULL);
6425       vassert(hAddr == NULL);
6426       assign(res, binop(op, argL, argR));
6427    } else {
6428       vassert(hName != NULL);
6429       vassert(hAddr != NULL);
6430       assign( res, 
6431               mkIRExprCCall(
6432                  Ity_I64, 
6433                  0/*regparms*/, hName, hAddr,
6434                  mkIRExprVec_2( argL, argR )
6435               ) 
6436             );
6437    }
6438
6439    putMMXReg( gregLO3ofRM(modrm), mkexpr(res) );
6440
6441    DIP("%s%s %s, %s\n", 
6442        name, show_granularity ? nameMMXGran(opc & 3) : "",
6443        ( isReg ? nameMMXReg(eregLO3ofRM(modrm)) : dis_buf ),
6444        nameMMXReg(gregLO3ofRM(modrm)) );
6445
6446    return delta;
6447 }
6448
6449
6450 /* Vector by scalar shift of G by the amount specified at the bottom
6451    of E.  This is a straight copy of dis_SSE_shiftG_byE. */
6452
6453 static ULong dis_MMX_shiftG_byE ( VexAbiInfo* vbi,
6454                                   Prefix pfx, Long delta, 
6455                                   HChar* opname, IROp op )
6456 {
6457    HChar   dis_buf[50];
6458    Int     alen, size;
6459    IRTemp  addr;
6460    Bool    shl, shr, sar;
6461    UChar   rm   = getUChar(delta);
6462    IRTemp  g0   = newTemp(Ity_I64);
6463    IRTemp  g1   = newTemp(Ity_I64);
6464    IRTemp  amt  = newTemp(Ity_I64);
6465    IRTemp  amt8 = newTemp(Ity_I8);
6466
6467    if (epartIsReg(rm)) {
6468       assign( amt, getMMXReg(eregLO3ofRM(rm)) );
6469       DIP("%s %s,%s\n", opname,
6470                         nameMMXReg(eregLO3ofRM(rm)),
6471                         nameMMXReg(gregLO3ofRM(rm)) );
6472       delta++;
6473    } else {
6474       addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
6475       assign( amt, loadLE(Ity_I64, mkexpr(addr)) );
6476       DIP("%s %s,%s\n", opname,
6477                         dis_buf,
6478                         nameMMXReg(gregLO3ofRM(rm)) );
6479       delta += alen;
6480    }
6481    assign( g0,   getMMXReg(gregLO3ofRM(rm)) );
6482    assign( amt8, unop(Iop_64to8, mkexpr(amt)) );
6483
6484    shl = shr = sar = False;
6485    size = 0;
6486    switch (op) {
6487       case Iop_ShlN16x4: shl = True; size = 32; break;
6488       case Iop_ShlN32x2: shl = True; size = 32; break;
6489       case Iop_Shl64:    shl = True; size = 64; break;
6490       case Iop_ShrN16x4: shr = True; size = 16; break;
6491       case Iop_ShrN32x2: shr = True; size = 32; break;
6492       case Iop_Shr64:    shr = True; size = 64; break;
6493       case Iop_SarN16x4: sar = True; size = 16; break;
6494       case Iop_SarN32x2: sar = True; size = 32; break;
6495       default: vassert(0);
6496    }
6497
6498    if (shl || shr) {
6499      assign( 
6500         g1,
6501         IRExpr_Mux0X(
6502            unop(Iop_1Uto8,binop(Iop_CmpLT64U,mkexpr(amt),mkU64(size))),
6503            mkU64(0),
6504            binop(op, mkexpr(g0), mkexpr(amt8))
6505         )
6506      );
6507    } else 
6508    if (sar) {
6509      assign( 
6510         g1,
6511         IRExpr_Mux0X(
6512            unop(Iop_1Uto8,binop(Iop_CmpLT64U,mkexpr(amt),mkU64(size))),
6513            binop(op, mkexpr(g0), mkU8(size-1)),
6514            binop(op, mkexpr(g0), mkexpr(amt8))
6515         )
6516      );
6517    } else {
6518       vassert(0);
6519    }
6520
6521    putMMXReg( gregLO3ofRM(rm), mkexpr(g1) );
6522    return delta;
6523 }
6524
6525
6526 /* Vector by scalar shift of E by an immediate byte.  This is a
6527    straight copy of dis_SSE_shiftE_imm. */
6528
6529 static 
6530 ULong dis_MMX_shiftE_imm ( Long delta, HChar* opname, IROp op )
6531 {
6532    Bool    shl, shr, sar;
6533    UChar   rm   = getUChar(delta);
6534    IRTemp  e0   = newTemp(Ity_I64);
6535    IRTemp  e1   = newTemp(Ity_I64);
6536    UChar   amt, size;
6537    vassert(epartIsReg(rm));
6538    vassert(gregLO3ofRM(rm) == 2 
6539            || gregLO3ofRM(rm) == 4 || gregLO3ofRM(rm) == 6);
6540    amt = getUChar(delta+1);
6541    delta += 2;
6542    DIP("%s $%d,%s\n", opname,
6543                       (Int)amt,
6544                       nameMMXReg(eregLO3ofRM(rm)) );
6545
6546    assign( e0, getMMXReg(eregLO3ofRM(rm)) );
6547
6548    shl = shr = sar = False;
6549    size = 0;
6550    switch (op) {
6551       case Iop_ShlN16x4: shl = True; size = 16; break;
6552       case Iop_ShlN32x2: shl = True; size = 32; break;
6553       case Iop_Shl64:    shl = True; size = 64; break;
6554       case Iop_SarN16x4: sar = True; size = 16; break;
6555       case Iop_SarN32x2: sar = True; size = 32; break;
6556       case Iop_ShrN16x4: shr = True; size = 16; break;
6557       case Iop_ShrN32x2: shr = True; size = 32; break;
6558       case Iop_Shr64:    shr = True; size = 64; break;
6559       default: vassert(0);
6560    }
6561
6562    if (shl || shr) {
6563      assign( e1, amt >= size 
6564                     ? mkU64(0)
6565                     : binop(op, mkexpr(e0), mkU8(amt))
6566      );
6567    } else 
6568    if (sar) {
6569      assign( e1, amt >= size 
6570                     ? binop(op, mkexpr(e0), mkU8(size-1))
6571                     : binop(op, mkexpr(e0), mkU8(amt))
6572      );
6573    } else {
6574       vassert(0);
6575    }
6576
6577    putMMXReg( eregLO3ofRM(rm), mkexpr(e1) );
6578    return delta;
6579 }
6580
6581
6582 /* Completely handle all MMX instructions except emms. */
6583
6584 static
6585 ULong dis_MMX ( Bool* decode_ok,
6586                 VexAbiInfo* vbi, Prefix pfx, Int sz, Long delta )
6587 {
6588    Int   len;
6589    UChar modrm;
6590    HChar dis_buf[50];
6591    UChar opc = getUChar(delta);
6592    delta++;
6593
6594    /* dis_MMX handles all insns except emms. */
6595    do_MMX_preamble();
6596
6597    switch (opc) {
6598
6599       case 0x6E: 
6600          if (sz == 4) {
6601             /* MOVD (src)ireg32-or-mem32 (E), (dst)mmxreg (G)*/
6602             modrm = getUChar(delta);
6603             if (epartIsReg(modrm)) {
6604                delta++;
6605                putMMXReg(
6606                   gregLO3ofRM(modrm),
6607                   binop( Iop_32HLto64,
6608                          mkU32(0),
6609                          getIReg32(eregOfRexRM(pfx,modrm)) ) );
6610                DIP("movd %s, %s\n", 
6611                    nameIReg32(eregOfRexRM(pfx,modrm)), 
6612                    nameMMXReg(gregLO3ofRM(modrm)));
6613             } else {
6614                IRTemp addr = disAMode( &len, vbi, pfx, delta, dis_buf, 0 );
6615                delta += len;
6616                putMMXReg(
6617                   gregLO3ofRM(modrm),
6618                   binop( Iop_32HLto64,
6619                          mkU32(0),
6620                          loadLE(Ity_I32, mkexpr(addr)) ) );
6621                DIP("movd %s, %s\n", dis_buf, nameMMXReg(gregLO3ofRM(modrm)));
6622             }
6623          } 
6624          else
6625          if (sz == 8) {
6626             /* MOVD (src)ireg64-or-mem64 (E), (dst)mmxreg (G)*/
6627             modrm = getUChar(delta);
6628             if (epartIsReg(modrm)) {
6629                delta++;
6630                putMMXReg( gregLO3ofRM(modrm),
6631                           getIReg64(eregOfRexRM(pfx,modrm)) );
6632                DIP("movd %s, %s\n", 
6633                    nameIReg64(eregOfRexRM(pfx,modrm)), 
6634                    nameMMXReg(gregLO3ofRM(modrm)));
6635             } else {
6636                IRTemp addr = disAMode( &len, vbi, pfx, delta, dis_buf, 0 );
6637                delta += len;
6638                putMMXReg( gregLO3ofRM(modrm),
6639                           loadLE(Ity_I64, mkexpr(addr)) );
6640                DIP("movd{64} %s, %s\n", dis_buf, nameMMXReg(gregLO3ofRM(modrm)));
6641             }
6642          }
6643          else {
6644             goto mmx_decode_failure;
6645          }
6646          break;
6647
6648       case 0x7E:
6649          if (sz == 4) {
6650             /* MOVD (src)mmxreg (G), (dst)ireg32-or-mem32 (E) */
6651             modrm = getUChar(delta);
6652             if (epartIsReg(modrm)) {
6653                delta++;
6654                putIReg32( eregOfRexRM(pfx,modrm),
6655                           unop(Iop_64to32, getMMXReg(gregLO3ofRM(modrm)) ) );
6656                DIP("movd %s, %s\n", 
6657                    nameMMXReg(gregLO3ofRM(modrm)), 
6658                    nameIReg32(eregOfRexRM(pfx,modrm)));
6659             } else {
6660                IRTemp addr = disAMode( &len, vbi, pfx, delta, dis_buf, 0 );
6661                delta += len;
6662                storeLE( mkexpr(addr),
6663                         unop(Iop_64to32, getMMXReg(gregLO3ofRM(modrm)) ) );
6664                DIP("movd %s, %s\n", nameMMXReg(gregLO3ofRM(modrm)), dis_buf);
6665             }
6666          }
6667          else
6668          if (sz == 8) {
6669             /* MOVD (src)mmxreg (G), (dst)ireg64-or-mem64 (E) */
6670             modrm = getUChar(delta);
6671             if (epartIsReg(modrm)) {
6672                delta++;
6673                putIReg64( eregOfRexRM(pfx,modrm),
6674                           getMMXReg(gregLO3ofRM(modrm)) );
6675                DIP("movd %s, %s\n", 
6676                    nameMMXReg(gregLO3ofRM(modrm)), 
6677                    nameIReg64(eregOfRexRM(pfx,modrm)));
6678             } else {
6679                IRTemp addr = disAMode( &len, vbi, pfx, delta, dis_buf, 0 );
6680                delta += len;
6681                storeLE( mkexpr(addr),
6682                        getMMXReg(gregLO3ofRM(modrm)) );
6683                DIP("movd{64} %s, %s\n", nameMMXReg(gregLO3ofRM(modrm)), dis_buf);
6684             }
6685          } else {
6686             goto mmx_decode_failure;
6687          }
6688          break;
6689
6690       case 0x6F:
6691          /* MOVQ (src)mmxreg-or-mem, (dst)mmxreg */
6692          if (sz != 4
6693              && /*ignore redundant REX.W*/!(sz==8 && haveNo66noF2noF3(pfx))) 
6694             goto mmx_decode_failure;
6695          modrm = getUChar(delta);
6696          if (epartIsReg(modrm)) {
6697             delta++;
6698             putMMXReg( gregLO3ofRM(modrm), getMMXReg(eregLO3ofRM(modrm)) );
6699             DIP("movq %s, %s\n", 
6700                 nameMMXReg(eregLO3ofRM(modrm)), 
6701                 nameMMXReg(gregLO3ofRM(modrm)));
6702          } else {
6703             IRTemp addr = disAMode( &len, vbi, pfx, delta, dis_buf, 0 );
6704             delta += len;
6705             putMMXReg( gregLO3ofRM(modrm), loadLE(Ity_I64, mkexpr(addr)) );
6706             DIP("movq %s, %s\n", 
6707                 dis_buf, nameMMXReg(gregLO3ofRM(modrm)));
6708          }
6709          break;
6710
6711       case 0x7F:
6712          /* MOVQ (src)mmxreg, (dst)mmxreg-or-mem */
6713          if (sz != 4
6714              && /*ignore redundant REX.W*/!(sz==8 && haveNo66noF2noF3(pfx)))
6715             goto mmx_decode_failure;
6716          modrm = getUChar(delta);
6717          if (epartIsReg(modrm)) {
6718             /* Fall through.  The assembler doesn't appear to generate
6719                these. */
6720             goto mmx_decode_failure;
6721          } else {
6722             IRTemp addr = disAMode( &len, vbi, pfx, delta, dis_buf, 0 );
6723             delta += len;
6724             storeLE( mkexpr(addr), getMMXReg(gregLO3ofRM(modrm)) );
6725             DIP("mov(nt)q %s, %s\n", 
6726                 nameMMXReg(gregLO3ofRM(modrm)), dis_buf);
6727          }
6728          break;
6729
6730       case 0xFC: 
6731       case 0xFD: 
6732       case 0xFE: /* PADDgg (src)mmxreg-or-mem, (dst)mmxreg */
6733          if (sz != 4) 
6734             goto mmx_decode_failure;
6735          delta = dis_MMXop_regmem_to_reg ( vbi, pfx, delta, opc, "padd", True );
6736          break;
6737
6738       case 0xEC: 
6739       case 0xED: /* PADDSgg (src)mmxreg-or-mem, (dst)mmxreg */
6740          if (sz != 4
6741              && /*ignore redundant REX.W*/!(sz==8 && haveNo66noF2noF3(pfx)))
6742             goto mmx_decode_failure;
6743          delta = dis_MMXop_regmem_to_reg ( vbi, pfx, delta, opc, "padds", True );
6744          break;
6745
6746       case 0xDC: 
6747       case 0xDD: /* PADDUSgg (src)mmxreg-or-mem, (dst)mmxreg */
6748          if (sz != 4) 
6749             goto mmx_decode_failure;
6750          delta = dis_MMXop_regmem_to_reg ( vbi, pfx, delta, opc, "paddus", True );
6751          break;
6752
6753       case 0xF8: 
6754       case 0xF9: 
6755       case 0xFA: /* PSUBgg (src)mmxreg-or-mem, (dst)mmxreg */
6756          if (sz != 4) 
6757             goto mmx_decode_failure;
6758          delta = dis_MMXop_regmem_to_reg ( vbi, pfx, delta, opc, "psub", True );
6759          break;
6760
6761       case 0xE8: 
6762       case 0xE9: /* PSUBSgg (src)mmxreg-or-mem, (dst)mmxreg */
6763          if (sz != 4) 
6764             goto mmx_decode_failure;
6765          delta = dis_MMXop_regmem_to_reg ( vbi, pfx, delta, opc, "psubs", True );
6766          break;
6767
6768       case 0xD8: 
6769       case 0xD9: /* PSUBUSgg (src)mmxreg-or-mem, (dst)mmxreg */
6770          if (sz != 4) 
6771             goto mmx_decode_failure;
6772          delta = dis_MMXop_regmem_to_reg ( vbi, pfx, delta, opc, "psubus", True );
6773          break;
6774
6775       case 0xE5: /* PMULHW (src)mmxreg-or-mem, (dst)mmxreg */
6776          if (sz != 4) 
6777             goto mmx_decode_failure;
6778          delta = dis_MMXop_regmem_to_reg ( vbi, pfx, delta, opc, "pmulhw", False );
6779          break;
6780
6781       case 0xD5: /* PMULLW (src)mmxreg-or-mem, (dst)mmxreg */
6782          if (sz != 4) 
6783             goto mmx_decode_failure;
6784          delta = dis_MMXop_regmem_to_reg ( vbi, pfx, delta, opc, "pmullw", False );
6785          break;
6786
6787       case 0xF5: /* PMADDWD (src)mmxreg-or-mem, (dst)mmxreg */
6788          vassert(sz == 4);
6789          delta = dis_MMXop_regmem_to_reg ( vbi, pfx, delta, opc, "pmaddwd", False );
6790          break;
6791
6792       case 0x74: 
6793       case 0x75: 
6794       case 0x76: /* PCMPEQgg (src)mmxreg-or-mem, (dst)mmxreg */
6795          if (sz != 4) 
6796             goto mmx_decode_failure;
6797          delta = dis_MMXop_regmem_to_reg ( vbi, pfx, delta, opc, "pcmpeq", True );
6798          break;
6799
6800       case 0x64: 
6801       case 0x65: 
6802       case 0x66: /* PCMPGTgg (src)mmxreg-or-mem, (dst)mmxreg */
6803          if (sz != 4) 
6804             goto mmx_decode_failure;
6805          delta = dis_MMXop_regmem_to_reg ( vbi, pfx, delta, opc, "pcmpgt", True );
6806          break;
6807
6808       case 0x6B: /* PACKSSDW (src)mmxreg-or-mem, (dst)mmxreg */
6809          if (sz != 4) 
6810             goto mmx_decode_failure;
6811          delta = dis_MMXop_regmem_to_reg ( vbi, pfx, delta, opc, "packssdw", False );
6812          break;
6813
6814       case 0x63: /* PACKSSWB (src)mmxreg-or-mem, (dst)mmxreg */
6815          if (sz != 4) 
6816             goto mmx_decode_failure;
6817          delta = dis_MMXop_regmem_to_reg ( vbi, pfx, delta, opc, "packsswb", False );
6818          break;
6819
6820       case 0x67: /* PACKUSWB (src)mmxreg-or-mem, (dst)mmxreg */
6821          if (sz != 4) 
6822             goto mmx_decode_failure;
6823          delta = dis_MMXop_regmem_to_reg ( vbi, pfx, delta, opc, "packuswb", False );
6824          break;
6825
6826       case 0x68: 
6827       case 0x69: 
6828       case 0x6A: /* PUNPCKHgg (src)mmxreg-or-mem, (dst)mmxreg */
6829          if (sz != 4
6830              && /*ignore redundant REX.W*/!(sz==8 && haveNo66noF2noF3(pfx))) 
6831             goto mmx_decode_failure;
6832          delta = dis_MMXop_regmem_to_reg ( vbi, pfx, delta, opc, "punpckh", True );
6833          break;
6834
6835       case 0x60: 
6836       case 0x61: 
6837       case 0x62: /* PUNPCKLgg (src)mmxreg-or-mem, (dst)mmxreg */
6838          if (sz != 4
6839              && /*ignore redundant REX.W*/!(sz==8 && haveNo66noF2noF3(pfx))) 
6840             goto mmx_decode_failure;
6841          delta = dis_MMXop_regmem_to_reg ( vbi, pfx, delta, opc, "punpckl", True );
6842          break;
6843
6844       case 0xDB: /* PAND (src)mmxreg-or-mem, (dst)mmxreg */
6845          if (sz != 4) 
6846             goto mmx_decode_failure;
6847          delta = dis_MMXop_regmem_to_reg ( vbi, pfx, delta, opc, "pand", False );
6848          break;
6849
6850       case 0xDF: /* PANDN (src)mmxreg-or-mem, (dst)mmxreg */
6851          if (sz != 4) 
6852             goto mmx_decode_failure;
6853          delta = dis_MMXop_regmem_to_reg ( vbi, pfx, delta, opc, "pandn", False );
6854          break;
6855
6856       case 0xEB: /* POR (src)mmxreg-or-mem, (dst)mmxreg */
6857          if (sz != 4) 
6858             goto mmx_decode_failure;
6859          delta = dis_MMXop_regmem_to_reg ( vbi, pfx, delta, opc, "por", False );
6860          break;
6861
6862       case 0xEF: /* PXOR (src)mmxreg-or-mem, (dst)mmxreg */
6863          if (sz != 4) 
6864             goto mmx_decode_failure;
6865          delta = dis_MMXop_regmem_to_reg ( vbi, pfx, delta, opc, "pxor", False );
6866          break; 
6867
6868 #     define SHIFT_BY_REG(_name,_op)                                     \
6869                 delta = dis_MMX_shiftG_byE(vbi, pfx, delta, _name, _op); \
6870                 break;
6871
6872       /* PSLLgg (src)mmxreg-or-mem, (dst)mmxreg */
6873       case 0xF1: SHIFT_BY_REG("psllw", Iop_ShlN16x4);
6874       case 0xF2: SHIFT_BY_REG("pslld", Iop_ShlN32x2);
6875       case 0xF3: SHIFT_BY_REG("psllq", Iop_Shl64);
6876
6877       /* PSRLgg (src)mmxreg-or-mem, (dst)mmxreg */
6878       case 0xD1: SHIFT_BY_REG("psrlw", Iop_ShrN16x4);
6879       case 0xD2: SHIFT_BY_REG("psrld", Iop_ShrN32x2);
6880       case 0xD3: SHIFT_BY_REG("psrlq", Iop_Shr64);
6881
6882       /* PSRAgg (src)mmxreg-or-mem, (dst)mmxreg */
6883       case 0xE1: SHIFT_BY_REG("psraw", Iop_SarN16x4);
6884       case 0xE2: SHIFT_BY_REG("psrad", Iop_SarN32x2);
6885
6886 #     undef SHIFT_BY_REG
6887
6888       case 0x71: 
6889       case 0x72: 
6890       case 0x73: {
6891          /* (sz==4): PSLLgg/PSRAgg/PSRLgg mmxreg by imm8 */
6892          UChar byte2, subopc;
6893          if (sz != 4) 
6894             goto mmx_decode_failure;
6895          byte2  = getUChar(delta);      /* amode / sub-opcode */
6896          subopc = toUChar( (byte2 >> 3) & 7 );
6897
6898 #        define SHIFT_BY_IMM(_name,_op)                        \
6899             do { delta = dis_MMX_shiftE_imm(delta,_name,_op);  \
6900             } while (0)
6901
6902               if (subopc == 2 /*SRL*/ && opc == 0x71) 
6903                   SHIFT_BY_IMM("psrlw", Iop_ShrN16x4);
6904          else if (subopc == 2 /*SRL*/ && opc == 0x72) 
6905                  SHIFT_BY_IMM("psrld", Iop_ShrN32x2);
6906          else if (subopc == 2 /*SRL*/ && opc == 0x73) 
6907                  SHIFT_BY_IMM("psrlq", Iop_Shr64);
6908
6909          else if (subopc == 4 /*SAR*/ && opc == 0x71) 
6910                  SHIFT_BY_IMM("psraw", Iop_SarN16x4);
6911          else if (subopc == 4 /*SAR*/ && opc == 0x72) 
6912                  SHIFT_BY_IMM("psrad", Iop_SarN32x2);
6913
6914          else if (subopc == 6 /*SHL*/ && opc == 0x71) 
6915                  SHIFT_BY_IMM("psllw", Iop_ShlN16x4);
6916          else if (subopc == 6 /*SHL*/ && opc == 0x72) 
6917                   SHIFT_BY_IMM("pslld", Iop_ShlN32x2);
6918          else if (subopc == 6 /*SHL*/ && opc == 0x73) 
6919                  SHIFT_BY_IMM("psllq", Iop_Shl64);
6920
6921          else goto mmx_decode_failure;
6922
6923 #        undef SHIFT_BY_IMM
6924          break;
6925       }
6926
6927       case 0xF7: {
6928          IRTemp addr    = newTemp(Ity_I64);
6929          IRTemp regD    = newTemp(Ity_I64);
6930          IRTemp regM    = newTemp(Ity_I64);
6931          IRTemp mask    = newTemp(Ity_I64);
6932          IRTemp olddata = newTemp(Ity_I64);
6933          IRTemp newdata = newTemp(Ity_I64);
6934
6935          modrm = getUChar(delta);
6936          if (sz != 4 || (!epartIsReg(modrm)))
6937             goto mmx_decode_failure;
6938          delta++;
6939
6940          assign( addr, handleAddrOverrides( vbi, pfx, getIReg64(R_RDI) ));
6941          assign( regM, getMMXReg( eregLO3ofRM(modrm) ));
6942          assign( regD, getMMXReg( gregLO3ofRM(modrm) ));
6943          assign( mask, binop(Iop_SarN8x8, mkexpr(regM), mkU8(7)) );
6944          assign( olddata, loadLE( Ity_I64, mkexpr(addr) ));
6945          assign( newdata, 
6946                  binop(Iop_Or64, 
6947                        binop(Iop_And64, 
6948                              mkexpr(regD), 
6949                              mkexpr(mask) ),
6950                        binop(Iop_And64, 
6951                              mkexpr(olddata),
6952                              unop(Iop_Not64, mkexpr(mask)))) );
6953          storeLE( mkexpr(addr), mkexpr(newdata) );
6954          DIP("maskmovq %s,%s\n", nameMMXReg( eregLO3ofRM(modrm) ),
6955                                  nameMMXReg( gregLO3ofRM(modrm) ) );
6956          break;
6957       }
6958
6959       /* --- MMX decode failure --- */
6960       default:
6961       mmx_decode_failure:
6962          *decode_ok = False;
6963          return delta; /* ignored */
6964
6965    }
6966
6967    *decode_ok = True;
6968    return delta;
6969 }
6970
6971
6972 /*------------------------------------------------------------*/
6973 /*--- More misc arithmetic and other obscure insns.        ---*/
6974 /*------------------------------------------------------------*/
6975
6976 /* Generate base << amt with vacated places filled with stuff
6977    from xtra.  amt guaranteed in 0 .. 63. */
6978 static 
6979 IRExpr* shiftL64_with_extras ( IRTemp base, IRTemp xtra, IRTemp amt )
6980 {
6981    /* if   amt == 0 
6982       then base
6983       else (base << amt) | (xtra >>u (64-amt))
6984    */
6985    return
6986       IRExpr_Mux0X( 
6987          mkexpr(amt), 
6988          mkexpr(base),
6989          binop(Iop_Or64, 
6990                binop(Iop_Shl64, mkexpr(base), mkexpr(amt)),
6991                binop(Iop_Shr64, mkexpr(xtra), 
6992                                 binop(Iop_Sub8, mkU8(64), mkexpr(amt)))
6993          )
6994       );
6995 }
6996
6997 /* Generate base >>u amt with vacated places filled with stuff
6998    from xtra.  amt guaranteed in 0 .. 63. */
6999 static 
7000 IRExpr* shiftR64_with_extras ( IRTemp xtra, IRTemp base, IRTemp amt )
7001 {
7002    /* if   amt == 0 
7003       then base
7004       else (base >>u amt) | (xtra << (64-amt))
7005    */
7006    return
7007       IRExpr_Mux0X( 
7008          mkexpr(amt), 
7009          mkexpr(base),
7010          binop(Iop_Or64, 
7011                binop(Iop_Shr64, mkexpr(base), mkexpr(amt)),
7012                binop(Iop_Shl64, mkexpr(xtra), 
7013                                 binop(Iop_Sub8, mkU8(64), mkexpr(amt)))
7014          )
7015       );
7016 }
7017
7018 /* Double length left and right shifts.  Apparently only required in
7019    v-size (no b- variant). */
7020 static
7021 ULong dis_SHLRD_Gv_Ev ( VexAbiInfo* vbi,
7022                         Prefix pfx,
7023                         Long delta, UChar modrm,
7024                         Int sz,
7025                         IRExpr* shift_amt,
7026                         Bool amt_is_literal,
7027                         HChar* shift_amt_txt,
7028                         Bool left_shift )
7029 {
7030    /* shift_amt :: Ity_I8 is the amount to shift.  shift_amt_txt is used
7031       for printing it.   And eip on entry points at the modrm byte. */
7032    Int len;
7033    HChar dis_buf[50];
7034
7035    IRType ty     = szToITy(sz);
7036    IRTemp gsrc   = newTemp(ty);
7037    IRTemp esrc   = newTemp(ty);
7038    IRTemp addr   = IRTemp_INVALID;
7039    IRTemp tmpSH  = newTemp(Ity_I8);
7040    IRTemp tmpSS  = newTemp(Ity_I8);
7041    IRTemp tmp64  = IRTemp_INVALID;
7042    IRTemp res64  = IRTemp_INVALID;
7043    IRTemp rss64  = IRTemp_INVALID;
7044    IRTemp resTy  = IRTemp_INVALID;
7045    IRTemp rssTy  = IRTemp_INVALID;
7046    Int    mask   = sz==8 ? 63 : 31;
7047
7048    vassert(sz == 2 || sz == 4 || sz == 8);
7049
7050    /* The E-part is the destination; this is shifted.  The G-part
7051       supplies bits to be shifted into the E-part, but is not
7052       changed.  
7053
7054       If shifting left, form a double-length word with E at the top
7055       and G at the bottom, and shift this left.  The result is then in
7056       the high part.
7057
7058       If shifting right, form a double-length word with G at the top
7059       and E at the bottom, and shift this right.  The result is then
7060       at the bottom.  */
7061
7062    /* Fetch the operands. */
7063
7064    assign( gsrc, getIRegG(sz, pfx, modrm) );
7065
7066    if (epartIsReg(modrm)) {
7067       delta++;
7068       assign( esrc, getIRegE(sz, pfx, modrm) );
7069       DIP("sh%cd%c %s, %s, %s\n",
7070           ( left_shift ? 'l' : 'r' ), nameISize(sz), 
7071           shift_amt_txt,
7072           nameIRegG(sz, pfx, modrm), nameIRegE(sz, pfx, modrm));
7073    } else {
7074       addr = disAMode ( &len, vbi, pfx, delta, dis_buf, 
7075                         /* # bytes following amode */
7076                         amt_is_literal ? 1 : 0 );
7077       delta += len;
7078       assign( esrc, loadLE(ty, mkexpr(addr)) );
7079       DIP("sh%cd%c %s, %s, %s\n", 
7080           ( left_shift ? 'l' : 'r' ), nameISize(sz), 
7081           shift_amt_txt,
7082           nameIRegG(sz, pfx, modrm), dis_buf);
7083    }
7084
7085    /* Calculate the masked shift amount (tmpSH), the masked subshift
7086       amount (tmpSS), the shifted value (res64) and the subshifted
7087       value (rss64). */
7088
7089    assign( tmpSH, binop(Iop_And8, shift_amt, mkU8(mask)) );
7090    assign( tmpSS, binop(Iop_And8, 
7091                         binop(Iop_Sub8, mkexpr(tmpSH), mkU8(1) ),
7092                         mkU8(mask)));
7093
7094    tmp64 = newTemp(Ity_I64);
7095    res64 = newTemp(Ity_I64);
7096    rss64 = newTemp(Ity_I64);
7097
7098    if (sz == 2 || sz == 4) {
7099
7100       /* G is xtra; E is data */
7101       /* what a freaking nightmare: */
7102       if (sz == 4 && left_shift) {
7103          assign( tmp64, binop(Iop_32HLto64, mkexpr(esrc), mkexpr(gsrc)) );
7104          assign( res64, 
7105                  binop(Iop_Shr64, 
7106                        binop(Iop_Shl64, mkexpr(tmp64), mkexpr(tmpSH)),
7107                        mkU8(32)) );
7108          assign( rss64, 
7109                  binop(Iop_Shr64, 
7110                        binop(Iop_Shl64, mkexpr(tmp64), mkexpr(tmpSS)),
7111                        mkU8(32)) );
7112       }
7113       else
7114       if (sz == 4 && !left_shift) {
7115          assign( tmp64, binop(Iop_32HLto64, mkexpr(gsrc), mkexpr(esrc)) );
7116          assign( res64, binop(Iop_Shr64, mkexpr(tmp64), mkexpr(tmpSH)) );
7117          assign( rss64, binop(Iop_Shr64, mkexpr(tmp64), mkexpr(tmpSS)) );
7118       }
7119       else
7120       if (sz == 2 && left_shift) {
7121          assign( tmp64,
7122                  binop(Iop_32HLto64,
7123                        binop(Iop_16HLto32, mkexpr(esrc), mkexpr(gsrc)),
7124                        binop(Iop_16HLto32, mkexpr(gsrc), mkexpr(gsrc))
7125          ));
7126          /* result formed by shifting [esrc'gsrc'gsrc'gsrc] */
7127          assign( res64, 
7128                  binop(Iop_Shr64, 
7129                        binop(Iop_Shl64, mkexpr(tmp64), mkexpr(tmpSH)),
7130                        mkU8(48)) );
7131          /* subshift formed by shifting [esrc'0000'0000'0000] */
7132          assign( rss64, 
7133                  binop(Iop_Shr64, 
7134                        binop(Iop_Shl64, 
7135                              binop(Iop_Shl64, unop(Iop_16Uto64, mkexpr(esrc)),
7136                                               mkU8(48)),
7137                              mkexpr(tmpSS)),
7138                        mkU8(48)) );
7139       }
7140       else
7141       if (sz == 2 && !left_shift) {
7142          assign( tmp64,
7143                  binop(Iop_32HLto64,
7144                        binop(Iop_16HLto32, mkexpr(gsrc), mkexpr(gsrc)),
7145                        binop(Iop_16HLto32, mkexpr(gsrc), mkexpr(esrc))
7146          ));
7147          /* result formed by shifting [gsrc'gsrc'gsrc'esrc] */
7148          assign( res64, binop(Iop_Shr64, mkexpr(tmp64), mkexpr(tmpSH)) );
7149          /* subshift formed by shifting [0000'0000'0000'esrc] */
7150          assign( rss64, binop(Iop_Shr64, 
7151                               unop(Iop_16Uto64, mkexpr(esrc)), 
7152                               mkexpr(tmpSS)) );
7153       }
7154
7155    } else {
7156
7157       vassert(sz == 8);
7158       if (left_shift) {
7159          assign( res64, shiftL64_with_extras( esrc, gsrc, tmpSH ));
7160          assign( rss64, shiftL64_with_extras( esrc, gsrc, tmpSS ));
7161       } else {
7162          assign( res64, shiftR64_with_extras( gsrc, esrc, tmpSH ));
7163          assign( rss64, shiftR64_with_extras( gsrc, esrc, tmpSS ));
7164       }
7165
7166    }
7167
7168    resTy = newTemp(ty);
7169    rssTy = newTemp(ty);
7170    assign( resTy, narrowTo(ty, mkexpr(res64)) );
7171    assign( rssTy, narrowTo(ty, mkexpr(rss64)) );
7172
7173    /* Put result back and write the flags thunk. */
7174    setFlags_DEP1_DEP2_shift ( left_shift ? Iop_Shl64 : Iop_Sar64,
7175                               resTy, rssTy, ty, tmpSH );
7176
7177    if (epartIsReg(modrm)) {
7178       putIRegE(sz, pfx, modrm, mkexpr(resTy));
7179    } else {
7180       storeLE( mkexpr(addr), mkexpr(resTy) );
7181    }
7182
7183    if (amt_is_literal) delta++;
7184    return delta;
7185 }
7186
7187
7188 /* Handle BT/BTS/BTR/BTC Gv, Ev.  Apparently b-size is not
7189    required. */
7190
7191 typedef enum { BtOpNone, BtOpSet, BtOpReset, BtOpComp } BtOp;
7192
7193 static HChar* nameBtOp ( BtOp op )
7194 {
7195    switch (op) {
7196       case BtOpNone:  return "";
7197       case BtOpSet:   return "s";
7198       case BtOpReset: return "r";
7199       case BtOpComp:  return "c";
7200       default: vpanic("nameBtOp(amd64)");
7201    }
7202 }
7203
7204
7205 static
7206 ULong dis_bt_G_E ( VexAbiInfo* vbi,
7207                    Prefix pfx, Int sz, Long delta, BtOp op )
7208 {
7209    HChar  dis_buf[50];
7210    UChar  modrm;
7211    Int    len;
7212    IRTemp t_fetched, t_bitno0, t_bitno1, t_bitno2, t_addr0, 
7213      t_addr1, t_rsp, t_mask, t_new;
7214
7215    vassert(sz == 2 || sz == 4 || sz == 8);
7216
7217    t_fetched = t_bitno0 = t_bitno1 = t_bitno2 
7218              = t_addr0 = t_addr1 = t_rsp
7219              = t_mask = t_new = IRTemp_INVALID;
7220
7221    t_fetched = newTemp(Ity_I8);
7222    t_new     = newTemp(Ity_I8);
7223    t_bitno0  = newTemp(Ity_I64);
7224    t_bitno1  = newTemp(Ity_I64);
7225    t_bitno2  = newTemp(Ity_I8);
7226    t_addr1   = newTemp(Ity_I64);
7227    modrm     = getUChar(delta);
7228
7229    assign( t_bitno0, widenSto64(getIRegG(sz, pfx, modrm)) );
7230    
7231    if (epartIsReg(modrm)) {
7232       delta++;
7233       /* Get it onto the client's stack. */
7234       t_rsp = newTemp(Ity_I64);
7235       t_addr0 = newTemp(Ity_I64);
7236
7237       assign( t_rsp, binop(Iop_Sub64, getIReg64(R_RSP), mkU64(sz)) );
7238       putIReg64(R_RSP, mkexpr(t_rsp));
7239
7240       storeLE( mkexpr(t_rsp), getIRegE(sz, pfx, modrm) );
7241
7242       /* Make t_addr0 point at it. */
7243       assign( t_addr0, mkexpr(t_rsp) );
7244
7245       /* Mask out upper bits of the shift amount, since we're doing a
7246          reg. */
7247       assign( t_bitno1, binop(Iop_And64, 
7248                               mkexpr(t_bitno0), 
7249                               mkU64(sz == 8 ? 63 : sz == 4 ? 31 : 15)) );
7250
7251    } else {
7252       t_addr0 = disAMode ( &len, vbi, pfx, delta, dis_buf, 0 );
7253       delta += len;
7254       assign( t_bitno1, mkexpr(t_bitno0) );
7255    }
7256   
7257    /* At this point: t_addr0 is the address being operated on.  If it
7258       was a reg, we will have pushed it onto the client's stack.
7259       t_bitno1 is the bit number, suitably masked in the case of a
7260       reg.  */
7261   
7262    /* Now the main sequence. */
7263    assign( t_addr1, 
7264            binop(Iop_Add64, 
7265                  mkexpr(t_addr0), 
7266                  binop(Iop_Sar64, mkexpr(t_bitno1), mkU8(3))) );
7267
7268    /* t_addr1 now holds effective address */
7269
7270    assign( t_bitno2, 
7271            unop(Iop_64to8, 
7272                 binop(Iop_And64, mkexpr(t_bitno1), mkU64(7))) );
7273
7274    /* t_bitno2 contains offset of bit within byte */
7275
7276    if (op != BtOpNone) {
7277       t_mask = newTemp(Ity_I8);
7278       assign( t_mask, binop(Iop_Shl8, mkU8(1), mkexpr(t_bitno2)) );
7279    }
7280
7281    /* t_mask is now a suitable byte mask */
7282
7283    assign( t_fetched, loadLE(Ity_I8, mkexpr(t_addr1)) );
7284
7285    if (op != BtOpNone) {
7286       switch (op) {
7287          case BtOpSet:
7288             assign( t_new,
7289                     binop(Iop_Or8, mkexpr(t_fetched), mkexpr(t_mask)) );
7290             break;
7291          case BtOpComp:
7292             assign( t_new,
7293                     binop(Iop_Xor8, mkexpr(t_fetched), mkexpr(t_mask)) );
7294             break;
7295          case BtOpReset:
7296             assign( t_new,
7297                     binop(Iop_And8, mkexpr(t_fetched), 
7298                                     unop(Iop_Not8, mkexpr(t_mask))) );
7299             break;
7300          default: 
7301             vpanic("dis_bt_G_E(amd64)");
7302       }
7303       if ((pfx & PFX_LOCK) && !epartIsReg(modrm)) {
7304          casLE( mkexpr(t_addr1), mkexpr(t_fetched)/*expd*/,
7305                                  mkexpr(t_new)/*new*/,
7306                                  guest_RIP_curr_instr );
7307       } else {
7308          storeLE( mkexpr(t_addr1), mkexpr(t_new) );
7309       }
7310    }
7311   
7312    /* Side effect done; now get selected bit into Carry flag */
7313    /* Flags: C=selected bit, O,S,Z,A,P undefined, so are set to zero. */
7314    stmt( IRStmt_Put( OFFB_CC_OP,   mkU64(AMD64G_CC_OP_COPY) ));
7315    stmt( IRStmt_Put( OFFB_CC_DEP2, mkU64(0) ));
7316    stmt( IRStmt_Put( 
7317             OFFB_CC_DEP1,
7318             binop(Iop_And64,
7319                   binop(Iop_Shr64, 
7320                         unop(Iop_8Uto64, mkexpr(t_fetched)),
7321                         mkexpr(t_bitno2)),
7322                   mkU64(1)))
7323        );
7324    /* Set NDEP even though it isn't used.  This makes redundant-PUT
7325       elimination of previous stores to this field work better. */
7326    stmt( IRStmt_Put( OFFB_CC_NDEP, mkU64(0) ));
7327
7328    /* Move reg operand from stack back to reg */
7329    if (epartIsReg(modrm)) {
7330       /* t_rsp still points at it. */
7331       /* only write the reg if actually modifying it; doing otherwise
7332          zeroes the top half erroneously when doing btl due to
7333          standard zero-extend rule */
7334       if (op != BtOpNone)
7335          putIRegE(sz, pfx, modrm, loadLE(szToITy(sz), mkexpr(t_rsp)) );
7336       putIReg64(R_RSP, binop(Iop_Add64, mkexpr(t_rsp), mkU64(sz)) );
7337    }
7338
7339    DIP("bt%s%c %s, %s\n",
7340        nameBtOp(op), nameISize(sz), nameIRegG(sz, pfx, modrm), 
7341        ( epartIsReg(modrm) ? nameIRegE(sz, pfx, modrm) : dis_buf ) );
7342  
7343    return delta;
7344 }
7345
7346
7347
7348 /* Handle BSF/BSR.  Only v-size seems necessary. */
7349 static
7350 ULong dis_bs_E_G ( VexAbiInfo* vbi,
7351                    Prefix pfx, Int sz, Long delta, Bool fwds )
7352 {
7353    Bool   isReg;
7354    UChar  modrm;
7355    HChar  dis_buf[50];
7356
7357    IRType ty    = szToITy(sz);
7358    IRTemp src   = newTemp(ty);
7359    IRTemp dst   = newTemp(ty);
7360    IRTemp src64 = newTemp(Ity_I64);
7361    IRTemp dst64 = newTemp(Ity_I64);
7362    IRTemp src8  = newTemp(Ity_I8);
7363
7364    vassert(sz == 8 || sz == 4 || sz == 2);
7365
7366    modrm = getUChar(delta);
7367    isReg = epartIsReg(modrm);
7368    if (isReg) {
7369       delta++;
7370       assign( src, getIRegE(sz, pfx, modrm) );
7371    } else {
7372       Int    len;
7373       IRTemp addr = disAMode( &len, vbi, pfx, delta, dis_buf, 0 );
7374       delta += len;
7375       assign( src, loadLE(ty, mkexpr(addr)) );
7376    }
7377
7378    DIP("bs%c%c %s, %s\n",
7379        fwds ? 'f' : 'r', nameISize(sz), 
7380        ( isReg ? nameIRegE(sz, pfx, modrm) : dis_buf ), 
7381        nameIRegG(sz, pfx, modrm));
7382
7383    /* First, widen src to 64 bits if it is not already. */
7384    assign( src64, widenUto64(mkexpr(src)) );
7385
7386    /* Generate an 8-bit expression which is zero iff the 
7387       original is zero, and nonzero otherwise */
7388    assign( src8,
7389            unop(Iop_1Uto8, 
7390                 binop(Iop_CmpNE64,
7391                       mkexpr(src64), mkU64(0))) );
7392
7393    /* Flags: Z is 1 iff source value is zero.  All others 
7394       are undefined -- we force them to zero. */
7395    stmt( IRStmt_Put( OFFB_CC_OP,   mkU64(AMD64G_CC_OP_COPY) ));
7396    stmt( IRStmt_Put( OFFB_CC_DEP2, mkU64(0) ));
7397    stmt( IRStmt_Put( 
7398             OFFB_CC_DEP1,
7399             IRExpr_Mux0X( mkexpr(src8),
7400                           /* src==0 */
7401                           mkU64(AMD64G_CC_MASK_Z),
7402                           /* src!=0 */
7403                           mkU64(0)
7404                         )
7405        ));
7406    /* Set NDEP even though it isn't used.  This makes redundant-PUT
7407       elimination of previous stores to this field work better. */
7408    stmt( IRStmt_Put( OFFB_CC_NDEP, mkU64(0) ));
7409
7410    /* Result: iff source value is zero, we can't use
7411       Iop_Clz64/Iop_Ctz64 as they have no defined result in that case.
7412       But anyway, amd64 semantics say the result is undefined in
7413       such situations.  Hence handle the zero case specially. */
7414
7415    /* Bleh.  What we compute:
7416
7417           bsf64:  if src == 0 then {dst is unchanged} 
7418                               else Ctz64(src)
7419
7420           bsr64:  if src == 0 then {dst is unchanged} 
7421                               else 63 - Clz64(src)
7422
7423           bsf32:  if src == 0 then {dst is unchanged} 
7424                               else Ctz64(32Uto64(src))
7425
7426           bsr32:  if src == 0 then {dst is unchanged}
7427                               else 63 - Clz64(32Uto64(src))
7428
7429           bsf16:  if src == 0 then {dst is unchanged} 
7430                               else Ctz64(32Uto64(16Uto32(src)))
7431
7432           bsr16:  if src == 0 then {dst is unchanged} 
7433                               else 63 - Clz64(32Uto64(16Uto32(src)))
7434    */
7435
7436    /* The main computation, guarding against zero. */
7437    assign( dst64,
7438            IRExpr_Mux0X( 
7439               mkexpr(src8),
7440               /* src == 0 -- leave dst unchanged */
7441               widenUto64( getIRegG( sz, pfx, modrm ) ),
7442               /* src != 0 */
7443               fwds ? unop(Iop_Ctz64, mkexpr(src64))
7444                    : binop(Iop_Sub64, 
7445                            mkU64(63), 
7446                            unop(Iop_Clz64, mkexpr(src64)))
7447            )
7448          );
7449
7450    if (sz == 2)
7451       assign( dst, unop(Iop_64to16, mkexpr(dst64)) );
7452    else
7453    if (sz == 4)
7454       assign( dst, unop(Iop_64to32, mkexpr(dst64)) );
7455    else
7456       assign( dst, mkexpr(dst64) );
7457
7458    /* dump result back */
7459    putIRegG( sz, pfx, modrm, mkexpr(dst) );
7460
7461    return delta;
7462 }
7463
7464
7465 /* swap rAX with the reg specified by reg and REX.B */
7466 static 
7467 void codegen_xchg_rAX_Reg ( Prefix pfx, Int sz, UInt regLo3 )
7468 {
7469    IRType ty = szToITy(sz);
7470    IRTemp t1 = newTemp(ty);
7471    IRTemp t2 = newTemp(ty);
7472    vassert(sz == 4 || sz == 8);
7473    vassert(regLo3 < 8);
7474    if (sz == 8) {
7475       assign( t1, getIReg64(R_RAX) );
7476       assign( t2, getIRegRexB(8, pfx, regLo3) );
7477       putIReg64( R_RAX, mkexpr(t2) );
7478       putIRegRexB(8, pfx, regLo3, mkexpr(t1) );
7479    } else {
7480       assign( t1, getIReg32(R_RAX) );
7481       assign( t2, getIRegRexB(4, pfx, regLo3) );
7482       putIReg32( R_RAX, mkexpr(t2) );
7483       putIRegRexB(4, pfx, regLo3, mkexpr(t1) );
7484    }
7485    DIP("xchg%c %s, %s\n", 
7486        nameISize(sz), nameIRegRAX(sz), 
7487                       nameIRegRexB(sz,pfx, regLo3));
7488 }
7489
7490
7491 static 
7492 void codegen_SAHF ( void )
7493 {
7494    /* Set the flags to:
7495       (amd64g_calculate_flags_all() & AMD64G_CC_MASK_O) 
7496                                     -- retain the old O flag
7497       | (%AH & (AMD64G_CC_MASK_S|AMD64G_CC_MASK_Z|AMD64G_CC_MASK_A
7498                 |AMD64G_CC_MASK_P|AMD64G_CC_MASK_C)
7499    */
7500    ULong  mask_SZACP = AMD64G_CC_MASK_S|AMD64G_CC_MASK_Z|AMD64G_CC_MASK_A
7501                        |AMD64G_CC_MASK_C|AMD64G_CC_MASK_P;
7502    IRTemp oldflags   = newTemp(Ity_I64);
7503    assign( oldflags, mk_amd64g_calculate_rflags_all() );
7504    stmt( IRStmt_Put( OFFB_CC_OP,   mkU64(AMD64G_CC_OP_COPY) ));
7505    stmt( IRStmt_Put( OFFB_CC_NDEP, mkU64(0) ));
7506    stmt( IRStmt_Put( OFFB_CC_DEP2, mkU64(0) ));
7507    stmt( IRStmt_Put( OFFB_CC_DEP1,
7508          binop(Iop_Or64,
7509                binop(Iop_And64, mkexpr(oldflags), mkU64(AMD64G_CC_MASK_O)),
7510                binop(Iop_And64, 
7511                      binop(Iop_Shr64, getIReg64(R_RAX), mkU8(8)),
7512                      mkU64(mask_SZACP))
7513               )
7514    ));
7515 }
7516
7517
7518 static 
7519 void codegen_LAHF ( void  )
7520 {
7521    /* AH <- EFLAGS(SF:ZF:0:AF:0:PF:1:CF) */
7522    IRExpr* rax_with_hole;
7523    IRExpr* new_byte;
7524    IRExpr* new_rax;
7525    ULong   mask_SZACP = AMD64G_CC_MASK_S|AMD64G_CC_MASK_Z|AMD64G_CC_MASK_A
7526                         |AMD64G_CC_MASK_C|AMD64G_CC_MASK_P;
7527
7528    IRTemp  flags = newTemp(Ity_I64);
7529    assign( flags, mk_amd64g_calculate_rflags_all() );
7530
7531    rax_with_hole 
7532       = binop(Iop_And64, getIReg64(R_RAX), mkU64(~0xFF00ULL));
7533    new_byte 
7534       = binop(Iop_Or64, binop(Iop_And64, mkexpr(flags), mkU64(mask_SZACP)),
7535                         mkU64(1<<1));
7536    new_rax 
7537       = binop(Iop_Or64, rax_with_hole,
7538                         binop(Iop_Shl64, new_byte, mkU8(8)));
7539    putIReg64(R_RAX, new_rax);
7540 }
7541
7542
7543 static
7544 ULong dis_cmpxchg_G_E ( /*OUT*/Bool* ok,
7545                         VexAbiInfo*  vbi,
7546                         Prefix       pfx,
7547                         Int          size, 
7548                         Long         delta0 )
7549 {
7550    HChar dis_buf[50];
7551    Int   len;
7552
7553    IRType ty    = szToITy(size);
7554    IRTemp acc   = newTemp(ty);
7555    IRTemp src   = newTemp(ty);
7556    IRTemp dest  = newTemp(ty);
7557    IRTemp dest2 = newTemp(ty);
7558    IRTemp acc2  = newTemp(ty);
7559    IRTemp cond8 = newTemp(Ity_I8);
7560    IRTemp addr  = IRTemp_INVALID;
7561    UChar  rm    = getUChar(delta0);
7562
7563    /* There are 3 cases to consider:
7564
7565       reg-reg: ignore any lock prefix, generate sequence based
7566                on Mux0X
7567
7568       reg-mem, not locked: ignore any lock prefix, generate sequence
7569                            based on Mux0X
7570
7571       reg-mem, locked: use IRCAS
7572    */
7573
7574    if (epartIsReg(rm)) {
7575       /* case 1 */
7576       *ok = False;
7577       return delta0;
7578       /* awaiting test case */
7579       assign( dest, getIRegE(size, pfx, rm) );
7580       delta0++;
7581       assign( src, getIRegG(size, pfx, rm) );
7582       assign( acc, getIRegRAX(size) );
7583       setFlags_DEP1_DEP2(Iop_Sub8, acc, dest, ty);
7584       assign( cond8, unop(Iop_1Uto8, mk_amd64g_calculate_condition(AMD64CondZ)) );
7585       assign( dest2, IRExpr_Mux0X(mkexpr(cond8), mkexpr(dest), mkexpr(src)) );
7586       assign( acc2,  IRExpr_Mux0X(mkexpr(cond8), mkexpr(dest), mkexpr(acc)) );
7587       putIRegRAX(size, mkexpr(acc2));
7588       putIRegE(size, pfx, rm, mkexpr(dest2));
7589       DIP("cmpxchg%c %s,%s\n", nameISize(size),
7590                                nameIRegG(size,pfx,rm),
7591                                nameIRegE(size,pfx,rm) );
7592    } 
7593    else if (!epartIsReg(rm) && !(pfx & PFX_LOCK)) {
7594       /* case 2 */
7595       addr = disAMode ( &len, vbi, pfx, delta0, dis_buf, 0 );
7596       assign( dest, loadLE(ty, mkexpr(addr)) );
7597       delta0 += len;
7598       assign( src, getIRegG(size, pfx, rm) );
7599       assign( acc, getIRegRAX(size) );
7600       setFlags_DEP1_DEP2(Iop_Sub8, acc, dest, ty);
7601       assign( cond8, unop(Iop_1Uto8, mk_amd64g_calculate_condition(AMD64CondZ)) );
7602       assign( dest2, IRExpr_Mux0X(mkexpr(cond8), mkexpr(dest), mkexpr(src)) );
7603       assign( acc2,  IRExpr_Mux0X(mkexpr(cond8), mkexpr(dest), mkexpr(acc)) );
7604       putIRegRAX(size, mkexpr(acc2));
7605       storeLE( mkexpr(addr), mkexpr(dest2) );
7606       DIP("cmpxchg%c %s,%s\n", nameISize(size), 
7607                                nameIRegG(size,pfx,rm), dis_buf);
7608    }
7609    else if (!epartIsReg(rm) && (pfx & PFX_LOCK)) {
7610       /* case 3 */
7611       /* src is new value.  acc is expected value.  dest is old value.
7612          Compute success from the output of the IRCAS, and steer the
7613          new value for RAX accordingly: in case of success, RAX is
7614          unchanged. */
7615       addr = disAMode ( &len, vbi, pfx, delta0, dis_buf, 0 );
7616       delta0 += len;
7617       assign( src, getIRegG(size, pfx, rm) );
7618       assign( acc, getIRegRAX(size) );
7619       stmt( IRStmt_CAS( 
7620          mkIRCAS( IRTemp_INVALID, dest, Iend_LE, mkexpr(addr), 
7621                   NULL, mkexpr(acc), NULL, mkexpr(src) )
7622       ));
7623       setFlags_DEP1_DEP2(Iop_Sub8, acc, dest, ty);
7624       assign( cond8, unop(Iop_1Uto8, mk_amd64g_calculate_condition(AMD64CondZ)) );
7625       assign( acc2,  IRExpr_Mux0X(mkexpr(cond8), mkexpr(dest), mkexpr(acc)) );
7626       putIRegRAX(size, mkexpr(acc2));
7627       DIP("cmpxchg%c %s,%s\n", nameISize(size), 
7628                                nameIRegG(size,pfx,rm), dis_buf);
7629    }
7630    else vassert(0);
7631
7632    *ok = True;
7633    return delta0;
7634 }
7635
7636
7637 /* Handle conditional move instructions of the form
7638       cmovcc E(reg-or-mem), G(reg)
7639
7640    E(src) is reg-or-mem
7641    G(dst) is reg.
7642
7643    If E is reg, -->    GET %E, tmps
7644                        GET %G, tmpd
7645                        CMOVcc tmps, tmpd
7646                        PUT tmpd, %G
7647  
7648    If E is mem  -->    (getAddr E) -> tmpa
7649                        LD (tmpa), tmps
7650                        GET %G, tmpd
7651                        CMOVcc tmps, tmpd
7652                        PUT tmpd, %G
7653 */
7654 static
7655 ULong dis_cmov_E_G ( VexAbiInfo* vbi,
7656                      Prefix        pfx,
7657                      Int           sz, 
7658                      AMD64Condcode cond,
7659                      Long          delta0 )
7660 {
7661    UChar rm  = getUChar(delta0);
7662    HChar dis_buf[50];
7663    Int   len;
7664
7665    IRType ty   = szToITy(sz);
7666    IRTemp tmps = newTemp(ty);
7667    IRTemp tmpd = newTemp(ty);
7668
7669    if (epartIsReg(rm)) {
7670       assign( tmps, getIRegE(sz, pfx, rm) );
7671       assign( tmpd, getIRegG(sz, pfx, rm) );
7672
7673       putIRegG( sz, pfx, rm,
7674                 IRExpr_Mux0X( unop(Iop_1Uto8,
7675                                    mk_amd64g_calculate_condition(cond)),
7676                               mkexpr(tmpd),
7677                               mkexpr(tmps) )
7678               );
7679       DIP("cmov%s %s,%s\n", name_AMD64Condcode(cond),
7680                             nameIRegE(sz,pfx,rm),
7681                             nameIRegG(sz,pfx,rm));
7682       return 1+delta0;
7683    }
7684
7685    /* E refers to memory */    
7686    {
7687       IRTemp addr = disAMode ( &len, vbi, pfx, delta0, dis_buf, 0 );
7688       assign( tmps, loadLE(ty, mkexpr(addr)) );
7689       assign( tmpd, getIRegG(sz, pfx, rm) );
7690
7691       putIRegG( sz, pfx, rm,
7692                 IRExpr_Mux0X( unop(Iop_1Uto8,
7693                                    mk_amd64g_calculate_condition(cond)),
7694                               mkexpr(tmpd),
7695                               mkexpr(tmps) )
7696               );
7697
7698       DIP("cmov%s %s,%s\n", name_AMD64Condcode(cond),
7699                             dis_buf,
7700                             nameIRegG(sz,pfx,rm));
7701       return len+delta0;
7702    }
7703 }
7704
7705
7706 static
7707 ULong dis_xadd_G_E ( /*OUT*/Bool* decode_ok,
7708                      VexAbiInfo* vbi,
7709                      Prefix pfx, Int sz, Long delta0 )
7710 {
7711    Int   len;
7712    UChar rm = getUChar(delta0);
7713    HChar dis_buf[50];
7714
7715    IRType ty    = szToITy(sz);
7716    IRTemp tmpd  = newTemp(ty);
7717    IRTemp tmpt0 = newTemp(ty);
7718    IRTemp tmpt1 = newTemp(ty);
7719
7720    /* There are 3 cases to consider:
7721
7722       reg-reg: currently unhandled
7723
7724       reg-mem, not locked: ignore any lock prefix, generate 'naive'
7725                            (non-atomic) sequence
7726
7727       reg-mem, locked: use IRCAS
7728    */
7729
7730    if (epartIsReg(rm)) {
7731       /* case 1 */
7732       *decode_ok = False;
7733       return delta0;
7734       /* Currently we don't handle xadd_G_E with register operand. */
7735    }
7736    else if (!epartIsReg(rm) && !(pfx & PFX_LOCK)) {
7737       /* case 2 */
7738       IRTemp addr = disAMode ( &len, vbi, pfx, delta0, dis_buf, 0 );
7739       assign( tmpd,  loadLE(ty, mkexpr(addr)) );
7740       assign( tmpt0, getIRegG(sz, pfx, rm) );
7741       assign( tmpt1, binop(mkSizedOp(ty,Iop_Add8),
7742                            mkexpr(tmpd), mkexpr(tmpt0)) );
7743       setFlags_DEP1_DEP2( Iop_Add8, tmpd, tmpt0, ty );
7744       storeLE( mkexpr(addr), mkexpr(tmpt1) );
7745       putIRegG(sz, pfx, rm, mkexpr(tmpd));
7746       DIP("xadd%c %s, %s\n",
7747           nameISize(sz), nameIRegG(sz,pfx,rm), dis_buf);
7748       *decode_ok = True;
7749       return len+delta0;
7750    }
7751    else if (!epartIsReg(rm) && (pfx & PFX_LOCK)) {
7752       /* case 3 */
7753       IRTemp addr = disAMode ( &len, vbi, pfx, delta0, dis_buf, 0 );
7754       assign( tmpd,  loadLE(ty, mkexpr(addr)) );
7755       assign( tmpt0, getIRegG(sz, pfx, rm) );
7756       assign( tmpt1, binop(mkSizedOp(ty,Iop_Add8), 
7757                            mkexpr(tmpd), mkexpr(tmpt0)) );
7758       casLE( mkexpr(addr), mkexpr(tmpd)/*expVal*/,
7759                            mkexpr(tmpt1)/*newVal*/, guest_RIP_curr_instr );
7760       setFlags_DEP1_DEP2( Iop_Add8, tmpd, tmpt0, ty );
7761       putIRegG(sz, pfx, rm, mkexpr(tmpd));
7762       DIP("xadd%c %s, %s\n",
7763           nameISize(sz), nameIRegG(sz,pfx,rm), dis_buf);
7764       *decode_ok = True;
7765       return len+delta0;
7766    }
7767    /*UNREACHED*/
7768    vassert(0);
7769 }
7770
7771 //.. /* Move 16 bits from Ew (ireg or mem) to G (a segment register). */
7772 //.. 
7773 //.. static
7774 //.. UInt dis_mov_Ew_Sw ( UChar sorb, Long delta0 )
7775 //.. {
7776 //..    Int    len;
7777 //..    IRTemp addr;
7778 //..    UChar  rm  = getUChar(delta0);
7779 //..    HChar  dis_buf[50];
7780 //.. 
7781 //..    if (epartIsReg(rm)) {
7782 //..       putSReg( gregOfRM(rm), getIReg(2, eregOfRM(rm)) );
7783 //..       DIP("movw %s,%s\n", nameIReg(2,eregOfRM(rm)), nameSReg(gregOfRM(rm)));
7784 //..       return 1+delta0;
7785 //..    } else {
7786 //..       addr = disAMode ( &len, sorb, delta0, dis_buf );
7787 //..       putSReg( gregOfRM(rm), loadLE(Ity_I16, mkexpr(addr)) );
7788 //..       DIP("movw %s,%s\n", dis_buf, nameSReg(gregOfRM(rm)));
7789 //..       return len+delta0;
7790 //..    }
7791 //.. }
7792 //.. 
7793 //.. /* Move 16 bits from G (a segment register) to Ew (ireg or mem).  If
7794 //..    dst is ireg and sz==4, zero out top half of it.  */
7795 //.. 
7796 //.. static
7797 //.. UInt dis_mov_Sw_Ew ( UChar sorb,
7798 //..                      Int   sz,
7799 //..                      UInt  delta0 )
7800 //.. {
7801 //..    Int    len;
7802 //..    IRTemp addr;
7803 //..    UChar  rm  = getUChar(delta0);
7804 //..    HChar  dis_buf[50];
7805 //.. 
7806 //..    vassert(sz == 2 || sz == 4);
7807 //.. 
7808 //..    if (epartIsReg(rm)) {
7809 //..       if (sz == 4)
7810 //..          putIReg(4, eregOfRM(rm), unop(Iop_16Uto32, getSReg(gregOfRM(rm))));
7811 //..       else
7812 //..          putIReg(2, eregOfRM(rm), getSReg(gregOfRM(rm)));
7813 //.. 
7814 //..       DIP("mov %s,%s\n", nameSReg(gregOfRM(rm)), nameIReg(sz,eregOfRM(rm)));
7815 //..       return 1+delta0;
7816 //..    } else {
7817 //..       addr = disAMode ( &len, sorb, delta0, dis_buf );
7818 //..       storeLE( mkexpr(addr), getSReg(gregOfRM(rm)) );
7819 //..       DIP("mov %s,%s\n", nameSReg(gregOfRM(rm)), dis_buf);
7820 //..       return len+delta0;
7821 //..    }
7822 //.. }
7823 //.. 
7824 //.. 
7825 //.. static 
7826 //.. void dis_push_segreg ( UInt sreg, Int sz )
7827 //.. {
7828 //..     IRTemp t1 = newTemp(Ity_I16);
7829 //..     IRTemp ta = newTemp(Ity_I32);
7830 //..     vassert(sz == 2 || sz == 4);
7831 //.. 
7832 //..     assign( t1, getSReg(sreg) );
7833 //..     assign( ta, binop(Iop_Sub32, getIReg(4, R_ESP), mkU32(sz)) );
7834 //..     putIReg(4, R_ESP, mkexpr(ta));
7835 //..     storeLE( mkexpr(ta), mkexpr(t1) );
7836 //.. 
7837 //..     DIP("pushw %s\n", nameSReg(sreg));
7838 //.. }
7839 //.. 
7840 //.. static
7841 //.. void dis_pop_segreg ( UInt sreg, Int sz )
7842 //.. {
7843 //..     IRTemp t1 = newTemp(Ity_I16);
7844 //..     IRTemp ta = newTemp(Ity_I32);
7845 //..     vassert(sz == 2 || sz == 4);
7846 //.. 
7847 //..     assign( ta, getIReg(4, R_ESP) );
7848 //..     assign( t1, loadLE(Ity_I16, mkexpr(ta)) );
7849 //.. 
7850 //..     putIReg(4, R_ESP, binop(Iop_Add32, mkexpr(ta), mkU32(sz)) );
7851 //..     putSReg( sreg, mkexpr(t1) );
7852 //..     DIP("pop %s\n", nameSReg(sreg));
7853 //.. }
7854
7855 static
7856 void dis_ret ( VexAbiInfo* vbi, ULong d64 )
7857 {
7858    IRTemp t1 = newTemp(Ity_I64); 
7859    IRTemp t2 = newTemp(Ity_I64);
7860    IRTemp t3 = newTemp(Ity_I64);
7861    assign(t1, getIReg64(R_RSP));
7862    assign(t2, loadLE(Ity_I64,mkexpr(t1)));
7863    assign(t3, binop(Iop_Add64, mkexpr(t1), mkU64(8+d64)));
7864    putIReg64(R_RSP, mkexpr(t3));
7865    make_redzone_AbiHint(vbi, t3, t2/*nia*/, "ret");
7866    jmp_treg(Ijk_Ret,t2);
7867 }
7868
7869
7870 /*------------------------------------------------------------*/
7871 /*--- SSE/SSE2/SSE3 helpers                                ---*/
7872 /*------------------------------------------------------------*/
7873
7874 /* Worker function; do not call directly. 
7875    Handles full width G = G `op` E   and   G = (not G) `op` E.
7876 */
7877
7878 static ULong dis_SSE_E_to_G_all_wrk ( 
7879                 VexAbiInfo* vbi,
7880                 Prefix pfx, Long delta, 
7881                 HChar* opname, IROp op,
7882                 Bool   invertG
7883              )
7884 {
7885    HChar   dis_buf[50];
7886    Int     alen;
7887    IRTemp  addr;
7888    UChar   rm = getUChar(delta);
7889    IRExpr* gpart
7890       = invertG ? unop(Iop_NotV128, getXMMReg(gregOfRexRM(pfx,rm)))
7891                 : getXMMReg(gregOfRexRM(pfx,rm));
7892    if (epartIsReg(rm)) {
7893       putXMMReg( gregOfRexRM(pfx,rm), 
7894                  binop(op, gpart,
7895                            getXMMReg(eregOfRexRM(pfx,rm))) );
7896       DIP("%s %s,%s\n", opname,
7897                         nameXMMReg(eregOfRexRM(pfx,rm)),
7898                         nameXMMReg(gregOfRexRM(pfx,rm)) );
7899       return delta+1;
7900    } else {
7901       addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
7902       putXMMReg( gregOfRexRM(pfx,rm), 
7903                  binop(op, gpart,
7904                            loadLE(Ity_V128, mkexpr(addr))) );
7905       DIP("%s %s,%s\n", opname,
7906                         dis_buf,
7907                         nameXMMReg(gregOfRexRM(pfx,rm)) );
7908       return delta+alen;
7909    }
7910 }
7911
7912
7913 /* All lanes SSE binary operation, G = G `op` E. */
7914
7915 static
7916 ULong dis_SSE_E_to_G_all ( VexAbiInfo* vbi,
7917                            Prefix pfx, Long delta, 
7918                            HChar* opname, IROp op )
7919 {
7920    return dis_SSE_E_to_G_all_wrk( vbi, pfx, delta, opname, op, False );
7921 }
7922
7923 /* All lanes SSE binary operation, G = (not G) `op` E. */
7924
7925 static
7926 ULong dis_SSE_E_to_G_all_invG ( VexAbiInfo* vbi,
7927                                 Prefix pfx, Long delta, 
7928                                 HChar* opname, IROp op )
7929 {
7930    return dis_SSE_E_to_G_all_wrk( vbi, pfx, delta, opname, op, True );
7931 }
7932
7933
7934 /* Lowest 32-bit lane only SSE binary operation, G = G `op` E. */
7935
7936 static ULong dis_SSE_E_to_G_lo32 ( VexAbiInfo* vbi,
7937                                    Prefix pfx, Long delta, 
7938                                    HChar* opname, IROp op )
7939 {
7940    HChar   dis_buf[50];
7941    Int     alen;
7942    IRTemp  addr;
7943    UChar   rm = getUChar(delta);
7944    IRExpr* gpart = getXMMReg(gregOfRexRM(pfx,rm));
7945    if (epartIsReg(rm)) {
7946       putXMMReg( gregOfRexRM(pfx,rm), 
7947                  binop(op, gpart,
7948                            getXMMReg(eregOfRexRM(pfx,rm))) );
7949       DIP("%s %s,%s\n", opname,
7950                         nameXMMReg(eregOfRexRM(pfx,rm)),
7951                         nameXMMReg(gregOfRexRM(pfx,rm)) );
7952       return delta+1;
7953    } else {
7954       /* We can only do a 32-bit memory read, so the upper 3/4 of the
7955          E operand needs to be made simply of zeroes. */
7956       IRTemp epart = newTemp(Ity_V128);
7957       addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
7958       assign( epart, unop( Iop_32UtoV128,
7959                            loadLE(Ity_I32, mkexpr(addr))) );
7960       putXMMReg( gregOfRexRM(pfx,rm), 
7961                  binop(op, gpart, mkexpr(epart)) );
7962       DIP("%s %s,%s\n", opname,
7963                         dis_buf,
7964                         nameXMMReg(gregOfRexRM(pfx,rm)) );
7965       return delta+alen;
7966    }
7967 }
7968
7969
7970 /* Lower 64-bit lane only SSE binary operation, G = G `op` E. */
7971
7972 static ULong dis_SSE_E_to_G_lo64 ( VexAbiInfo* vbi,
7973                                    Prefix pfx, Long delta, 
7974                                    HChar* opname, IROp op )
7975 {
7976    HChar   dis_buf[50];
7977    Int     alen;
7978    IRTemp  addr;
7979    UChar   rm = getUChar(delta);
7980    IRExpr* gpart = getXMMReg(gregOfRexRM(pfx,rm));
7981    if (epartIsReg(rm)) {
7982       putXMMReg( gregOfRexRM(pfx,rm), 
7983                  binop(op, gpart,
7984                            getXMMReg(eregOfRexRM(pfx,rm))) );
7985       DIP("%s %s,%s\n", opname,
7986                         nameXMMReg(eregOfRexRM(pfx,rm)),
7987                         nameXMMReg(gregOfRexRM(pfx,rm)) );
7988       return delta+1;
7989    } else {
7990       /* We can only do a 64-bit memory read, so the upper half of the
7991          E operand needs to be made simply of zeroes. */
7992       IRTemp epart = newTemp(Ity_V128);
7993       addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
7994       assign( epart, unop( Iop_64UtoV128,
7995                            loadLE(Ity_I64, mkexpr(addr))) );
7996       putXMMReg( gregOfRexRM(pfx,rm), 
7997                  binop(op, gpart, mkexpr(epart)) );
7998       DIP("%s %s,%s\n", opname,
7999                         dis_buf,
8000                         nameXMMReg(gregOfRexRM(pfx,rm)) );
8001       return delta+alen;
8002    }
8003 }
8004
8005
8006 /* All lanes unary SSE operation, G = op(E). */
8007
8008 static ULong dis_SSE_E_to_G_unary_all ( 
8009                 VexAbiInfo* vbi,
8010                 Prefix pfx, Long delta, 
8011                 HChar* opname, IROp op
8012              )
8013 {
8014    HChar   dis_buf[50];
8015    Int     alen;
8016    IRTemp  addr;
8017    UChar   rm = getUChar(delta);
8018    if (epartIsReg(rm)) {
8019       putXMMReg( gregOfRexRM(pfx,rm), 
8020                  unop(op, getXMMReg(eregOfRexRM(pfx,rm))) );
8021       DIP("%s %s,%s\n", opname,
8022                         nameXMMReg(eregOfRexRM(pfx,rm)),
8023                         nameXMMReg(gregOfRexRM(pfx,rm)) );
8024       return delta+1;
8025    } else {
8026       addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
8027       putXMMReg( gregOfRexRM(pfx,rm), 
8028                  unop(op, loadLE(Ity_V128, mkexpr(addr))) );
8029       DIP("%s %s,%s\n", opname,
8030                         dis_buf,
8031                         nameXMMReg(gregOfRexRM(pfx,rm)) );
8032       return delta+alen;
8033    }
8034 }
8035
8036
8037 /* Lowest 32-bit lane only unary SSE operation, G = op(E). */
8038
8039 static ULong dis_SSE_E_to_G_unary_lo32 ( 
8040                 VexAbiInfo* vbi,
8041                 Prefix pfx, Long delta, 
8042                 HChar* opname, IROp op
8043              )
8044 {
8045    /* First we need to get the old G value and patch the low 32 bits
8046       of the E operand into it.  Then apply op and write back to G. */
8047    HChar   dis_buf[50];
8048    Int     alen;
8049    IRTemp  addr;
8050    UChar   rm = getUChar(delta);
8051    IRTemp  oldG0 = newTemp(Ity_V128);
8052    IRTemp  oldG1 = newTemp(Ity_V128);
8053
8054    assign( oldG0, getXMMReg(gregOfRexRM(pfx,rm)) );
8055
8056    if (epartIsReg(rm)) {
8057       assign( oldG1, 
8058               binop( Iop_SetV128lo32,
8059                      mkexpr(oldG0),
8060                      getXMMRegLane32(eregOfRexRM(pfx,rm), 0)) );
8061       putXMMReg( gregOfRexRM(pfx,rm), unop(op, mkexpr(oldG1)) );
8062       DIP("%s %s,%s\n", opname,
8063                         nameXMMReg(eregOfRexRM(pfx,rm)),
8064                         nameXMMReg(gregOfRexRM(pfx,rm)) );
8065       return delta+1;
8066    } else {
8067       addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
8068       assign( oldG1, 
8069               binop( Iop_SetV128lo32,
8070                      mkexpr(oldG0),
8071                      loadLE(Ity_I32, mkexpr(addr)) ));
8072       putXMMReg( gregOfRexRM(pfx,rm), unop(op, mkexpr(oldG1)) );
8073       DIP("%s %s,%s\n", opname,
8074                         dis_buf,
8075                         nameXMMReg(gregOfRexRM(pfx,rm)) );
8076       return delta+alen;
8077    }
8078 }
8079
8080
8081 /* Lowest 64-bit lane only unary SSE operation, G = op(E). */
8082
8083 static ULong dis_SSE_E_to_G_unary_lo64 ( 
8084                 VexAbiInfo* vbi,
8085                 Prefix pfx, Long delta, 
8086                 HChar* opname, IROp op
8087              )
8088 {
8089    /* First we need to get the old G value and patch the low 64 bits
8090       of the E operand into it.  Then apply op and write back to G. */
8091    HChar   dis_buf[50];
8092    Int     alen;
8093    IRTemp  addr;
8094    UChar   rm = getUChar(delta);
8095    IRTemp  oldG0 = newTemp(Ity_V128);
8096    IRTemp  oldG1 = newTemp(Ity_V128);
8097
8098    assign( oldG0, getXMMReg(gregOfRexRM(pfx,rm)) );
8099
8100    if (epartIsReg(rm)) {
8101       assign( oldG1, 
8102               binop( Iop_SetV128lo64,
8103                      mkexpr(oldG0),
8104                      getXMMRegLane64(eregOfRexRM(pfx,rm), 0)) );
8105       putXMMReg( gregOfRexRM(pfx,rm), unop(op, mkexpr(oldG1)) );
8106       DIP("%s %s,%s\n", opname,
8107                         nameXMMReg(eregOfRexRM(pfx,rm)),
8108                         nameXMMReg(gregOfRexRM(pfx,rm)) );
8109       return delta+1;
8110    } else {
8111       addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
8112       assign( oldG1, 
8113               binop( Iop_SetV128lo64,
8114                      mkexpr(oldG0),
8115                      loadLE(Ity_I64, mkexpr(addr)) ));
8116       putXMMReg( gregOfRexRM(pfx,rm), unop(op, mkexpr(oldG1)) );
8117       DIP("%s %s,%s\n", opname,
8118                         dis_buf,
8119                         nameXMMReg(gregOfRexRM(pfx,rm)) );
8120       return delta+alen;
8121    }
8122 }
8123
8124
8125 /* SSE integer binary operation:
8126       G = G `op` E   (eLeft == False)
8127       G = E `op` G   (eLeft == True)
8128 */
8129 static ULong dis_SSEint_E_to_G( 
8130                 VexAbiInfo* vbi,
8131                 Prefix pfx, Long delta, 
8132                 HChar* opname, IROp op,
8133                 Bool   eLeft
8134              )
8135 {
8136    HChar   dis_buf[50];
8137    Int     alen;
8138    IRTemp  addr;
8139    UChar   rm = getUChar(delta);
8140    IRExpr* gpart = getXMMReg(gregOfRexRM(pfx,rm));
8141    IRExpr* epart = NULL;
8142    if (epartIsReg(rm)) {
8143       epart = getXMMReg(eregOfRexRM(pfx,rm));
8144       DIP("%s %s,%s\n", opname,
8145                         nameXMMReg(eregOfRexRM(pfx,rm)),
8146                         nameXMMReg(gregOfRexRM(pfx,rm)) );
8147       delta += 1;
8148    } else {
8149       addr  = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
8150       epart = loadLE(Ity_V128, mkexpr(addr));
8151       DIP("%s %s,%s\n", opname,
8152                         dis_buf,
8153                         nameXMMReg(gregOfRexRM(pfx,rm)) );
8154       delta += alen;
8155    }
8156    putXMMReg( gregOfRexRM(pfx,rm), 
8157               eLeft ? binop(op, epart, gpart)
8158                     : binop(op, gpart, epart) );
8159    return delta;
8160 }
8161
8162
8163 /* Helper for doing SSE FP comparisons. */
8164
8165 static void findSSECmpOp ( Bool* needNot, IROp* op, 
8166                            Int imm8, Bool all_lanes, Int sz )
8167 {
8168    imm8 &= 7;
8169    *needNot = False;
8170    *op      = Iop_INVALID;
8171    if (imm8 >= 4) {
8172       *needNot = True;
8173       imm8 -= 4;
8174    }
8175
8176    if (sz == 4 && all_lanes) {
8177       switch (imm8) {
8178          case 0: *op = Iop_CmpEQ32Fx4; return;
8179          case 1: *op = Iop_CmpLT32Fx4; return;
8180          case 2: *op = Iop_CmpLE32Fx4; return;
8181          case 3: *op = Iop_CmpUN32Fx4; return;
8182          default: break;
8183       }
8184    }
8185    if (sz == 4 && !all_lanes) {
8186       switch (imm8) {
8187          case 0: *op = Iop_CmpEQ32F0x4; return;
8188          case 1: *op = Iop_CmpLT32F0x4; return;
8189          case 2: *op = Iop_CmpLE32F0x4; return;
8190          case 3: *op = Iop_CmpUN32F0x4; return;
8191          default: break;
8192       }
8193    }
8194    if (sz == 8 && all_lanes) {
8195       switch (imm8) {
8196          case 0: *op = Iop_CmpEQ64Fx2; return;
8197          case 1: *op = Iop_CmpLT64Fx2; return;
8198          case 2: *op = Iop_CmpLE64Fx2; return;
8199          case 3: *op = Iop_CmpUN64Fx2; return;
8200          default: break;
8201       }
8202    }
8203    if (sz == 8 && !all_lanes) {
8204       switch (imm8) {
8205          case 0: *op = Iop_CmpEQ64F0x2; return;
8206          case 1: *op = Iop_CmpLT64F0x2; return;
8207          case 2: *op = Iop_CmpLE64F0x2; return;
8208          case 3: *op = Iop_CmpUN64F0x2; return;
8209          default: break;
8210       }
8211    }
8212    vpanic("findSSECmpOp(amd64,guest)");
8213 }
8214
8215 /* Handles SSE 32F/64F comparisons. */
8216
8217 static ULong dis_SSEcmp_E_to_G ( VexAbiInfo* vbi,
8218                                  Prefix pfx, Long delta, 
8219                                  HChar* opname, Bool all_lanes, Int sz )
8220 {
8221    HChar   dis_buf[50];
8222    Int     alen, imm8;
8223    IRTemp  addr;
8224    Bool    needNot = False;
8225    IROp    op      = Iop_INVALID;
8226    IRTemp  plain   = newTemp(Ity_V128);
8227    UChar   rm      = getUChar(delta);
8228    UShort  mask    = 0;
8229    vassert(sz == 4 || sz == 8);
8230    if (epartIsReg(rm)) {
8231       imm8 = getUChar(delta+1);
8232       findSSECmpOp(&needNot, &op, imm8, all_lanes, sz);
8233       assign( plain, binop(op, getXMMReg(gregOfRexRM(pfx,rm)), 
8234                                getXMMReg(eregOfRexRM(pfx,rm))) );
8235       delta += 2;
8236       DIP("%s $%d,%s,%s\n", opname,
8237                             (Int)imm8,
8238                             nameXMMReg(eregOfRexRM(pfx,rm)),
8239                             nameXMMReg(gregOfRexRM(pfx,rm)) );
8240    } else {
8241       addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 1 );
8242       imm8 = getUChar(delta+alen);
8243       findSSECmpOp(&needNot, &op, imm8, all_lanes, sz);
8244       assign( plain, 
8245               binop(
8246                  op,
8247                  getXMMReg(gregOfRexRM(pfx,rm)), 
8248                    all_lanes  ? loadLE(Ity_V128, mkexpr(addr))
8249                  : sz == 8    ? unop( Iop_64UtoV128, loadLE(Ity_I64, mkexpr(addr)))
8250                  : /*sz==4*/    unop( Iop_32UtoV128, loadLE(Ity_I32, mkexpr(addr)))
8251               ) 
8252       );
8253       delta += alen+1;
8254       DIP("%s $%d,%s,%s\n", opname,
8255                             (Int)imm8,
8256                             dis_buf,
8257                             nameXMMReg(gregOfRexRM(pfx,rm)) );
8258    }
8259
8260    if (needNot && all_lanes) {
8261       putXMMReg( gregOfRexRM(pfx,rm), 
8262                  unop(Iop_NotV128, mkexpr(plain)) );
8263    }
8264    else
8265    if (needNot && !all_lanes) {
8266       mask = toUShort(sz==4 ? 0x000F : 0x00FF);
8267       putXMMReg( gregOfRexRM(pfx,rm), 
8268                  binop(Iop_XorV128, mkexpr(plain), mkV128(mask)) );
8269    }
8270    else {
8271       putXMMReg( gregOfRexRM(pfx,rm), mkexpr(plain) );
8272    }
8273
8274    return delta;
8275 }
8276
8277
8278 /* Vector by scalar shift of G by the amount specified at the bottom
8279    of E. */
8280
8281 static ULong dis_SSE_shiftG_byE ( VexAbiInfo* vbi,
8282                                   Prefix pfx, Long delta, 
8283                                   HChar* opname, IROp op )
8284 {
8285    HChar   dis_buf[50];
8286    Int     alen, size;
8287    IRTemp  addr;
8288    Bool    shl, shr, sar;
8289    UChar   rm   = getUChar(delta);
8290    IRTemp  g0   = newTemp(Ity_V128);
8291    IRTemp  g1   = newTemp(Ity_V128);
8292    IRTemp  amt  = newTemp(Ity_I32);
8293    IRTemp  amt8 = newTemp(Ity_I8);
8294    if (epartIsReg(rm)) {
8295       assign( amt, getXMMRegLane32(eregOfRexRM(pfx,rm), 0) );
8296       DIP("%s %s,%s\n", opname,
8297                         nameXMMReg(eregOfRexRM(pfx,rm)),
8298                         nameXMMReg(gregOfRexRM(pfx,rm)) );
8299       delta++;
8300    } else {
8301       addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
8302       assign( amt, loadLE(Ity_I32, mkexpr(addr)) );
8303       DIP("%s %s,%s\n", opname,
8304                         dis_buf,
8305                         nameXMMReg(gregOfRexRM(pfx,rm)) );
8306       delta += alen;
8307    }
8308    assign( g0,   getXMMReg(gregOfRexRM(pfx,rm)) );
8309    assign( amt8, unop(Iop_32to8, mkexpr(amt)) );
8310
8311    shl = shr = sar = False;
8312    size = 0;
8313    switch (op) {
8314       case Iop_ShlN16x8: shl = True; size = 32; break;
8315       case Iop_ShlN32x4: shl = True; size = 32; break;
8316       case Iop_ShlN64x2: shl = True; size = 64; break;
8317       case Iop_SarN16x8: sar = True; size = 16; break;
8318       case Iop_SarN32x4: sar = True; size = 32; break;
8319       case Iop_ShrN16x8: shr = True; size = 16; break;
8320       case Iop_ShrN32x4: shr = True; size = 32; break;
8321       case Iop_ShrN64x2: shr = True; size = 64; break;
8322       default: vassert(0);
8323    }
8324
8325    if (shl || shr) {
8326      assign( 
8327         g1,
8328         IRExpr_Mux0X(
8329            unop(Iop_1Uto8,
8330                 binop(Iop_CmpLT64U, unop(Iop_32Uto64,mkexpr(amt)), mkU64(size))),
8331            mkV128(0x0000),
8332            binop(op, mkexpr(g0), mkexpr(amt8))
8333         )
8334      );
8335    } else 
8336    if (sar) {
8337      assign( 
8338         g1,
8339         IRExpr_Mux0X(
8340            unop(Iop_1Uto8,
8341                 binop(Iop_CmpLT64U, unop(Iop_32Uto64,mkexpr(amt)), mkU64(size))),
8342            binop(op, mkexpr(g0), mkU8(size-1)),
8343            binop(op, mkexpr(g0), mkexpr(amt8))
8344         )
8345      );
8346    } else {
8347       vassert(0);
8348    }
8349
8350    putXMMReg( gregOfRexRM(pfx,rm), mkexpr(g1) );
8351    return delta;
8352 }
8353
8354
8355 /* Vector by scalar shift of E by an immediate byte. */
8356
8357 static 
8358 ULong dis_SSE_shiftE_imm ( Prefix pfx, 
8359                            Long delta, HChar* opname, IROp op )
8360 {
8361    Bool    shl, shr, sar;
8362    UChar   rm   = getUChar(delta);
8363    IRTemp  e0   = newTemp(Ity_V128);
8364    IRTemp  e1   = newTemp(Ity_V128);
8365    UChar   amt, size;
8366    vassert(epartIsReg(rm));
8367    vassert(gregLO3ofRM(rm) == 2 
8368            || gregLO3ofRM(rm) == 4 || gregLO3ofRM(rm) == 6);
8369    amt = getUChar(delta+1);
8370    delta += 2;
8371    DIP("%s $%d,%s\n", opname,
8372                       (Int)amt,
8373                       nameXMMReg(eregOfRexRM(pfx,rm)) );
8374    assign( e0, getXMMReg(eregOfRexRM(pfx,rm)) );
8375
8376    shl = shr = sar = False;
8377    size = 0;
8378    switch (op) {
8379       case Iop_ShlN16x8: shl = True; size = 16; break;
8380       case Iop_ShlN32x4: shl = True; size = 32; break;
8381       case Iop_ShlN64x2: shl = True; size = 64; break;
8382       case Iop_SarN16x8: sar = True; size = 16; break;
8383       case Iop_SarN32x4: sar = True; size = 32; break;
8384       case Iop_ShrN16x8: shr = True; size = 16; break;
8385       case Iop_ShrN32x4: shr = True; size = 32; break;
8386       case Iop_ShrN64x2: shr = True; size = 64; break;
8387       default: vassert(0);
8388    }
8389
8390    if (shl || shr) {
8391      assign( e1, amt >= size 
8392                     ? mkV128(0x0000)
8393                     : binop(op, mkexpr(e0), mkU8(amt))
8394      );
8395    } else 
8396    if (sar) {
8397      assign( e1, amt >= size 
8398                     ? binop(op, mkexpr(e0), mkU8(size-1))
8399                     : binop(op, mkexpr(e0), mkU8(amt))
8400      );
8401    } else {
8402       vassert(0);
8403    }
8404
8405    putXMMReg( eregOfRexRM(pfx,rm), mkexpr(e1) );
8406    return delta;
8407 }
8408
8409
8410 /* Get the current SSE rounding mode. */
8411
8412 static IRExpr* /* :: Ity_I32 */ get_sse_roundingmode ( void )
8413 {
8414    return 
8415       unop( Iop_64to32, 
8416             binop( Iop_And64, 
8417                    IRExpr_Get( OFFB_SSEROUND, Ity_I64 ), 
8418                    mkU64(3) ));
8419 }
8420
8421 static void put_sse_roundingmode ( IRExpr* sseround )
8422 {
8423    vassert(typeOfIRExpr(irsb->tyenv, sseround) == Ity_I32);
8424    stmt( IRStmt_Put( OFFB_SSEROUND, 
8425                      unop(Iop_32Uto64,sseround) ) );
8426 }
8427
8428 /* Break a 128-bit value up into four 32-bit ints. */
8429
8430 static void breakup128to32s ( IRTemp t128,
8431                               /*OUTs*/
8432                               IRTemp* t3, IRTemp* t2,
8433                               IRTemp* t1, IRTemp* t0 )
8434 {
8435    IRTemp hi64 = newTemp(Ity_I64);
8436    IRTemp lo64 = newTemp(Ity_I64);
8437    assign( hi64, unop(Iop_V128HIto64, mkexpr(t128)) );
8438    assign( lo64, unop(Iop_V128to64,   mkexpr(t128)) );
8439
8440    vassert(t0 && *t0 == IRTemp_INVALID);
8441    vassert(t1 && *t1 == IRTemp_INVALID);
8442    vassert(t2 && *t2 == IRTemp_INVALID);
8443    vassert(t3 && *t3 == IRTemp_INVALID);
8444
8445    *t0 = newTemp(Ity_I32);
8446    *t1 = newTemp(Ity_I32);
8447    *t2 = newTemp(Ity_I32);
8448    *t3 = newTemp(Ity_I32);
8449    assign( *t0, unop(Iop_64to32,   mkexpr(lo64)) );
8450    assign( *t1, unop(Iop_64HIto32, mkexpr(lo64)) );
8451    assign( *t2, unop(Iop_64to32,   mkexpr(hi64)) );
8452    assign( *t3, unop(Iop_64HIto32, mkexpr(hi64)) );
8453 }
8454
8455 /* Construct a 128-bit value from four 32-bit ints. */
8456
8457 static IRExpr* mk128from32s ( IRTemp t3, IRTemp t2,
8458                               IRTemp t1, IRTemp t0 )
8459 {
8460    return
8461       binop( Iop_64HLtoV128,
8462              binop(Iop_32HLto64, mkexpr(t3), mkexpr(t2)),
8463              binop(Iop_32HLto64, mkexpr(t1), mkexpr(t0))
8464    );
8465 }
8466
8467 /* Break a 64-bit value up into four 16-bit ints. */
8468
8469 static void breakup64to16s ( IRTemp t64,
8470                              /*OUTs*/
8471                              IRTemp* t3, IRTemp* t2,
8472                              IRTemp* t1, IRTemp* t0 )
8473 {
8474    IRTemp hi32 = newTemp(Ity_I32);
8475    IRTemp lo32 = newTemp(Ity_I32);
8476    assign( hi32, unop(Iop_64HIto32, mkexpr(t64)) );
8477    assign( lo32, unop(Iop_64to32,   mkexpr(t64)) );
8478
8479    vassert(t0 && *t0 == IRTemp_INVALID);
8480    vassert(t1 && *t1 == IRTemp_INVALID);
8481    vassert(t2 && *t2 == IRTemp_INVALID);
8482    vassert(t3 && *t3 == IRTemp_INVALID);
8483
8484    *t0 = newTemp(Ity_I16);
8485    *t1 = newTemp(Ity_I16);
8486    *t2 = newTemp(Ity_I16);
8487    *t3 = newTemp(Ity_I16);
8488    assign( *t0, unop(Iop_32to16,   mkexpr(lo32)) );
8489    assign( *t1, unop(Iop_32HIto16, mkexpr(lo32)) );
8490    assign( *t2, unop(Iop_32to16,   mkexpr(hi32)) );
8491    assign( *t3, unop(Iop_32HIto16, mkexpr(hi32)) );
8492 }
8493
8494 /* Construct a 64-bit value from four 16-bit ints. */
8495
8496 static IRExpr* mk64from16s ( IRTemp t3, IRTemp t2,
8497                              IRTemp t1, IRTemp t0 )
8498 {
8499    return
8500       binop( Iop_32HLto64,
8501              binop(Iop_16HLto32, mkexpr(t3), mkexpr(t2)),
8502              binop(Iop_16HLto32, mkexpr(t1), mkexpr(t0))
8503    );
8504 }
8505
8506
8507 /* Helper for the SSSE3 (not SSE3) PMULHRSW insns.  Given two 64-bit
8508    values (aa,bb), computes, for each of the 4 16-bit lanes:
8509
8510    (((aa_lane *s32 bb_lane) >>u 14) + 1) >>u 1
8511 */
8512 static IRExpr* dis_PMULHRSW_helper ( IRExpr* aax, IRExpr* bbx )
8513 {
8514    IRTemp aa      = newTemp(Ity_I64);
8515    IRTemp bb      = newTemp(Ity_I64);
8516    IRTemp aahi32s = newTemp(Ity_I64);
8517    IRTemp aalo32s = newTemp(Ity_I64);
8518    IRTemp bbhi32s = newTemp(Ity_I64);
8519    IRTemp bblo32s = newTemp(Ity_I64);
8520    IRTemp rHi     = newTemp(Ity_I64);
8521    IRTemp rLo     = newTemp(Ity_I64);
8522    IRTemp one32x2 = newTemp(Ity_I64);
8523    assign(aa, aax);
8524    assign(bb, bbx);
8525    assign( aahi32s,
8526            binop(Iop_SarN32x2,
8527                  binop(Iop_InterleaveHI16x4, mkexpr(aa), mkexpr(aa)),
8528                  mkU8(16) ));
8529    assign( aalo32s,
8530            binop(Iop_SarN32x2,
8531                  binop(Iop_InterleaveLO16x4, mkexpr(aa), mkexpr(aa)),
8532                  mkU8(16) ));
8533    assign( bbhi32s,
8534            binop(Iop_SarN32x2,
8535                  binop(Iop_InterleaveHI16x4, mkexpr(bb), mkexpr(bb)),
8536                  mkU8(16) ));
8537    assign( bblo32s,
8538            binop(Iop_SarN32x2,
8539                  binop(Iop_InterleaveLO16x4, mkexpr(bb), mkexpr(bb)),
8540                  mkU8(16) ));
8541    assign(one32x2, mkU64( (1ULL << 32) + 1 ));
8542    assign(
8543       rHi,
8544       binop(
8545          Iop_ShrN32x2,
8546          binop(
8547             Iop_Add32x2, 
8548             binop(
8549                Iop_ShrN32x2,
8550                binop(Iop_Mul32x2, mkexpr(aahi32s), mkexpr(bbhi32s)),
8551                mkU8(14)
8552             ),
8553             mkexpr(one32x2)
8554          ),
8555          mkU8(1)
8556       )
8557    );
8558    assign(
8559       rLo,
8560       binop(
8561          Iop_ShrN32x2,
8562          binop(
8563             Iop_Add32x2, 
8564             binop(
8565                Iop_ShrN32x2,
8566                binop(Iop_Mul32x2, mkexpr(aalo32s), mkexpr(bblo32s)),
8567                mkU8(14)
8568             ),
8569             mkexpr(one32x2)
8570          ),
8571          mkU8(1)
8572       )
8573    );
8574    return
8575       binop(Iop_CatEvenLanes16x4, mkexpr(rHi), mkexpr(rLo));
8576 }
8577
8578 /* Helper for the SSSE3 (not SSE3) PSIGN{B,W,D} insns.  Given two 64-bit
8579    values (aa,bb), computes, for each lane:
8580
8581           if aa_lane < 0 then - bb_lane
8582      else if aa_lane > 0 then bb_lane
8583      else 0
8584 */
8585 static IRExpr* dis_PSIGN_helper ( IRExpr* aax, IRExpr* bbx, Int laneszB )
8586 {
8587    IRTemp aa       = newTemp(Ity_I64);
8588    IRTemp bb       = newTemp(Ity_I64);
8589    IRTemp zero     = newTemp(Ity_I64);
8590    IRTemp bbNeg    = newTemp(Ity_I64);
8591    IRTemp negMask  = newTemp(Ity_I64);
8592    IRTemp posMask  = newTemp(Ity_I64);
8593    IROp   opSub    = Iop_INVALID;
8594    IROp   opCmpGTS = Iop_INVALID;
8595
8596    switch (laneszB) {
8597       case 1: opSub = Iop_Sub8x8;  opCmpGTS = Iop_CmpGT8Sx8;  break;
8598       case 2: opSub = Iop_Sub16x4; opCmpGTS = Iop_CmpGT16Sx4; break;
8599       case 4: opSub = Iop_Sub32x2; opCmpGTS = Iop_CmpGT32Sx2; break;
8600       default: vassert(0);
8601    }
8602
8603    assign( aa,      aax );
8604    assign( bb,      bbx );
8605    assign( zero,    mkU64(0) );
8606    assign( bbNeg,   binop(opSub,    mkexpr(zero), mkexpr(bb)) );
8607    assign( negMask, binop(opCmpGTS, mkexpr(zero), mkexpr(aa)) );
8608    assign( posMask, binop(opCmpGTS, mkexpr(aa),   mkexpr(zero)) );
8609
8610    return
8611       binop(Iop_Or64,
8612             binop(Iop_And64, mkexpr(bb),    mkexpr(posMask)),
8613             binop(Iop_And64, mkexpr(bbNeg), mkexpr(negMask)) );
8614
8615 }
8616
8617 /* Helper for the SSSE3 (not SSE3) PABS{B,W,D} insns.  Given a 64-bit
8618    value aa, computes, for each lane
8619
8620    if aa < 0 then -aa else aa
8621
8622    Note that the result is interpreted as unsigned, so that the
8623    absolute value of the most negative signed input can be
8624    represented.
8625 */
8626 static IRExpr* dis_PABS_helper ( IRExpr* aax, Int laneszB )
8627 {
8628    IRTemp aa      = newTemp(Ity_I64);
8629    IRTemp zero    = newTemp(Ity_I64);
8630    IRTemp aaNeg   = newTemp(Ity_I64);
8631    IRTemp negMask = newTemp(Ity_I64);
8632    IRTemp posMask = newTemp(Ity_I64);
8633    IROp   opSub   = Iop_INVALID;
8634    IROp   opSarN  = Iop_INVALID;
8635
8636    switch (laneszB) {
8637       case 1: opSub = Iop_Sub8x8;  opSarN = Iop_SarN8x8;  break;
8638       case 2: opSub = Iop_Sub16x4; opSarN = Iop_SarN16x4; break;
8639       case 4: opSub = Iop_Sub32x2; opSarN = Iop_SarN32x2; break;
8640       default: vassert(0);
8641    }
8642
8643    assign( aa,      aax );
8644    assign( negMask, binop(opSarN, mkexpr(aa), mkU8(8*laneszB-1)) );
8645    assign( posMask, unop(Iop_Not64, mkexpr(negMask)) );
8646    assign( zero,    mkU64(0) );
8647    assign( aaNeg,   binop(opSub, mkexpr(zero), mkexpr(aa)) );
8648    return
8649       binop(Iop_Or64,
8650             binop(Iop_And64, mkexpr(aa),    mkexpr(posMask)),
8651             binop(Iop_And64, mkexpr(aaNeg), mkexpr(negMask)) );
8652 }
8653
8654 static IRExpr* dis_PALIGNR_XMM_helper ( IRTemp hi64,
8655                                         IRTemp lo64, Long byteShift )
8656 {
8657    vassert(byteShift >= 1 && byteShift <= 7);
8658    return
8659       binop(Iop_Or64,
8660             binop(Iop_Shl64, mkexpr(hi64), mkU8(8*(8-byteShift))),
8661             binop(Iop_Shr64, mkexpr(lo64), mkU8(8*byteShift))
8662       );
8663 }
8664
8665 /* Generate a SIGSEGV followed by a restart of the current instruction
8666    if effective_addr is not 16-aligned.  This is required behaviour
8667    for some SSE3 instructions and all 128-bit SSSE3 instructions.
8668    This assumes that guest_RIP_curr_instr is set correctly! */
8669 static void gen_SEGV_if_not_16_aligned ( IRTemp effective_addr )
8670 {
8671    stmt(
8672       IRStmt_Exit(
8673          binop(Iop_CmpNE64,
8674                binop(Iop_And64,mkexpr(effective_addr),mkU64(0xF)),
8675                mkU64(0)),
8676          Ijk_SigSEGV,
8677          IRConst_U64(guest_RIP_curr_instr)
8678       )
8679    );
8680 }
8681
8682
8683 /* Helper for deciding whether a given insn (starting at the opcode
8684    byte) may validly be used with a LOCK prefix.  The following insns
8685    may be used with LOCK when their destination operand is in memory.
8686    AFAICS this is exactly the same for both 32-bit and 64-bit mode.
8687
8688    ADD        80 /0,  81 /0,  82 /0,  83 /0,  00,  01
8689    OR         80 /1,  81 /1,  82 /x,  83 /1,  08,  09
8690    ADC        80 /2,  81 /2,  82 /2,  83 /2,  10,  11
8691    SBB        81 /3,  81 /3,  82 /x,  83 /3,  18,  19
8692    AND        80 /4,  81 /4,  82 /x,  83 /4,  20,  21
8693    SUB        80 /5,  81 /5,  82 /x,  83 /5,  28,  29
8694    XOR        80 /6,  81 /6,  82 /x,  83 /6,  30,  31
8695
8696    DEC        FE /1,  FF /1
8697    INC        FE /0,  FF /0
8698
8699    NEG        F6 /3,  F7 /3
8700    NOT        F6 /2,  F7 /2
8701
8702    XCHG       86, 87
8703
8704    BTC        0F BB,  0F BA /7
8705    BTR        0F B3,  0F BA /6
8706    BTS        0F AB,  0F BA /5
8707
8708    CMPXCHG    0F B0,  0F B1
8709    CMPXCHG8B  0F C7 /1
8710
8711    XADD       0F C0,  0F C1
8712
8713    ------------------------------
8714
8715    80 /0  =  addb $imm8,  rm8
8716    81 /0  =  addl $imm32, rm32  and  addw $imm16, rm16
8717    82 /0  =  addb $imm8,  rm8
8718    83 /0  =  addl $simm8, rm32  and  addw $simm8, rm16
8719
8720    00     =  addb r8,  rm8
8721    01     =  addl r32, rm32  and  addw r16, rm16
8722
8723    Same for ADD OR ADC SBB AND SUB XOR
8724
8725    FE /1  = dec rm8
8726    FF /1  = dec rm32  and  dec rm16
8727
8728    FE /0  = inc rm8
8729    FF /0  = inc rm32  and  inc rm16
8730
8731    F6 /3  = neg rm8
8732    F7 /3  = neg rm32  and  neg rm16
8733
8734    F6 /2  = not rm8
8735    F7 /2  = not rm32  and  not rm16
8736
8737    0F BB     = btcw r16, rm16    and  btcl r32, rm32
8738    OF BA /7  = btcw $imm8, rm16  and  btcw $imm8, rm32
8739
8740    Same for BTS, BTR
8741 */
8742 static Bool can_be_used_with_LOCK_prefix ( UChar* opc )
8743 {
8744    switch (opc[0]) {
8745       case 0x00: case 0x01: case 0x08: case 0x09:
8746       case 0x10: case 0x11: case 0x18: case 0x19:
8747       case 0x20: case 0x21: case 0x28: case 0x29:
8748       case 0x30: case 0x31:
8749          if (!epartIsReg(opc[1]))
8750             return True;
8751          break;
8752
8753       case 0x80: case 0x81: case 0x82: case 0x83:
8754          if (gregLO3ofRM(opc[1]) >= 0 && gregLO3ofRM(opc[1]) <= 6
8755              && !epartIsReg(opc[1]))
8756             return True;
8757          break;
8758
8759       case 0xFE: case 0xFF:
8760          if (gregLO3ofRM(opc[1]) >= 0 && gregLO3ofRM(opc[1]) <= 1
8761              && !epartIsReg(opc[1]))
8762             return True;
8763          break;
8764
8765       case 0xF6: case 0xF7:
8766          if (gregLO3ofRM(opc[1]) >= 2 && gregLO3ofRM(opc[1]) <= 3
8767              && !epartIsReg(opc[1]))
8768             return True;
8769          break;
8770
8771       case 0x86: case 0x87:
8772          if (!epartIsReg(opc[1]))
8773             return True;
8774          break;
8775
8776       case 0x0F: {
8777          switch (opc[1]) {
8778             case 0xBB: case 0xB3: case 0xAB:
8779                if (!epartIsReg(opc[2]))
8780                   return True;
8781                break;
8782             case 0xBA: 
8783                if (gregLO3ofRM(opc[2]) >= 5 && gregLO3ofRM(opc[2]) <= 7
8784                    && !epartIsReg(opc[2]))
8785                   return True;
8786                break;
8787             case 0xB0: case 0xB1:
8788                if (!epartIsReg(opc[2]))
8789                   return True;
8790                break;
8791             case 0xC7: 
8792                if (gregLO3ofRM(opc[2]) == 1 && !epartIsReg(opc[2]) )
8793                   return True;
8794                break;
8795             case 0xC0: case 0xC1:
8796                if (!epartIsReg(opc[2]))
8797                   return True;
8798                break;
8799             default:
8800                break;
8801          } /* switch (opc[1]) */
8802          break;
8803       }
8804
8805       default:
8806          break;
8807    } /* switch (opc[0]) */
8808
8809    return False;
8810 }
8811
8812
8813 /*------------------------------------------------------------*/
8814 /*--- Disassemble a single instruction                     ---*/
8815 /*------------------------------------------------------------*/
8816
8817 /* Disassemble a single instruction into IR.  The instruction is
8818    located in host memory at &guest_code[delta]. */
8819    
8820 static
8821 DisResult disInstr_AMD64_WRK ( 
8822              /*OUT*/Bool* expect_CAS,
8823              Bool         put_IP,
8824              Bool         (*resteerOkFn) ( /*opaque*/void*, Addr64 ),
8825              Bool         resteerCisOk,
8826              void*        callback_opaque,
8827              Long         delta64,
8828              VexArchInfo* archinfo,
8829              VexAbiInfo*  vbi
8830           )
8831 {
8832    IRType    ty;
8833    IRTemp    addr, t0, t1, t2, t3, t4, t5, t6;
8834    Int       alen;
8835    UChar     opc, modrm, abyte, pre;
8836    Long      d64;
8837    HChar     dis_buf[50];
8838    Int       am_sz, d_sz, n, n_prefixes;
8839    DisResult dres;
8840    UChar*    insn; /* used in SSE decoders */
8841
8842    /* The running delta */
8843    Long delta = delta64;
8844
8845    /* Holds eip at the start of the insn, so that we can print
8846       consistent error messages for unimplemented insns. */
8847    Long delta_start = delta;
8848
8849    /* sz denotes the nominal data-op size of the insn; we change it to
8850       2 if an 0x66 prefix is seen and 8 if REX.W is 1.  In case of
8851       conflict REX.W takes precedence. */
8852    Int sz = 4;
8853
8854    /* pfx holds the summary of prefixes. */
8855    Prefix pfx = PFX_EMPTY;
8856
8857    /* Set result defaults. */
8858    dres.whatNext   = Dis_Continue;
8859    dres.len        = 0;
8860    dres.continueAt = 0;
8861
8862    *expect_CAS = False;
8863
8864    vassert(guest_RIP_next_assumed == 0);
8865    vassert(guest_RIP_next_mustcheck == False);
8866
8867    addr = t0 = t1 = t2 = t3 = t4 = t5 = t6 = IRTemp_INVALID; 
8868
8869    DIP("\t0x%llx:  ", guest_RIP_bbstart+delta);
8870
8871    /* We may be asked to update the guest RIP before going further. */
8872    if (put_IP)
8873       stmt( IRStmt_Put( OFFB_RIP, mkU64(guest_RIP_curr_instr)) );
8874
8875    /* Spot "Special" instructions (see comment at top of file). */
8876    {
8877       UChar* code = (UChar*)(guest_code + delta);
8878       /* Spot the 16-byte preamble:
8879          48C1C703   rolq $3,  %rdi
8880          48C1C70D   rolq $13, %rdi
8881          48C1C73D   rolq $61, %rdi
8882          48C1C733   rolq $51, %rdi
8883       */
8884       if (code[ 0] == 0x48 && code[ 1] == 0xC1 && code[ 2] == 0xC7 
8885                                                && code[ 3] == 0x03 &&
8886           code[ 4] == 0x48 && code[ 5] == 0xC1 && code[ 6] == 0xC7 
8887                                                && code[ 7] == 0x0D &&
8888           code[ 8] == 0x48 && code[ 9] == 0xC1 && code[10] == 0xC7 
8889                                                && code[11] == 0x3D &&
8890           code[12] == 0x48 && code[13] == 0xC1 && code[14] == 0xC7 
8891                                                && code[15] == 0x33) {
8892          /* Got a "Special" instruction preamble.  Which one is it? */
8893          if (code[16] == 0x48 && code[17] == 0x87 
8894                               && code[18] == 0xDB /* xchgq %rbx,%rbx */) {
8895             /* %RDX = client_request ( %RAX ) */
8896             DIP("%%rdx = client_request ( %%rax )\n");
8897             delta += 19;
8898             jmp_lit(Ijk_ClientReq, guest_RIP_bbstart+delta);
8899             dres.whatNext = Dis_StopHere;
8900             goto decode_success;
8901          }
8902          else
8903          if (code[16] == 0x48 && code[17] == 0x87 
8904                               && code[18] == 0xC9 /* xchgq %rcx,%rcx */) {
8905             /* %RAX = guest_NRADDR */
8906             DIP("%%rax = guest_NRADDR\n");
8907             delta += 19;
8908             putIRegRAX(8, IRExpr_Get( OFFB_NRADDR, Ity_I64 ));
8909             goto decode_success;
8910          }
8911          else
8912          if (code[16] == 0x48 && code[17] == 0x87 
8913                               && code[18] == 0xD2 /* xchgq %rdx,%rdx */) {
8914             /* call-noredir *%RAX */
8915             DIP("call-noredir *%%rax\n");
8916             delta += 19;
8917             t1 = newTemp(Ity_I64);
8918             assign(t1, getIRegRAX(8));
8919             t2 = newTemp(Ity_I64);
8920             assign(t2, binop(Iop_Sub64, getIReg64(R_RSP), mkU64(8)));
8921             putIReg64(R_RSP, mkexpr(t2));
8922             storeLE( mkexpr(t2), mkU64(guest_RIP_bbstart+delta));
8923             jmp_treg(Ijk_NoRedir,t1);
8924             dres.whatNext = Dis_StopHere;
8925             goto decode_success;
8926          }
8927          /* We don't know what it is. */
8928          goto decode_failure;
8929          /*NOTREACHED*/
8930       }
8931    }
8932
8933    /* Eat prefixes, summarising the result in pfx and sz, and rejecting
8934       as many invalid combinations as possible. */
8935    n_prefixes = 0;
8936    while (True) {
8937       if (n_prefixes > 7) goto decode_failure;
8938       pre = getUChar(delta);
8939       switch (pre) {
8940          case 0x66: pfx |= PFX_66; break;
8941          case 0x67: pfx |= PFX_ASO; break;
8942          case 0xF2: pfx |= PFX_F2; break;
8943          case 0xF3: pfx |= PFX_F3; break;
8944          case 0xF0: pfx |= PFX_LOCK; *expect_CAS = True; break;
8945          case 0x2E: pfx |= PFX_CS; break;
8946          case 0x3E: pfx |= PFX_DS; break;
8947          case 0x26: pfx |= PFX_ES; break;
8948          case 0x64: pfx |= PFX_FS; break;
8949          case 0x65: pfx |= PFX_GS; break;
8950          case 0x36: pfx |= PFX_SS; break;
8951          case 0x40 ... 0x4F:
8952             pfx |= PFX_REX;
8953             if (pre & (1<<3)) pfx |= PFX_REXW;
8954             if (pre & (1<<2)) pfx |= PFX_REXR;
8955             if (pre & (1<<1)) pfx |= PFX_REXX;
8956             if (pre & (1<<0)) pfx |= PFX_REXB;
8957             break;
8958          default: 
8959             goto not_a_prefix;
8960       }
8961       n_prefixes++;
8962       delta++;
8963    }
8964
8965    not_a_prefix:
8966
8967    /* Dump invalid combinations */
8968    n = 0;
8969    if (pfx & PFX_F2) n++;
8970    if (pfx & PFX_F3) n++;
8971    if (n > 1) 
8972       goto decode_failure; /* can't have both */
8973
8974    n = 0;
8975    if (pfx & PFX_CS) n++;
8976    if (pfx & PFX_DS) n++;
8977    if (pfx & PFX_ES) n++;
8978    if (pfx & PFX_FS) n++;
8979    if (pfx & PFX_GS) n++;
8980    if (pfx & PFX_SS) n++;
8981    if (n > 1) 
8982       goto decode_failure; /* multiple seg overrides == illegal */
8983
8984    /* We have a %fs prefix.  Reject it if there's no evidence in 'vbi'
8985       that we should accept it. */
8986    if ((pfx & PFX_FS) && !vbi->guest_amd64_assume_fs_is_zero)
8987       goto decode_failure;
8988
8989    /* Ditto for %gs prefixes. */
8990    if ((pfx & PFX_GS) && !vbi->guest_amd64_assume_gs_is_0x60)
8991       goto decode_failure;
8992
8993    /* Set up sz. */
8994    sz = 4;
8995    if (pfx & PFX_66) sz = 2;
8996    if ((pfx & PFX_REX) && (pfx & PFX_REXW)) sz = 8;
8997
8998    /* Now we should be looking at the primary opcode byte or the
8999       leading F2 or F3.  Check that any LOCK prefix is actually
9000       allowed. */
9001
9002    if (pfx & PFX_LOCK) {
9003       if (can_be_used_with_LOCK_prefix( (UChar*)&guest_code[delta] )) {
9004          DIP("lock ");
9005       } else {
9006          *expect_CAS = False;
9007          goto decode_failure;
9008       }
9009    }
9010
9011
9012    /* ---------------------------------------------------- */
9013    /* --- The SSE/SSE2 decoder.                        --- */
9014    /* ---------------------------------------------------- */
9015
9016    /* What did I do to deserve SSE ?  Perhaps I was really bad in a
9017       previous life? */
9018
9019    /* Note, this doesn't handle SSE3 right now.  All amd64s support
9020       SSE2 as a minimum so there is no point distinguishing SSE1 vs
9021       SSE2. */
9022
9023    insn = (UChar*)&guest_code[delta];
9024
9025    /* FXSAVE is spuriously at the start here only because it is
9026       thusly placed in guest-x86/toIR.c. */
9027
9028    /* 0F AE /0 = FXSAVE m512 -- write x87 and SSE state to memory.
9029       Note that REX.W 0F AE /0 writes a slightly different format and
9030       we don't handle that here. */
9031    if (haveNo66noF2noF3(pfx) && sz == 4 
9032        && insn[0] == 0x0F && insn[1] == 0xAE
9033        && !epartIsReg(insn[2]) && gregOfRexRM(pfx,insn[2]) == 0) {
9034        IRDirty* d;
9035       modrm = getUChar(delta+2);
9036       vassert(sz == 4);
9037       vassert(!epartIsReg(modrm));
9038       /* REX.W must not be set.  That should be assured us by sz == 4
9039          above. */
9040       vassert(!(pfx & PFX_REXW));
9041
9042       addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
9043       delta += 2+alen;
9044
9045       DIP("fxsave %s\n", dis_buf);
9046
9047       /* Uses dirty helper: 
9048             void amd64g_do_FXSAVE ( VexGuestAMD64State*, UInt ) */
9049       d = unsafeIRDirty_0_N ( 
9050              0/*regparms*/, 
9051              "amd64g_dirtyhelper_FXSAVE", 
9052              &amd64g_dirtyhelper_FXSAVE,
9053              mkIRExprVec_1( mkexpr(addr) )
9054           );
9055       d->needsBBP = True;
9056
9057       /* declare we're writing memory */
9058       d->mFx   = Ifx_Write;
9059       d->mAddr = mkexpr(addr);
9060       d->mSize = 512;
9061
9062       /* declare we're reading guest state */
9063       d->nFxState = 7;
9064
9065       d->fxState[0].fx     = Ifx_Read;
9066       d->fxState[0].offset = OFFB_FTOP;
9067       d->fxState[0].size   = sizeof(UInt);
9068
9069       d->fxState[1].fx     = Ifx_Read;
9070       d->fxState[1].offset = OFFB_FPREGS;
9071       d->fxState[1].size   = 8 * sizeof(ULong);
9072
9073       d->fxState[2].fx     = Ifx_Read;
9074       d->fxState[2].offset = OFFB_FPTAGS;
9075       d->fxState[2].size   = 8 * sizeof(UChar);
9076
9077       d->fxState[3].fx     = Ifx_Read;
9078       d->fxState[3].offset = OFFB_FPROUND;
9079       d->fxState[3].size   = sizeof(ULong);
9080
9081       d->fxState[4].fx     = Ifx_Read;
9082       d->fxState[4].offset = OFFB_FC3210;
9083       d->fxState[4].size   = sizeof(ULong);
9084
9085       d->fxState[5].fx     = Ifx_Read;
9086       d->fxState[5].offset = OFFB_XMM0;
9087       d->fxState[5].size   = 16 * sizeof(U128);
9088
9089       d->fxState[6].fx     = Ifx_Read;
9090       d->fxState[6].offset = OFFB_SSEROUND;
9091       d->fxState[6].size   = sizeof(ULong);
9092
9093       /* Be paranoid ... this assertion tries to ensure the 16 %xmm
9094          images are packed back-to-back.  If not, the value of
9095          d->fxState[5].size is wrong. */
9096       vassert(16 == sizeof(U128));
9097       vassert(OFFB_XMM15 == (OFFB_XMM0 + 15 * 16));
9098
9099       stmt( IRStmt_Dirty(d) );
9100
9101       goto decode_success;
9102    }
9103
9104    /* ------ SSE decoder main ------ */
9105
9106    /* 0F 58 = ADDPS -- add 32Fx4 from R/M to R */
9107    if (haveNo66noF2noF3(pfx) && sz == 4 
9108        && insn[0] == 0x0F && insn[1] == 0x58) {
9109       delta = dis_SSE_E_to_G_all( vbi, pfx, delta+2, "addps", Iop_Add32Fx4 );
9110       goto decode_success;
9111    }
9112
9113    /* F3 0F 58 = ADDSS -- add 32F0x4 from R/M to R */
9114    if (haveF3no66noF2(pfx) && sz == 4
9115        && insn[0] == 0x0F && insn[1] == 0x58) {
9116       delta = dis_SSE_E_to_G_lo32( vbi, pfx, delta+2, "addss", Iop_Add32F0x4 );
9117       goto decode_success;
9118    }
9119
9120    /* 0F 55 = ANDNPS -- G = (not G) and E */
9121    if (haveNo66noF2noF3(pfx) && sz == 4 
9122        && insn[0] == 0x0F && insn[1] == 0x55) {
9123       delta = dis_SSE_E_to_G_all_invG( vbi, pfx, delta+2, "andnps", Iop_AndV128 );
9124       goto decode_success;
9125    }
9126
9127    /* 0F 54 = ANDPS -- G = G and E */
9128    if (haveNo66noF2noF3(pfx) && sz == 4 
9129        && insn[0] == 0x0F && insn[1] == 0x54) {
9130       delta = dis_SSE_E_to_G_all( vbi, pfx, delta+2, "andps", Iop_AndV128 );
9131       goto decode_success;
9132    }
9133
9134    /* 0F C2 = CMPPS -- 32Fx4 comparison from R/M to R */
9135    if (haveNo66noF2noF3(pfx) && sz == 4 
9136        && insn[0] == 0x0F && insn[1] == 0xC2) {
9137       delta = dis_SSEcmp_E_to_G( vbi, pfx, delta+2, "cmpps", True, 4 );
9138       goto decode_success;
9139    }
9140
9141    /* F3 0F C2 = CMPSS -- 32F0x4 comparison from R/M to R */
9142    if (haveF3no66noF2(pfx) && sz == 4
9143        && insn[0] == 0x0F && insn[1] == 0xC2) {
9144       delta = dis_SSEcmp_E_to_G( vbi, pfx, delta+2, "cmpss", False, 4 );
9145       goto decode_success;
9146    }
9147
9148    /* 0F 2F = COMISS  -- 32F0x4 comparison G,E, and set ZCP */
9149    /* 0F 2E = UCOMISS -- 32F0x4 comparison G,E, and set ZCP */
9150    if (haveNo66noF2noF3(pfx) && sz == 4 
9151        && insn[0] == 0x0F && (insn[1] == 0x2F || insn[1] == 0x2E)) {
9152       IRTemp argL = newTemp(Ity_F32);
9153       IRTemp argR = newTemp(Ity_F32);
9154       modrm = getUChar(delta+2);
9155       if (epartIsReg(modrm)) {
9156          assign( argR, getXMMRegLane32F( eregOfRexRM(pfx,modrm), 
9157                                          0/*lowest lane*/ ) );
9158          delta += 2+1;
9159          DIP("%scomiss %s,%s\n", insn[1]==0x2E ? "u" : "",
9160                                  nameXMMReg(eregOfRexRM(pfx,modrm)),
9161                                  nameXMMReg(gregOfRexRM(pfx,modrm)) );
9162       } else {
9163          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
9164          assign( argR, loadLE(Ity_F32, mkexpr(addr)) );
9165          delta += 2+alen;
9166          DIP("%scomiss %s,%s\n", insn[1]==0x2E ? "u" : "",
9167                                  dis_buf,
9168                                  nameXMMReg(gregOfRexRM(pfx,modrm)) );
9169       }
9170       assign( argL, getXMMRegLane32F( gregOfRexRM(pfx,modrm), 
9171                                       0/*lowest lane*/ ) );
9172
9173       stmt( IRStmt_Put( OFFB_CC_OP,   mkU64(AMD64G_CC_OP_COPY) ));
9174       stmt( IRStmt_Put( OFFB_CC_DEP2, mkU64(0) ));
9175       stmt( IRStmt_Put( 
9176                OFFB_CC_DEP1,
9177                binop( Iop_And64,
9178                       unop( Iop_32Uto64,
9179                             binop(Iop_CmpF64, 
9180                                   unop(Iop_F32toF64,mkexpr(argL)),
9181                                   unop(Iop_F32toF64,mkexpr(argR)))),
9182                       mkU64(0x45)
9183           )));
9184
9185       goto decode_success;
9186    }
9187
9188    /* 0F 2A = CVTPI2PS -- convert 2 x I32 in mem/mmx to 2 x F32 in low
9189       half xmm */
9190    if (haveNo66noF2noF3(pfx) && sz == 4 
9191        && insn[0] == 0x0F && insn[1] == 0x2A) {
9192       IRTemp arg64 = newTemp(Ity_I64);
9193       IRTemp rmode = newTemp(Ity_I32);
9194
9195       modrm = getUChar(delta+2);
9196       do_MMX_preamble();
9197       if (epartIsReg(modrm)) {
9198          assign( arg64, getMMXReg(eregLO3ofRM(modrm)) );
9199          delta += 2+1;
9200          DIP("cvtpi2ps %s,%s\n", nameMMXReg(eregLO3ofRM(modrm)),
9201                                  nameXMMReg(gregOfRexRM(pfx,modrm)));
9202       } else {
9203          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
9204          assign( arg64, loadLE(Ity_I64, mkexpr(addr)) );
9205          delta += 2+alen;
9206          DIP("cvtpi2ps %s,%s\n", dis_buf,
9207                                  nameXMMReg(gregOfRexRM(pfx,modrm)) );
9208       }
9209
9210       assign( rmode, get_sse_roundingmode() );
9211
9212       putXMMRegLane32F( 
9213          gregOfRexRM(pfx,modrm), 0,
9214          binop(Iop_F64toF32, 
9215                mkexpr(rmode),
9216                unop(Iop_I32StoF64, 
9217                     unop(Iop_64to32, mkexpr(arg64)) )) );
9218
9219       putXMMRegLane32F(
9220          gregOfRexRM(pfx,modrm), 1, 
9221          binop(Iop_F64toF32, 
9222                mkexpr(rmode),
9223                unop(Iop_I32StoF64,
9224                     unop(Iop_64HIto32, mkexpr(arg64)) )) );
9225
9226       goto decode_success;
9227    }
9228
9229    /* F3 0F 2A = CVTSI2SS 
9230       -- sz==4: convert I32 in mem/ireg to F32 in low quarter xmm
9231       -- sz==8: convert I64 in mem/ireg to F32 in low quarter xmm */
9232    if (haveF3no66noF2(pfx) && (sz == 4 || sz == 8)
9233        && insn[0] == 0x0F && insn[1] == 0x2A) {
9234
9235       IRTemp rmode = newTemp(Ity_I32);
9236       assign( rmode, get_sse_roundingmode() );
9237       modrm = getUChar(delta+2);
9238
9239       if (sz == 4) {
9240          IRTemp arg32 = newTemp(Ity_I32);
9241          if (epartIsReg(modrm)) {
9242             assign( arg32, getIReg32(eregOfRexRM(pfx,modrm)) );
9243             delta += 2+1;
9244             DIP("cvtsi2ss %s,%s\n", nameIReg32(eregOfRexRM(pfx,modrm)),
9245                                     nameXMMReg(gregOfRexRM(pfx,modrm)));
9246          } else {
9247             addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
9248             assign( arg32, loadLE(Ity_I32, mkexpr(addr)) );
9249             delta += 2+alen;
9250             DIP("cvtsi2ss %s,%s\n", dis_buf,
9251                                     nameXMMReg(gregOfRexRM(pfx,modrm)) );
9252          }
9253          putXMMRegLane32F( 
9254             gregOfRexRM(pfx,modrm), 0,
9255             binop(Iop_F64toF32,
9256                   mkexpr(rmode),
9257                   unop(Iop_I32StoF64, mkexpr(arg32)) ) );
9258       } else {
9259          /* sz == 8 */
9260          IRTemp arg64 = newTemp(Ity_I64);
9261          if (epartIsReg(modrm)) {
9262             assign( arg64, getIReg64(eregOfRexRM(pfx,modrm)) );
9263             delta += 2+1;
9264             DIP("cvtsi2ssq %s,%s\n", nameIReg64(eregOfRexRM(pfx,modrm)),
9265                                      nameXMMReg(gregOfRexRM(pfx,modrm)));
9266          } else {
9267             addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
9268             assign( arg64, loadLE(Ity_I64, mkexpr(addr)) );
9269             delta += 2+alen;
9270             DIP("cvtsi2ssq %s,%s\n", dis_buf,
9271                                      nameXMMReg(gregOfRexRM(pfx,modrm)) );
9272          }
9273          putXMMRegLane32F( 
9274             gregOfRexRM(pfx,modrm), 0,
9275             binop(Iop_F64toF32,
9276                   mkexpr(rmode),
9277                   binop(Iop_I64StoF64, mkexpr(rmode), mkexpr(arg64)) ) );
9278       }
9279
9280       goto decode_success;
9281    }
9282
9283    /* 0F 2D = CVTPS2PI -- convert 2 x F32 in mem/low half xmm to 2 x
9284       I32 in mmx, according to prevailing SSE rounding mode */
9285    /* 0F 2C = CVTTPS2PI -- convert 2 x F32 in mem/low half xmm to 2 x
9286       I32 in mmx, rounding towards zero */
9287    if (haveNo66noF2noF3(pfx) && sz == 4 
9288        && insn[0] == 0x0F && (insn[1] == 0x2D || insn[1] == 0x2C)) {
9289       IRTemp dst64  = newTemp(Ity_I64);
9290       IRTemp rmode  = newTemp(Ity_I32);
9291       IRTemp f32lo  = newTemp(Ity_F32);
9292       IRTemp f32hi  = newTemp(Ity_F32);
9293       Bool   r2zero = toBool(insn[1] == 0x2C);
9294
9295       do_MMX_preamble();
9296       modrm = getUChar(delta+2);
9297
9298       if (epartIsReg(modrm)) {
9299          delta += 2+1;
9300          assign(f32lo, getXMMRegLane32F(eregOfRexRM(pfx,modrm), 0));
9301          assign(f32hi, getXMMRegLane32F(eregOfRexRM(pfx,modrm), 1));
9302          DIP("cvt%sps2pi %s,%s\n", r2zero ? "t" : "",
9303                                    nameXMMReg(eregOfRexRM(pfx,modrm)),
9304                                    nameMMXReg(gregLO3ofRM(modrm)));
9305       } else {
9306          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
9307          assign(f32lo, loadLE(Ity_F32, mkexpr(addr)));
9308          assign(f32hi, loadLE(Ity_F32, binop( Iop_Add64, 
9309                                               mkexpr(addr), 
9310                                               mkU64(4) )));
9311          delta += 2+alen;
9312          DIP("cvt%sps2pi %s,%s\n", r2zero ? "t" : "",
9313                                    dis_buf,
9314                                    nameMMXReg(gregLO3ofRM(modrm)));
9315       }
9316
9317       if (r2zero) {
9318          assign(rmode, mkU32((UInt)Irrm_ZERO) );
9319       } else {
9320          assign( rmode, get_sse_roundingmode() );
9321       }
9322
9323       assign( 
9324          dst64,
9325          binop( Iop_32HLto64,
9326                 binop( Iop_F64toI32S, 
9327                        mkexpr(rmode), 
9328                        unop( Iop_F32toF64, mkexpr(f32hi) ) ),
9329                 binop( Iop_F64toI32S, 
9330                        mkexpr(rmode), 
9331                        unop( Iop_F32toF64, mkexpr(f32lo) ) )
9332               )
9333       );
9334
9335       putMMXReg(gregLO3ofRM(modrm), mkexpr(dst64));
9336       goto decode_success;
9337    }
9338
9339    /* F3 0F 2D = CVTSS2SI 
9340       when sz==4 -- convert F32 in mem/low quarter xmm to I32 in ireg, 
9341                     according to prevailing SSE rounding mode
9342       when sz==8 -- convert F32 in mem/low quarter xmm to I64 in ireg, 
9343                     according to prevailing SSE rounding mode
9344    */
9345    /* F3 0F 2C = CVTTSS2SI 
9346       when sz==4 -- convert F32 in mem/low quarter xmm to I32 in ireg, 
9347                     truncating towards zero
9348       when sz==8 -- convert F32 in mem/low quarter xmm to I64 in ireg, 
9349                     truncating towards zero 
9350    */
9351    if (haveF3no66noF2(pfx) 
9352        && insn[0] == 0x0F 
9353        && (insn[1] == 0x2D || insn[1] == 0x2C)) {
9354       IRTemp rmode  = newTemp(Ity_I32);
9355       IRTemp f32lo  = newTemp(Ity_F32);
9356       Bool   r2zero = toBool(insn[1] == 0x2C);
9357       vassert(sz == 4 || sz == 8);
9358
9359       modrm = getUChar(delta+2);
9360       if (epartIsReg(modrm)) {
9361          delta += 2+1;
9362          assign(f32lo, getXMMRegLane32F(eregOfRexRM(pfx,modrm), 0));
9363          DIP("cvt%sss2si %s,%s\n", r2zero ? "t" : "",
9364                                    nameXMMReg(eregOfRexRM(pfx,modrm)),
9365                                    nameIReg(sz, gregOfRexRM(pfx,modrm), False));
9366       } else {
9367          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
9368          assign(f32lo, loadLE(Ity_F32, mkexpr(addr)));
9369          delta += 2+alen;
9370          DIP("cvt%sss2si %s,%s\n", r2zero ? "t" : "",
9371                                    dis_buf,
9372                                    nameIReg(sz, gregOfRexRM(pfx,modrm), False));
9373       }
9374
9375       if (r2zero) {
9376          assign( rmode, mkU32((UInt)Irrm_ZERO) );
9377       } else {
9378          assign( rmode, get_sse_roundingmode() );
9379       }
9380
9381       if (sz == 4) {
9382          putIReg32( gregOfRexRM(pfx,modrm),
9383                     binop( Iop_F64toI32S, 
9384                            mkexpr(rmode), 
9385                            unop(Iop_F32toF64, mkexpr(f32lo))) );
9386       } else {
9387          putIReg64( gregOfRexRM(pfx,modrm),
9388                     binop( Iop_F64toI64S, 
9389                            mkexpr(rmode), 
9390                            unop(Iop_F32toF64, mkexpr(f32lo))) );
9391       }
9392
9393       goto decode_success;
9394    }
9395
9396    /* 0F 5E = DIVPS -- div 32Fx4 from R/M to R */
9397    if (haveNo66noF2noF3(pfx) && sz == 4 
9398        && insn[0] == 0x0F && insn[1] == 0x5E) {
9399       delta = dis_SSE_E_to_G_all( vbi, pfx, delta+2, "divps", Iop_Div32Fx4 );
9400       goto decode_success;
9401    }
9402
9403    /* F3 0F 5E = DIVSS -- div 32F0x4 from R/M to R */
9404    if (haveF3no66noF2(pfx) && sz == 4
9405        && insn[0] == 0x0F && insn[1] == 0x5E) {
9406       delta = dis_SSE_E_to_G_lo32( vbi, pfx, delta+2, "divss", Iop_Div32F0x4 );
9407       goto decode_success;
9408    }
9409
9410    /* 0F AE /2 = LDMXCSR m32 -- load %mxcsr */
9411    if (insn[0] == 0x0F && insn[1] == 0xAE
9412        && haveNo66noF2noF3(pfx)
9413        && !epartIsReg(insn[2]) && gregLO3ofRM(insn[2]) == 2) {
9414
9415       IRTemp t64 = newTemp(Ity_I64);
9416       IRTemp ew = newTemp(Ity_I32);
9417
9418       vassert(sz == 4);
9419       addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
9420       delta += 2+alen;
9421       DIP("ldmxcsr %s\n", dis_buf);
9422
9423       /* The only thing we observe in %mxcsr is the rounding mode.
9424          Therefore, pass the 32-bit value (SSE native-format control
9425          word) to a clean helper, getting back a 64-bit value, the
9426          lower half of which is the SSEROUND value to store, and the
9427          upper half of which is the emulation-warning token which may
9428          be generated.  
9429       */
9430       /* ULong amd64h_check_ldmxcsr ( ULong ); */
9431       assign( t64, mkIRExprCCall(
9432                       Ity_I64, 0/*regparms*/, 
9433                       "amd64g_check_ldmxcsr",
9434                       &amd64g_check_ldmxcsr, 
9435                       mkIRExprVec_1( 
9436                          unop(Iop_32Uto64,
9437                               loadLE(Ity_I32, mkexpr(addr))
9438                          )
9439                       )
9440                    )
9441             );
9442
9443       put_sse_roundingmode( unop(Iop_64to32, mkexpr(t64)) );
9444       assign( ew, unop(Iop_64HIto32, mkexpr(t64) ) );
9445       put_emwarn( mkexpr(ew) );
9446       /* Finally, if an emulation warning was reported, side-exit to
9447          the next insn, reporting the warning, so that Valgrind's
9448          dispatcher sees the warning. */
9449       stmt( 
9450          IRStmt_Exit(
9451             binop(Iop_CmpNE64, unop(Iop_32Uto64,mkexpr(ew)), mkU64(0)),
9452             Ijk_EmWarn,
9453             IRConst_U64(guest_RIP_bbstart+delta)
9454          )
9455       );
9456       goto decode_success;
9457    }
9458
9459    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
9460    /* 0F F7 = MASKMOVQ -- 8x8 masked store */
9461    if (haveNo66noF2noF3(pfx) && sz == 4 
9462        && insn[0] == 0x0F && insn[1] == 0xF7) {
9463       Bool ok = False;
9464       delta = dis_MMX( &ok, vbi, pfx, sz, delta+1 );
9465       if (!ok)
9466          goto decode_failure;
9467       goto decode_success;
9468    }
9469
9470    /* 0F 5F = MAXPS -- max 32Fx4 from R/M to R */
9471    if (haveNo66noF2noF3(pfx) && sz == 4 
9472        && insn[0] == 0x0F && insn[1] == 0x5F) {
9473       delta = dis_SSE_E_to_G_all( vbi, pfx, delta+2, "maxps", Iop_Max32Fx4 );
9474       goto decode_success;
9475    }
9476
9477    /* F3 0F 5F = MAXSS -- max 32F0x4 from R/M to R */
9478    if (haveF3no66noF2(pfx) && sz == 4
9479        && insn[0] == 0x0F && insn[1] == 0x5F) {
9480       delta = dis_SSE_E_to_G_lo32( vbi, pfx, delta+2, "maxss", Iop_Max32F0x4 );
9481       goto decode_success;
9482    }
9483
9484    /* 0F 5D = MINPS -- min 32Fx4 from R/M to R */
9485    if (haveNo66noF2noF3(pfx) && sz == 4 
9486        && insn[0] == 0x0F && insn[1] == 0x5D) {
9487       delta = dis_SSE_E_to_G_all( vbi, pfx, delta+2, "minps", Iop_Min32Fx4 );
9488       goto decode_success;
9489    }
9490
9491    /* F3 0F 5D = MINSS -- min 32F0x4 from R/M to R */
9492    if (haveF3no66noF2(pfx) && sz == 4
9493        && insn[0] == 0x0F && insn[1] == 0x5D) {
9494       delta = dis_SSE_E_to_G_lo32( vbi, pfx, delta+2, "minss", Iop_Min32F0x4 );
9495       goto decode_success;
9496    }
9497
9498    /* 0F 28 = MOVAPS -- move from E (mem or xmm) to G (xmm). */
9499    /* 0F 10 = MOVUPS -- move from E (mem or xmm) to G (xmm). */
9500    if (haveNo66noF2noF3(pfx) 
9501        && (sz == 4 || /* ignore redundant REX.W */ sz == 8)
9502        && insn[0] == 0x0F && (insn[1] == 0x28 || insn[1] == 0x10)) {
9503       modrm = getUChar(delta+2);
9504       if (epartIsReg(modrm)) {
9505          putXMMReg( gregOfRexRM(pfx,modrm), 
9506                     getXMMReg( eregOfRexRM(pfx,modrm) ));
9507          DIP("mov[ua]ps %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)),
9508                                   nameXMMReg(gregOfRexRM(pfx,modrm)));
9509          delta += 2+1;
9510       } else {
9511          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
9512          putXMMReg( gregOfRexRM(pfx,modrm), 
9513                     loadLE(Ity_V128, mkexpr(addr)) );
9514          DIP("mov[ua]ps %s,%s\n", dis_buf,
9515                                   nameXMMReg(gregOfRexRM(pfx,modrm)));
9516          delta += 2+alen;
9517       }
9518       goto decode_success;
9519    }
9520
9521    /* 0F 29 = MOVAPS -- move from G (xmm) to E (mem or xmm). */
9522    /* 0F 11 = MOVUPS -- move from G (xmm) to E (mem or xmm). */
9523    if (haveNo66noF2noF3(pfx)
9524        && (sz == 4 || /* ignore redundant REX.W */ sz == 8)
9525        && insn[0] == 0x0F && (insn[1] == 0x29 || insn[1] == 0x11)) {
9526       modrm = getUChar(delta+2);
9527       if (epartIsReg(modrm)) {
9528          /* fall through; awaiting test case */
9529       } else {
9530          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
9531          storeLE( mkexpr(addr), getXMMReg(gregOfRexRM(pfx,modrm)) );
9532          DIP("mov[ua]ps %s,%s\n", nameXMMReg(gregOfRexRM(pfx,modrm)),
9533                                   dis_buf );
9534          delta += 2+alen;
9535          goto decode_success;
9536       }
9537    }
9538
9539    /* 0F 16 = MOVHPS -- move from mem to high half of XMM. */
9540    /* 0F 16 = MOVLHPS -- move from lo half to hi half of XMM. */
9541    if (haveNo66noF2noF3(pfx)
9542        && (sz == 4 || /* ignore redundant REX.W */ sz == 8)
9543        && insn[0] == 0x0F && insn[1] == 0x16) {
9544       modrm = getUChar(delta+2);
9545       if (epartIsReg(modrm)) {
9546          delta += 2+1;
9547          putXMMRegLane64( gregOfRexRM(pfx,modrm), 1/*upper lane*/,
9548                           getXMMRegLane64( eregOfRexRM(pfx,modrm), 0 ) );
9549          DIP("movhps %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)), 
9550                                nameXMMReg(gregOfRexRM(pfx,modrm)));
9551       } else {
9552          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
9553          delta += 2+alen;
9554          putXMMRegLane64( gregOfRexRM(pfx,modrm), 1/*upper lane*/,
9555                           loadLE(Ity_I64, mkexpr(addr)) );
9556          DIP("movhps %s,%s\n", dis_buf, 
9557                                nameXMMReg( gregOfRexRM(pfx,modrm) ));
9558       }
9559       goto decode_success;
9560    }
9561
9562    /* 0F 17 = MOVHPS -- move from high half of XMM to mem. */
9563    if (haveNo66noF2noF3(pfx)
9564        && (sz == 4 || /* ignore redundant REX.W */ sz == 8)
9565        && insn[0] == 0x0F && insn[1] == 0x17) {
9566       if (!epartIsReg(insn[2])) {
9567          delta += 2;
9568          addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
9569          delta += alen;
9570          storeLE( mkexpr(addr), 
9571                   getXMMRegLane64( gregOfRexRM(pfx,insn[2]),
9572                                    1/*upper lane*/ ) );
9573          DIP("movhps %s,%s\n", nameXMMReg( gregOfRexRM(pfx,insn[2]) ),
9574                                dis_buf);
9575          goto decode_success;
9576       }
9577       /* else fall through */
9578    }
9579
9580    /* 0F 12 = MOVLPS -- move from mem to low half of XMM. */
9581    /* OF 12 = MOVHLPS -- from from hi half to lo half of XMM. */
9582    if (haveNo66noF2noF3(pfx)
9583        && (sz == 4 || /* ignore redundant REX.W */ sz == 8)
9584        && insn[0] == 0x0F && insn[1] == 0x12) {
9585       modrm = getUChar(delta+2);
9586       if (epartIsReg(modrm)) {
9587          delta += 2+1;
9588          putXMMRegLane64( gregOfRexRM(pfx,modrm),  
9589                           0/*lower lane*/,
9590                           getXMMRegLane64( eregOfRexRM(pfx,modrm), 1 ));
9591          DIP("movhlps %s, %s\n", nameXMMReg(eregOfRexRM(pfx,modrm)), 
9592                                  nameXMMReg(gregOfRexRM(pfx,modrm)));
9593       } else {
9594          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
9595          delta += 2+alen;
9596          putXMMRegLane64( gregOfRexRM(pfx,modrm),  0/*lower lane*/,
9597                           loadLE(Ity_I64, mkexpr(addr)) );
9598          DIP("movlps %s, %s\n", 
9599              dis_buf, nameXMMReg( gregOfRexRM(pfx,modrm) ));
9600       }
9601       goto decode_success;
9602    }
9603
9604    /* 0F 13 = MOVLPS -- move from low half of XMM to mem. */
9605    if (haveNo66noF2noF3(pfx)
9606        && (sz == 4 || /* ignore redundant REX.W */ sz == 8)
9607        && insn[0] == 0x0F && insn[1] == 0x13) {
9608       if (!epartIsReg(insn[2])) {
9609          delta += 2;
9610          addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
9611          delta += alen;
9612          storeLE( mkexpr(addr), 
9613                   getXMMRegLane64( gregOfRexRM(pfx,insn[2]), 
9614                                    0/*lower lane*/ ) );
9615          DIP("movlps %s, %s\n", nameXMMReg( gregOfRexRM(pfx,insn[2]) ),
9616                                 dis_buf);
9617          goto decode_success;
9618       }
9619       /* else fall through */
9620    }
9621
9622    /* 0F 50 = MOVMSKPS - move 4 sign bits from 4 x F32 in xmm(E)
9623       to 4 lowest bits of ireg(G) */
9624    if (haveNo66noF2noF3(pfx) && (sz == 4 || sz == 8)
9625        && insn[0] == 0x0F && insn[1] == 0x50) {
9626       /* sz == 8 is a kludge to handle insns with REX.W redundantly
9627          set to 1, which has been known to happen:
9628
9629          4c 0f 50 d9             rex64X movmskps %xmm1,%r11d
9630
9631          20071106: Intel docs say that REX.W isn't redundant: when
9632          present, a 64-bit register is written; when not present, only
9633          the 32-bit half is written.  However, testing on a Core2
9634          machine suggests the entire 64 bit register is written
9635          irrespective of the status of REX.W.  That could be because
9636          of the default rule that says "if the lower half of a 32-bit
9637          register is written, the upper half is zeroed".  By using
9638          putIReg32 here we inadvertantly produce the same behaviour as
9639          the Core2, for the same reason -- putIReg32 implements said
9640          rule.
9641
9642          AMD docs give no indication that REX.W is even valid for this
9643          insn. */
9644       modrm = getUChar(delta+2);
9645       if (epartIsReg(modrm)) {
9646          Int src;
9647          t0 = newTemp(Ity_I32);
9648          t1 = newTemp(Ity_I32);
9649          t2 = newTemp(Ity_I32);
9650          t3 = newTemp(Ity_I32);
9651          delta += 2+1;
9652          src = eregOfRexRM(pfx,modrm);
9653          assign( t0, binop( Iop_And32,
9654                             binop(Iop_Shr32, getXMMRegLane32(src,0), mkU8(31)),
9655                             mkU32(1) ));
9656          assign( t1, binop( Iop_And32,
9657                             binop(Iop_Shr32, getXMMRegLane32(src,1), mkU8(30)),
9658                             mkU32(2) ));
9659          assign( t2, binop( Iop_And32,
9660                             binop(Iop_Shr32, getXMMRegLane32(src,2), mkU8(29)),
9661                             mkU32(4) ));
9662          assign( t3, binop( Iop_And32,
9663                             binop(Iop_Shr32, getXMMRegLane32(src,3), mkU8(28)),
9664                             mkU32(8) ));
9665          putIReg32( gregOfRexRM(pfx,modrm),
9666                     binop(Iop_Or32,
9667                           binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
9668                           binop(Iop_Or32, mkexpr(t2), mkexpr(t3))
9669                          )
9670                  );
9671          DIP("movmskps %s,%s\n", nameXMMReg(src), 
9672                                  nameIReg32(gregOfRexRM(pfx,modrm)));
9673          goto decode_success;
9674       }
9675       /* else fall through */
9676    }
9677
9678    /* 66 0F 2B = MOVNTPD -- for us, just a plain SSE store. */
9679    /* 0F 2B = MOVNTPS -- for us, just a plain SSE store. */
9680    if ( ( (haveNo66noF2noF3(pfx) && sz == 4)
9681           || (have66noF2noF3(pfx) && sz == 2) 
9682         )
9683         && insn[0] == 0x0F && insn[1] == 0x2B) {
9684       modrm = getUChar(delta+2);
9685       if (!epartIsReg(modrm)) {
9686          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
9687          storeLE( mkexpr(addr), getXMMReg(gregOfRexRM(pfx,modrm)) );
9688          DIP("movntp%s %s,%s\n", sz==2 ? "d" : "s",
9689                                  dis_buf,
9690                                  nameXMMReg(gregOfRexRM(pfx,modrm)));
9691          delta += 2+alen;
9692          goto decode_success;
9693       }
9694       /* else fall through */
9695    }
9696
9697    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
9698    /* 0F E7 = MOVNTQ -- for us, just a plain MMX store.  Note, the
9699       Intel manual does not say anything about the usual business of
9700       the FP reg tags getting trashed whenever an MMX insn happens.
9701       So we just leave them alone. 
9702    */
9703    if (haveNo66noF2noF3(pfx) && sz == 4 
9704        && insn[0] == 0x0F && insn[1] == 0xE7) {
9705       modrm = getUChar(delta+2);
9706       if (!epartIsReg(modrm)) {
9707          /* do_MMX_preamble(); Intel docs don't specify this */
9708          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
9709          storeLE( mkexpr(addr), getMMXReg(gregLO3ofRM(modrm)) );
9710          DIP("movntq %s,%s\n", dis_buf,
9711                                nameMMXReg(gregLO3ofRM(modrm)));
9712          delta += 2+alen;
9713          goto decode_success;
9714       }
9715       /* else fall through */
9716    }
9717
9718    /* F3 0F 10 = MOVSS -- move 32 bits from E (mem or lo 1/4 xmm) to G
9719       (lo 1/4 xmm).  If E is mem, upper 3/4 of G is zeroed out. */
9720    if (haveF3no66noF2(pfx) 
9721        && (sz == 4 || /* ignore redundant REX.W */ sz == 8)
9722        && insn[0] == 0x0F && insn[1] == 0x10) {
9723       modrm = getUChar(delta+2);
9724       if (epartIsReg(modrm)) {
9725          putXMMRegLane32( gregOfRexRM(pfx,modrm), 0,
9726                           getXMMRegLane32( eregOfRexRM(pfx,modrm), 0 ));
9727          DIP("movss %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)),
9728                               nameXMMReg(gregOfRexRM(pfx,modrm)));
9729          delta += 2+1;
9730       } else {
9731          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
9732          putXMMReg( gregOfRexRM(pfx,modrm), mkV128(0) );
9733          putXMMRegLane32( gregOfRexRM(pfx,modrm), 0,
9734                           loadLE(Ity_I32, mkexpr(addr)) );
9735          DIP("movss %s,%s\n", dis_buf,
9736                               nameXMMReg(gregOfRexRM(pfx,modrm)));
9737          delta += 2+alen;
9738       }
9739       goto decode_success;
9740    }
9741
9742    /* F3 0F 11 = MOVSS -- move 32 bits from G (lo 1/4 xmm) to E (mem
9743       or lo 1/4 xmm). */
9744    if (haveF3no66noF2(pfx) && sz == 4
9745        && insn[0] == 0x0F && insn[1] == 0x11) {
9746       modrm = getUChar(delta+2);
9747       if (epartIsReg(modrm)) {
9748          /* fall through, we don't yet have a test case */
9749       } else {
9750          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
9751          storeLE( mkexpr(addr),
9752                   getXMMRegLane32(gregOfRexRM(pfx,modrm), 0) );
9753          DIP("movss %s,%s\n", nameXMMReg(gregOfRexRM(pfx,modrm)),
9754                               dis_buf);
9755          delta += 2+alen;
9756          goto decode_success;
9757       }
9758    }
9759
9760    /* 0F 59 = MULPS -- mul 32Fx4 from R/M to R */
9761    if (haveNo66noF2noF3(pfx) && sz == 4 
9762        && insn[0] == 0x0F && insn[1] == 0x59) {
9763       delta = dis_SSE_E_to_G_all( vbi, pfx, delta+2, "mulps", Iop_Mul32Fx4 );
9764       goto decode_success;
9765    }
9766
9767    /* F3 0F 59 = MULSS -- mul 32F0x4 from R/M to R */
9768    if (haveF3no66noF2(pfx) && sz == 4
9769        && insn[0] == 0x0F && insn[1] == 0x59) {
9770       delta = dis_SSE_E_to_G_lo32( vbi, pfx, delta+2, "mulss", Iop_Mul32F0x4 );
9771       goto decode_success;
9772    }
9773
9774    /* 0F 56 = ORPS -- G = G and E */
9775    if (haveNo66noF2noF3(pfx) && sz == 4
9776        && insn[0] == 0x0F && insn[1] == 0x56) {
9777       delta = dis_SSE_E_to_G_all( vbi, pfx, delta+2, "orps", Iop_OrV128 );
9778       goto decode_success;
9779    }
9780
9781    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
9782    /* 0F E0 = PAVGB -- 8x8 unsigned Packed Average, with rounding */
9783    if (haveNo66noF2noF3(pfx) && sz == 4 
9784        && insn[0] == 0x0F && insn[1] == 0xE0) {
9785       do_MMX_preamble();
9786       delta = dis_MMXop_regmem_to_reg ( 
9787                  vbi, pfx, delta+2, insn[1], "pavgb", False );
9788       goto decode_success;
9789    }
9790
9791    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
9792    /* 0F E3 = PAVGW -- 16x4 unsigned Packed Average, with rounding */
9793    if (haveNo66noF2noF3(pfx) && sz == 4 
9794        && insn[0] == 0x0F && insn[1] == 0xE3) {
9795       do_MMX_preamble();
9796       delta = dis_MMXop_regmem_to_reg ( 
9797                  vbi, pfx, delta+2, insn[1], "pavgw", False );
9798       goto decode_success;
9799    }
9800
9801    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
9802    /* 0F C5 = PEXTRW -- extract 16-bit field from mmx(E) and put 
9803       zero-extend of it in ireg(G). */
9804    if (haveNo66noF2noF3(pfx) && (sz == 4 || sz == 8)
9805        && insn[0] == 0x0F && insn[1] == 0xC5) {
9806       modrm = insn[2];
9807       if (epartIsReg(modrm)) {
9808          IRTemp sV = newTemp(Ity_I64);
9809          t5 = newTemp(Ity_I16);
9810          do_MMX_preamble();
9811          assign(sV, getMMXReg(eregLO3ofRM(modrm)));
9812          breakup64to16s( sV, &t3, &t2, &t1, &t0 );
9813          switch (insn[3] & 3) {
9814             case 0:  assign(t5, mkexpr(t0)); break;
9815             case 1:  assign(t5, mkexpr(t1)); break;
9816             case 2:  assign(t5, mkexpr(t2)); break;
9817             case 3:  assign(t5, mkexpr(t3)); break;
9818             default: vassert(0);
9819          }
9820          if (sz == 8)
9821             putIReg64(gregOfRexRM(pfx,modrm), unop(Iop_16Uto64, mkexpr(t5)));
9822          else
9823             putIReg32(gregOfRexRM(pfx,modrm), unop(Iop_16Uto32, mkexpr(t5)));
9824          DIP("pextrw $%d,%s,%s\n",
9825              (Int)insn[3], nameMMXReg(eregLO3ofRM(modrm)),
9826                            sz==8 ? nameIReg64(gregOfRexRM(pfx,modrm))
9827                                  : nameIReg32(gregOfRexRM(pfx,modrm))
9828          );
9829          delta += 4;
9830          goto decode_success;
9831       } 
9832       /* else fall through */
9833       /* note, for anyone filling in the mem case: this insn has one
9834          byte after the amode and therefore you must pass 1 as the
9835          last arg to disAMode */
9836    }
9837
9838    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
9839    /* 0F C4 = PINSRW -- get 16 bits from E(mem or low half ireg) and
9840       put it into the specified lane of mmx(G). */
9841    if (haveNo66noF2noF3(pfx) && sz == 4 
9842        && insn[0] == 0x0F && insn[1] == 0xC4) {
9843       /* Use t0 .. t3 to hold the 4 original 16-bit lanes of the
9844          mmx reg.  t4 is the new lane value.  t5 is the original
9845          mmx value. t6 is the new mmx value. */
9846       Int lane;
9847       t4 = newTemp(Ity_I16);
9848       t5 = newTemp(Ity_I64);
9849       t6 = newTemp(Ity_I64);
9850       modrm = insn[2];
9851       do_MMX_preamble();
9852
9853       assign(t5, getMMXReg(gregLO3ofRM(modrm)));
9854       breakup64to16s( t5, &t3, &t2, &t1, &t0 );
9855
9856       if (epartIsReg(modrm)) {
9857          assign(t4, getIReg16(eregOfRexRM(pfx,modrm)));
9858          delta += 3+1;
9859          lane = insn[3+1-1];
9860          DIP("pinsrw $%d,%s,%s\n", (Int)lane, 
9861                                    nameIReg16(eregOfRexRM(pfx,modrm)),
9862                                    nameMMXReg(gregLO3ofRM(modrm)));
9863       } else {
9864          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 1 );
9865          delta += 3+alen;
9866          lane = insn[3+alen-1];
9867          assign(t4, loadLE(Ity_I16, mkexpr(addr)));
9868          DIP("pinsrw $%d,%s,%s\n", (Int)lane,
9869                                    dis_buf,
9870                                    nameMMXReg(gregLO3ofRM(modrm)));
9871       }
9872
9873       switch (lane & 3) {
9874          case 0:  assign(t6, mk64from16s(t3,t2,t1,t4)); break;
9875          case 1:  assign(t6, mk64from16s(t3,t2,t4,t0)); break;
9876          case 2:  assign(t6, mk64from16s(t3,t4,t1,t0)); break;
9877          case 3:  assign(t6, mk64from16s(t4,t2,t1,t0)); break;
9878          default: vassert(0);
9879       }
9880       putMMXReg(gregLO3ofRM(modrm), mkexpr(t6));
9881       goto decode_success;
9882    }
9883
9884    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
9885    /* 0F EE = PMAXSW -- 16x4 signed max */
9886    if (haveNo66noF2noF3(pfx) && sz == 4 
9887        && insn[0] == 0x0F && insn[1] == 0xEE) {
9888       do_MMX_preamble();
9889       delta = dis_MMXop_regmem_to_reg ( 
9890                  vbi, pfx, delta+2, insn[1], "pmaxsw", False );
9891       goto decode_success;
9892    }
9893
9894    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
9895    /* 0F DE = PMAXUB -- 8x8 unsigned max */
9896    if (haveNo66noF2noF3(pfx) && sz == 4 
9897        && insn[0] == 0x0F && insn[1] == 0xDE) {
9898       do_MMX_preamble();
9899       delta = dis_MMXop_regmem_to_reg ( 
9900                  vbi, pfx, delta+2, insn[1], "pmaxub", False );
9901       goto decode_success;
9902    }
9903
9904    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
9905    /* 0F EA = PMINSW -- 16x4 signed min */
9906    if (haveNo66noF2noF3(pfx) && sz == 4 
9907        && insn[0] == 0x0F && insn[1] == 0xEA) {
9908       do_MMX_preamble();
9909       delta = dis_MMXop_regmem_to_reg ( 
9910                  vbi, pfx, delta+2, insn[1], "pminsw", False );
9911       goto decode_success;
9912    }
9913
9914    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
9915    /* 0F DA = PMINUB -- 8x8 unsigned min */
9916    if (haveNo66noF2noF3(pfx) && sz == 4 
9917        && insn[0] == 0x0F && insn[1] == 0xDA) {
9918       do_MMX_preamble();
9919       delta = dis_MMXop_regmem_to_reg ( 
9920                  vbi, pfx, delta+2, insn[1], "pminub", False );
9921       goto decode_success;
9922    }
9923
9924    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
9925    /* 0F D7 = PMOVMSKB -- extract sign bits from each of 8 lanes in
9926       mmx(G), turn them into a byte, and put zero-extend of it in
9927       ireg(G). */
9928    if (haveNo66noF2noF3(pfx) && sz == 4 
9929        && insn[0] == 0x0F && insn[1] == 0xD7) {
9930       modrm = insn[2];
9931       if (epartIsReg(modrm)) {
9932          do_MMX_preamble();
9933          t0 = newTemp(Ity_I64);
9934          t1 = newTemp(Ity_I64);
9935          assign(t0, getMMXReg(eregLO3ofRM(modrm)));
9936          assign(t1, mkIRExprCCall(
9937                        Ity_I64, 0/*regparms*/, 
9938                        "amd64g_calculate_mmx_pmovmskb",
9939                        &amd64g_calculate_mmx_pmovmskb,
9940                        mkIRExprVec_1(mkexpr(t0))));
9941          putIReg32(gregOfRexRM(pfx,modrm), unop(Iop_64to32,mkexpr(t1)));
9942          DIP("pmovmskb %s,%s\n", nameMMXReg(eregLO3ofRM(modrm)),
9943                                  nameIReg32(gregOfRexRM(pfx,modrm)));
9944          delta += 3;
9945          goto decode_success;
9946       } 
9947       /* else fall through */
9948    }
9949
9950    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
9951    /* 0F E4 = PMULUH -- 16x4 hi-half of unsigned widening multiply */
9952    if (haveNo66noF2noF3(pfx) && sz == 4 
9953        && insn[0] == 0x0F && insn[1] == 0xE4) {
9954       do_MMX_preamble();
9955       delta = dis_MMXop_regmem_to_reg ( 
9956                  vbi, pfx, delta+2, insn[1], "pmuluh", False );
9957       goto decode_success;
9958    }
9959
9960    /* 0F 18 /0 = PREFETCHNTA -- prefetch into caches, */
9961    /* 0F 18 /1 = PREFETCH0   -- with various different hints */
9962    /* 0F 18 /2 = PREFETCH1 */
9963    /* 0F 18 /3 = PREFETCH2 */
9964    if (insn[0] == 0x0F && insn[1] == 0x18
9965        && haveNo66noF2noF3(pfx)
9966        && !epartIsReg(insn[2]) 
9967        && gregLO3ofRM(insn[2]) >= 0 && gregLO3ofRM(insn[2]) <= 3) {
9968       HChar* hintstr = "??";
9969
9970       modrm = getUChar(delta+2);
9971       vassert(!epartIsReg(modrm));
9972
9973       addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
9974       delta += 2+alen;
9975
9976       switch (gregLO3ofRM(modrm)) {
9977          case 0: hintstr = "nta"; break;
9978          case 1: hintstr = "t0"; break;
9979          case 2: hintstr = "t1"; break;
9980          case 3: hintstr = "t2"; break;
9981          default: vassert(0);
9982       }
9983
9984       DIP("prefetch%s %s\n", hintstr, dis_buf);
9985       goto decode_success;
9986    }
9987
9988    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
9989    /* 0F F6 = PSADBW -- sum of 8Ux8 absolute differences */
9990    if (haveNo66noF2noF3(pfx) && sz == 4 
9991        && insn[0] == 0x0F && insn[1] == 0xF6) {
9992       do_MMX_preamble();
9993       delta = dis_MMXop_regmem_to_reg ( 
9994                  vbi, pfx, delta+2, insn[1], "psadbw", False );
9995       goto decode_success;
9996    }
9997
9998    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
9999    /* 0F 70 = PSHUFW -- rearrange 4x16 from E(mmx or mem) to G(mmx) */
10000    if (haveNo66noF2noF3(pfx) && sz == 4 
10001        && insn[0] == 0x0F && insn[1] == 0x70) {
10002       Int order;
10003       IRTemp sV, dV, s3, s2, s1, s0;
10004       s3 = s2 = s1 = s0 = IRTemp_INVALID;
10005       sV = newTemp(Ity_I64);
10006       dV = newTemp(Ity_I64);
10007       do_MMX_preamble();
10008       modrm = insn[2];
10009       if (epartIsReg(modrm)) {
10010          assign( sV, getMMXReg(eregLO3ofRM(modrm)) );
10011          order = (Int)insn[3];
10012          delta += 2+2;
10013          DIP("pshufw $%d,%s,%s\n", order, 
10014                                    nameMMXReg(eregLO3ofRM(modrm)),
10015                                    nameMMXReg(gregLO3ofRM(modrm)));
10016       } else {
10017          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf,
10018                            1/*extra byte after amode*/ );
10019          assign( sV, loadLE(Ity_I64, mkexpr(addr)) );
10020          order = (Int)insn[2+alen];
10021          delta += 3+alen;
10022          DIP("pshufw $%d,%s,%s\n", order, 
10023                                    dis_buf,
10024                                    nameMMXReg(gregLO3ofRM(modrm)));
10025       }
10026       breakup64to16s( sV, &s3, &s2, &s1, &s0 );
10027 #     define SEL(n) \
10028                 ((n)==0 ? s0 : ((n)==1 ? s1 : ((n)==2 ? s2 : s3)))
10029       assign(dV,
10030              mk64from16s( SEL((order>>6)&3), SEL((order>>4)&3),
10031                           SEL((order>>2)&3), SEL((order>>0)&3) )
10032       );
10033       putMMXReg(gregLO3ofRM(modrm), mkexpr(dV));
10034 #     undef SEL
10035       goto decode_success;
10036    }
10037
10038    /* 0F 53 = RCPPS -- approx reciprocal 32Fx4 from R/M to R */
10039    if (haveNo66noF2noF3(pfx) && sz == 4 
10040        && insn[0] == 0x0F && insn[1] == 0x53) {
10041       delta = dis_SSE_E_to_G_unary_all( vbi, pfx, delta+2, 
10042                                         "rcpps", Iop_Recip32Fx4 );
10043       goto decode_success;
10044    }
10045
10046    /* F3 0F 53 = RCPSS -- approx reciprocal 32F0x4 from R/M to R */
10047    if (haveF3no66noF2(pfx) && sz == 4 
10048        && insn[0] == 0x0F && insn[1] == 0x53) {
10049       delta = dis_SSE_E_to_G_unary_lo32( vbi, pfx, delta+2, 
10050                                          "rcpss", Iop_Recip32F0x4 );
10051       goto decode_success;
10052    }
10053
10054    /* 0F 52 = RSQRTPS -- approx reciprocal sqrt 32Fx4 from R/M to R */
10055    if (haveNo66noF2noF3(pfx) && sz == 4 
10056        && insn[0] == 0x0F && insn[1] == 0x52) {
10057       delta = dis_SSE_E_to_G_unary_all( vbi, pfx, delta+2, 
10058                                         "rsqrtps", Iop_RSqrt32Fx4 );
10059       goto decode_success;
10060    }
10061
10062    /* F3 0F 52 = RSQRTSS -- approx reciprocal sqrt 32F0x4 from R/M to R */
10063    if (haveF3no66noF2(pfx) && sz == 4 
10064        && insn[0] == 0x0F && insn[1] == 0x52) {
10065       delta = dis_SSE_E_to_G_unary_lo32( vbi, pfx, delta+2, 
10066                                          "rsqrtss", Iop_RSqrt32F0x4 );
10067       goto decode_success;
10068    }
10069
10070    /* 0F AE /7 = SFENCE -- flush pending operations to memory */
10071    if (haveNo66noF2noF3(pfx) 
10072        && insn[0] == 0x0F && insn[1] == 0xAE
10073        && epartIsReg(insn[2]) && gregLO3ofRM(insn[2]) == 7
10074        && sz == 4) {
10075       delta += 3;
10076       /* Insert a memory fence.  It's sometimes important that these
10077          are carried through to the generated code. */
10078       stmt( IRStmt_MBE(Imbe_Fence) );
10079       DIP("sfence\n");
10080       goto decode_success;
10081    }
10082
10083    /* 0F C6 /r ib = SHUFPS -- shuffle packed F32s */
10084    if (haveNo66noF2noF3(pfx) && sz == 4 
10085        && insn[0] == 0x0F && insn[1] == 0xC6) {
10086       Int    select;
10087       IRTemp sV, dV;
10088       IRTemp s3, s2, s1, s0, d3, d2, d1, d0;
10089       sV = newTemp(Ity_V128);
10090       dV = newTemp(Ity_V128);
10091       s3 = s2 = s1 = s0 = d3 = d2 = d1 = d0 = IRTemp_INVALID;
10092       modrm = insn[2];
10093       assign( dV, getXMMReg(gregOfRexRM(pfx,modrm)) );
10094
10095       if (epartIsReg(modrm)) {
10096          assign( sV, getXMMReg(eregOfRexRM(pfx,modrm)) );
10097          select = (Int)insn[3];
10098          delta += 2+2;
10099          DIP("shufps $%d,%s,%s\n", select, 
10100                                    nameXMMReg(eregOfRexRM(pfx,modrm)),
10101                                    nameXMMReg(gregOfRexRM(pfx,modrm)));
10102       } else {
10103          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 
10104                            1/*byte at end of insn*/ );
10105          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
10106          select = (Int)insn[2+alen];
10107          delta += 3+alen;
10108          DIP("shufps $%d,%s,%s\n", select, 
10109                                    dis_buf,
10110                                    nameXMMReg(gregOfRexRM(pfx,modrm)));
10111       }
10112
10113       breakup128to32s( dV, &d3, &d2, &d1, &d0 );
10114       breakup128to32s( sV, &s3, &s2, &s1, &s0 );
10115
10116 #     define SELD(n) ((n)==0 ? d0 : ((n)==1 ? d1 : ((n)==2 ? d2 : d3)))
10117 #     define SELS(n) ((n)==0 ? s0 : ((n)==1 ? s1 : ((n)==2 ? s2 : s3)))
10118
10119       putXMMReg(
10120          gregOfRexRM(pfx,modrm), 
10121          mk128from32s( SELS((select>>6)&3), SELS((select>>4)&3), 
10122                        SELD((select>>2)&3), SELD((select>>0)&3) )
10123       );
10124
10125 #     undef SELD
10126 #     undef SELS
10127
10128       goto decode_success;
10129    }
10130
10131    /* 0F 51 = SQRTPS -- approx sqrt 32Fx4 from R/M to R */
10132    if (haveNo66noF2noF3(pfx) && sz == 4 
10133        && insn[0] == 0x0F && insn[1] == 0x51) {
10134       delta = dis_SSE_E_to_G_unary_all( vbi, pfx, delta+2, 
10135                                         "sqrtps", Iop_Sqrt32Fx4 );
10136       goto decode_success;
10137    }
10138
10139    /* F3 0F 51 = SQRTSS -- approx sqrt 32F0x4 from R/M to R */
10140    if (haveF3no66noF2(pfx) && sz == 4
10141        && insn[0] == 0x0F && insn[1] == 0x51) {
10142       delta = dis_SSE_E_to_G_unary_lo32( vbi, pfx, delta+2, 
10143                                          "sqrtss", Iop_Sqrt32F0x4 );
10144       goto decode_success;
10145    }
10146
10147    /* 0F AE /3 = STMXCSR m32 -- store %mxcsr */
10148    if (insn[0] == 0x0F && insn[1] == 0xAE
10149        && haveNo66noF2noF3(pfx)
10150        && !epartIsReg(insn[2]) && gregLO3ofRM(insn[2]) == 3) {
10151
10152       vassert(sz == 4);
10153       addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
10154       delta += 2+alen;
10155
10156       /* Fake up a native SSE mxcsr word.  The only thing it depends
10157          on is SSEROUND[1:0], so call a clean helper to cook it up. 
10158       */
10159       /* ULong amd64h_create_mxcsr ( ULong sseround ) */
10160       DIP("stmxcsr %s\n", dis_buf);
10161       storeLE( 
10162          mkexpr(addr), 
10163          unop(Iop_64to32,      
10164               mkIRExprCCall(
10165                  Ity_I64, 0/*regp*/,
10166                  "amd64g_create_mxcsr", &amd64g_create_mxcsr, 
10167                  mkIRExprVec_1( unop(Iop_32Uto64,get_sse_roundingmode()) ) 
10168               ) 
10169          )
10170       );
10171       goto decode_success;
10172    }
10173
10174    /* 0F 5C = SUBPS -- sub 32Fx4 from R/M to R */
10175    if (haveNo66noF2noF3(pfx) && sz == 4 
10176        && insn[0] == 0x0F && insn[1] == 0x5C) {
10177       delta = dis_SSE_E_to_G_all( vbi, pfx, delta+2, "subps", Iop_Sub32Fx4 );
10178       goto decode_success;
10179    }
10180
10181    /* F3 0F 5C = SUBSS -- sub 32F0x4 from R/M to R */
10182    if (haveF3no66noF2(pfx) && sz == 4
10183        && insn[0] == 0x0F && insn[1] == 0x5C) {
10184       delta = dis_SSE_E_to_G_lo32( vbi, pfx, delta+2, "subss", Iop_Sub32F0x4 );
10185       goto decode_success;
10186    }
10187
10188    /* 0F 15 = UNPCKHPS -- unpack and interleave high part F32s */
10189    /* 0F 14 = UNPCKLPS -- unpack and interleave low part F32s */
10190    /* These just appear to be special cases of SHUFPS */
10191    if (haveNo66noF2noF3(pfx) && sz == 4 
10192        && insn[0] == 0x0F && (insn[1] == 0x15 || insn[1] == 0x14)) {
10193       IRTemp sV, dV;
10194       IRTemp s3, s2, s1, s0, d3, d2, d1, d0;
10195       Bool hi = toBool(insn[1] == 0x15);
10196       sV = newTemp(Ity_V128);
10197       dV = newTemp(Ity_V128);
10198       s3 = s2 = s1 = s0 = d3 = d2 = d1 = d0 = IRTemp_INVALID;
10199       modrm = insn[2];
10200       assign( dV, getXMMReg(gregOfRexRM(pfx,modrm)) );
10201
10202       if (epartIsReg(modrm)) {
10203          assign( sV, getXMMReg(eregOfRexRM(pfx,modrm)) );
10204          delta += 2+1;
10205          DIP("unpck%sps %s,%s\n", hi ? "h" : "l",
10206                                   nameXMMReg(eregOfRexRM(pfx,modrm)),
10207                                   nameXMMReg(gregOfRexRM(pfx,modrm)));
10208       } else {
10209          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
10210          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
10211          delta += 2+alen;
10212          DIP("unpck%sps %s,%s\n", hi ? "h" : "l",
10213                                   dis_buf,
10214                                   nameXMMReg(gregOfRexRM(pfx,modrm)));
10215       }
10216
10217       breakup128to32s( dV, &d3, &d2, &d1, &d0 );
10218       breakup128to32s( sV, &s3, &s2, &s1, &s0 );
10219
10220       if (hi) {
10221          putXMMReg( gregOfRexRM(pfx,modrm), mk128from32s( s3, d3, s2, d2 ) );
10222       } else {
10223          putXMMReg( gregOfRexRM(pfx,modrm), mk128from32s( s1, d1, s0, d0 ) );
10224       }
10225
10226       goto decode_success;
10227    }
10228
10229    /* 0F 57 = XORPS -- G = G and E */
10230    if (haveNo66noF2noF3(pfx) && sz == 4 
10231        && insn[0] == 0x0F && insn[1] == 0x57) {
10232       delta = dis_SSE_E_to_G_all( vbi, pfx, delta+2, "xorps", Iop_XorV128 );
10233       goto decode_success;
10234    }
10235
10236    /* ---------------------------------------------------- */
10237    /* --- end of the SSE decoder.                      --- */
10238    /* ---------------------------------------------------- */
10239
10240    /* ---------------------------------------------------- */
10241    /* --- start of the SSE2 decoder.                   --- */
10242    /* ---------------------------------------------------- */
10243
10244    /* 66 0F 58 = ADDPD -- add 32Fx4 from R/M to R */
10245    if (have66noF2noF3(pfx) 
10246        && (sz == 2 || /* ignore redundant REX.W */ sz == 8)
10247        && insn[0] == 0x0F && insn[1] == 0x58) {
10248       delta = dis_SSE_E_to_G_all( vbi, pfx, delta+2, "addpd", Iop_Add64Fx2 );
10249       goto decode_success;
10250    }
10251  
10252    /* F2 0F 58 = ADDSD -- add 64F0x2 from R/M to R */
10253    if (haveF2no66noF3(pfx) 
10254        && (sz == 4 || /* ignore redundant REX.W */ sz == 8)
10255        && insn[0] == 0x0F && insn[1] == 0x58) {
10256       delta = dis_SSE_E_to_G_lo64( vbi, pfx, delta+2, "addsd", Iop_Add64F0x2 );
10257       goto decode_success;
10258    }
10259
10260    /* 66 0F 55 = ANDNPD -- G = (not G) and E */
10261    if (have66noF2noF3(pfx) && sz == 2 
10262        && insn[0] == 0x0F && insn[1] == 0x55) {
10263       delta = dis_SSE_E_to_G_all_invG( vbi, pfx, delta+2, "andnpd", Iop_AndV128 );
10264       goto decode_success;
10265    }
10266
10267    /* 66 0F 54 = ANDPD -- G = G and E */
10268    if (have66noF2noF3(pfx) && sz == 2 
10269        && insn[0] == 0x0F && insn[1] == 0x54) {
10270       delta = dis_SSE_E_to_G_all( vbi, pfx, delta+2, "andpd", Iop_AndV128 );
10271       goto decode_success;
10272    }
10273
10274    /* 66 0F C2 = CMPPD -- 64Fx2 comparison from R/M to R */
10275    if (have66noF2noF3(pfx) && sz == 2 
10276        && insn[0] == 0x0F && insn[1] == 0xC2) {
10277       delta = dis_SSEcmp_E_to_G( vbi, pfx, delta+2, "cmppd", True, 8 );
10278       goto decode_success;
10279    }
10280
10281    /* F2 0F C2 = CMPSD -- 64F0x2 comparison from R/M to R */
10282    if (haveF2no66noF3(pfx) && sz == 4
10283        && insn[0] == 0x0F && insn[1] == 0xC2) {
10284       delta = dis_SSEcmp_E_to_G( vbi, pfx, delta+2, "cmpsd", False, 8 );
10285       goto decode_success;
10286    }
10287
10288    /* 66 0F 2F = COMISD  -- 64F0x2 comparison G,E, and set ZCP */
10289    /* 66 0F 2E = UCOMISD -- 64F0x2 comparison G,E, and set ZCP */
10290    if (have66noF2noF3(pfx) && sz == 2
10291        && insn[0] == 0x0F && (insn[1] == 0x2F || insn[1] == 0x2E)) {
10292       IRTemp argL = newTemp(Ity_F64);
10293       IRTemp argR = newTemp(Ity_F64);
10294       modrm = getUChar(delta+2);
10295       if (epartIsReg(modrm)) {
10296          assign( argR, getXMMRegLane64F( eregOfRexRM(pfx,modrm), 
10297                                          0/*lowest lane*/ ) );
10298          delta += 2+1;
10299          DIP("%scomisd %s,%s\n", insn[1]==0x2E ? "u" : "",
10300                                  nameXMMReg(eregOfRexRM(pfx,modrm)),
10301                                  nameXMMReg(gregOfRexRM(pfx,modrm)) );
10302       } else {
10303          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
10304          assign( argR, loadLE(Ity_F64, mkexpr(addr)) );
10305          delta += 2+alen;
10306          DIP("%scomisd %s,%s\n", insn[1]==0x2E ? "u" : "",
10307                                  dis_buf,
10308                                  nameXMMReg(gregOfRexRM(pfx,modrm)) );
10309       }
10310       assign( argL, getXMMRegLane64F( gregOfRexRM(pfx,modrm), 
10311                                       0/*lowest lane*/ ) );
10312
10313       stmt( IRStmt_Put( OFFB_CC_OP,   mkU64(AMD64G_CC_OP_COPY) ));
10314       stmt( IRStmt_Put( OFFB_CC_DEP2, mkU64(0) ));
10315       stmt( IRStmt_Put( 
10316                OFFB_CC_DEP1,
10317                binop( Iop_And64,
10318                       unop( Iop_32Uto64, 
10319                             binop(Iop_CmpF64, mkexpr(argL), mkexpr(argR)) ),
10320                       mkU64(0x45)
10321           )));
10322
10323       goto decode_success;
10324    }
10325
10326    /* F3 0F E6 = CVTDQ2PD -- convert 2 x I32 in mem/lo half xmm to 2 x
10327       F64 in xmm(G) */
10328    if (haveF3no66noF2(pfx) && insn[0] == 0x0F && insn[1] == 0xE6) {
10329       IRTemp arg64 = newTemp(Ity_I64);
10330       if (sz != 4) goto decode_failure;
10331
10332       modrm = getUChar(delta+2);
10333       if (epartIsReg(modrm)) {
10334          assign( arg64, getXMMRegLane64(eregOfRexRM(pfx,modrm), 0) );
10335          delta += 2+1;
10336          DIP("cvtdq2pd %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)),
10337                                  nameXMMReg(gregOfRexRM(pfx,modrm)));
10338       } else {
10339          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
10340          assign( arg64, loadLE(Ity_I64, mkexpr(addr)) );
10341          delta += 2+alen;
10342          DIP("cvtdq2pd %s,%s\n", dis_buf,
10343                                  nameXMMReg(gregOfRexRM(pfx,modrm)) );
10344       }
10345
10346       putXMMRegLane64F( 
10347          gregOfRexRM(pfx,modrm), 0,
10348          unop(Iop_I32StoF64, unop(Iop_64to32, mkexpr(arg64)))
10349       );
10350
10351       putXMMRegLane64F(
10352          gregOfRexRM(pfx,modrm), 1, 
10353          unop(Iop_I32StoF64, unop(Iop_64HIto32, mkexpr(arg64)))
10354       );
10355
10356       goto decode_success;
10357    }
10358
10359    /* 0F 5B = CVTDQ2PS -- convert 4 x I32 in mem/xmm to 4 x F32 in
10360       xmm(G) */
10361    if (haveNo66noF2noF3(pfx) && sz == 4 
10362        && insn[0] == 0x0F && insn[1] == 0x5B) {
10363       IRTemp argV  = newTemp(Ity_V128);
10364       IRTemp rmode = newTemp(Ity_I32);
10365
10366       modrm = getUChar(delta+2);
10367       if (epartIsReg(modrm)) {
10368          assign( argV, getXMMReg(eregOfRexRM(pfx,modrm)) );
10369          delta += 2+1;
10370          DIP("cvtdq2ps %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)),
10371                                  nameXMMReg(gregOfRexRM(pfx,modrm)));
10372       } else {
10373          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
10374          assign( argV, loadLE(Ity_V128, mkexpr(addr)) );
10375          delta += 2+alen;
10376          DIP("cvtdq2ps %s,%s\n", dis_buf,
10377                                  nameXMMReg(gregOfRexRM(pfx,modrm)) );
10378       }
10379          
10380       assign( rmode, get_sse_roundingmode() );
10381       breakup128to32s( argV, &t3, &t2, &t1, &t0 );
10382
10383 #     define CVT(_t)  binop( Iop_F64toF32,                    \
10384                              mkexpr(rmode),                   \
10385                              unop(Iop_I32StoF64,mkexpr(_t)))
10386       
10387       putXMMRegLane32F( gregOfRexRM(pfx,modrm), 3, CVT(t3) );
10388       putXMMRegLane32F( gregOfRexRM(pfx,modrm), 2, CVT(t2) );
10389       putXMMRegLane32F( gregOfRexRM(pfx,modrm), 1, CVT(t1) );
10390       putXMMRegLane32F( gregOfRexRM(pfx,modrm), 0, CVT(t0) );
10391
10392 #     undef CVT
10393
10394       goto decode_success;
10395    }
10396
10397    /* 66 0F E6 = CVTTPD2DQ -- convert 2 x F64 in mem/xmm to 2 x I32 in
10398       lo half xmm(G), and zero upper half, rounding towards zero */
10399    /* F2 0F E6 = CVTPD2DQ -- convert 2 x F64 in mem/xmm to 2 x I32 in
10400       lo half xmm(G), according to prevailing rounding mode, and zero
10401       upper half */
10402    if ( ( (haveF2no66noF3(pfx) && sz == 4)
10403           || (have66noF2noF3(pfx) && sz == 2)
10404         )
10405         && insn[0] == 0x0F && insn[1] == 0xE6) {
10406       IRTemp argV   = newTemp(Ity_V128);
10407       IRTemp rmode  = newTemp(Ity_I32);
10408       Bool   r2zero = toBool(sz == 2);
10409
10410       modrm = getUChar(delta+2);
10411       if (epartIsReg(modrm)) {
10412          assign( argV, getXMMReg(eregOfRexRM(pfx,modrm)) );
10413          delta += 2+1;
10414          DIP("cvt%spd2dq %s,%s\n", r2zero ? "t" : "",
10415                                    nameXMMReg(eregOfRexRM(pfx,modrm)),
10416                                    nameXMMReg(gregOfRexRM(pfx,modrm)));
10417       } else {
10418          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
10419          assign( argV, loadLE(Ity_V128, mkexpr(addr)) );
10420          delta += 2+alen;
10421          DIP("cvt%spd2dq %s,%s\n", r2zero ? "t" : "",
10422                                    dis_buf,
10423                                    nameXMMReg(gregOfRexRM(pfx,modrm)) );
10424       }
10425          
10426       if (r2zero) {
10427          assign(rmode, mkU32((UInt)Irrm_ZERO) );
10428       } else {
10429          assign( rmode, get_sse_roundingmode() );
10430       }
10431
10432       t0 = newTemp(Ity_F64);
10433       t1 = newTemp(Ity_F64);
10434       assign( t0, unop(Iop_ReinterpI64asF64, 
10435                        unop(Iop_V128to64, mkexpr(argV))) );
10436       assign( t1, unop(Iop_ReinterpI64asF64, 
10437                        unop(Iop_V128HIto64, mkexpr(argV))) );
10438       
10439 #     define CVT(_t)  binop( Iop_F64toI32S,                   \
10440                              mkexpr(rmode),                   \
10441                              mkexpr(_t) )
10442       
10443       putXMMRegLane32( gregOfRexRM(pfx,modrm), 3, mkU32(0) );
10444       putXMMRegLane32( gregOfRexRM(pfx,modrm), 2, mkU32(0) );
10445       putXMMRegLane32( gregOfRexRM(pfx,modrm), 1, CVT(t1) );
10446       putXMMRegLane32( gregOfRexRM(pfx,modrm), 0, CVT(t0) );
10447
10448 #     undef CVT
10449
10450       goto decode_success;
10451    }
10452
10453    /* 66 0F 2D = CVTPD2PI -- convert 2 x F64 in mem/xmm to 2 x
10454       I32 in mmx, according to prevailing SSE rounding mode */
10455    /* 66 0F 2C = CVTTPD2PI -- convert 2 x F64 in mem/xmm to 2 x
10456       I32 in mmx, rounding towards zero */
10457    if (have66noF2noF3(pfx) && sz == 2 
10458        && insn[0] == 0x0F && (insn[1] == 0x2D || insn[1] == 0x2C)) {
10459       IRTemp dst64  = newTemp(Ity_I64);
10460       IRTemp rmode  = newTemp(Ity_I32);
10461       IRTemp f64lo  = newTemp(Ity_F64);
10462       IRTemp f64hi  = newTemp(Ity_F64);
10463       Bool   r2zero = toBool(insn[1] == 0x2C);
10464
10465       do_MMX_preamble();
10466       modrm = getUChar(delta+2);
10467
10468       if (epartIsReg(modrm)) {
10469          delta += 2+1;
10470          assign(f64lo, getXMMRegLane64F(eregOfRexRM(pfx,modrm), 0));
10471          assign(f64hi, getXMMRegLane64F(eregOfRexRM(pfx,modrm), 1));
10472          DIP("cvt%spd2pi %s,%s\n", r2zero ? "t" : "",
10473                                    nameXMMReg(eregOfRexRM(pfx,modrm)),
10474                                    nameMMXReg(gregLO3ofRM(modrm)));
10475       } else {
10476          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
10477          assign(f64lo, loadLE(Ity_F64, mkexpr(addr)));
10478          assign(f64hi, loadLE(Ity_F64, binop( Iop_Add64, 
10479                                               mkexpr(addr), 
10480                                               mkU64(8) )));
10481          delta += 2+alen;
10482          DIP("cvt%spf2pi %s,%s\n", r2zero ? "t" : "",
10483                                    dis_buf,
10484                                    nameMMXReg(gregLO3ofRM(modrm)));
10485       }
10486
10487       if (r2zero) {
10488          assign(rmode, mkU32((UInt)Irrm_ZERO) );
10489       } else {
10490          assign( rmode, get_sse_roundingmode() );
10491       }
10492
10493       assign( 
10494          dst64,
10495          binop( Iop_32HLto64,
10496                 binop( Iop_F64toI32S, mkexpr(rmode), mkexpr(f64hi) ),
10497                 binop( Iop_F64toI32S, mkexpr(rmode), mkexpr(f64lo) )
10498               )
10499       );
10500
10501       putMMXReg(gregLO3ofRM(modrm), mkexpr(dst64));
10502       goto decode_success;
10503    }
10504
10505    /* 66 0F 5A = CVTPD2PS -- convert 2 x F64 in mem/xmm to 2 x F32 in
10506       lo half xmm(G), rounding according to prevailing SSE rounding
10507       mode, and zero upper half */
10508    /* Note, this is practically identical to CVTPD2DQ.  It would have
10509       been nicer to merge them together, but the insn[] offsets differ
10510       by one. */
10511    if (have66noF2noF3(pfx) && sz == 2 
10512        && insn[0] == 0x0F && insn[1] == 0x5A) {
10513       IRTemp argV  = newTemp(Ity_V128);
10514       IRTemp rmode = newTemp(Ity_I32);
10515
10516       modrm = getUChar(delta+2);
10517       if (epartIsReg(modrm)) {
10518          assign( argV, getXMMReg(eregOfRexRM(pfx,modrm)) );
10519          delta += 2+1;
10520          DIP("cvtpd2ps %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)),
10521                                  nameXMMReg(gregOfRexRM(pfx,modrm)));
10522       } else {
10523          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
10524          assign( argV, loadLE(Ity_V128, mkexpr(addr)) );
10525          delta += 2+alen;
10526          DIP("cvtpd2ps %s,%s\n", dis_buf,
10527                                  nameXMMReg(gregOfRexRM(pfx,modrm)) );
10528       }
10529          
10530       assign( rmode, get_sse_roundingmode() );
10531       t0 = newTemp(Ity_F64);
10532       t1 = newTemp(Ity_F64);
10533       assign( t0, unop(Iop_ReinterpI64asF64, 
10534                        unop(Iop_V128to64, mkexpr(argV))) );
10535       assign( t1, unop(Iop_ReinterpI64asF64, 
10536                        unop(Iop_V128HIto64, mkexpr(argV))) );
10537       
10538 #     define CVT(_t)  binop( Iop_F64toF32,                    \
10539                              mkexpr(rmode),                   \
10540                              mkexpr(_t) )
10541       
10542       putXMMRegLane32(  gregOfRexRM(pfx,modrm), 3, mkU32(0) );
10543       putXMMRegLane32(  gregOfRexRM(pfx,modrm), 2, mkU32(0) );
10544       putXMMRegLane32F( gregOfRexRM(pfx,modrm), 1, CVT(t1) );
10545       putXMMRegLane32F( gregOfRexRM(pfx,modrm), 0, CVT(t0) );
10546
10547 #     undef CVT
10548
10549       goto decode_success;
10550    }
10551
10552    /* 66 0F 2A = CVTPI2PD -- convert 2 x I32 in mem/mmx to 2 x F64 in
10553       xmm(G) */
10554    if (have66noF2noF3(pfx) && sz == 2 
10555        && insn[0] == 0x0F && insn[1] == 0x2A) {
10556       IRTemp arg64 = newTemp(Ity_I64);
10557
10558       modrm = getUChar(delta+2);
10559       if (epartIsReg(modrm)) {
10560          /* Only switch to MMX mode if the source is a MMX register.
10561             This is inconsistent with all other instructions which
10562             convert between XMM and (M64 or MMX), which always switch
10563             to MMX mode even if 64-bit operand is M64 and not MMX.  At
10564             least, that's what the Intel docs seem to me to say.
10565             Fixes #210264. */
10566          do_MMX_preamble();
10567          assign( arg64, getMMXReg(eregLO3ofRM(modrm)) );
10568          delta += 2+1;
10569          DIP("cvtpi2pd %s,%s\n", nameMMXReg(eregLO3ofRM(modrm)),
10570                                  nameXMMReg(gregOfRexRM(pfx,modrm)));
10571       } else {
10572          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
10573          assign( arg64, loadLE(Ity_I64, mkexpr(addr)) );
10574          delta += 2+alen;
10575          DIP("cvtpi2pd %s,%s\n", dis_buf,
10576                                  nameXMMReg(gregOfRexRM(pfx,modrm)) );
10577       }
10578
10579       putXMMRegLane64F( 
10580          gregOfRexRM(pfx,modrm), 0,
10581          unop(Iop_I32StoF64, unop(Iop_64to32, mkexpr(arg64)) )
10582       );
10583
10584       putXMMRegLane64F( 
10585          gregOfRexRM(pfx,modrm), 1,
10586          unop(Iop_I32StoF64, unop(Iop_64HIto32, mkexpr(arg64)) )
10587       );
10588
10589       goto decode_success;
10590    }
10591
10592    /* F3 0F 5B = CVTTPS2DQ -- convert 4 x F32 in mem/xmm to 4 x I32 in
10593       xmm(G), rounding towards zero */
10594    /* 66 0F 5B = CVTPS2DQ -- convert 4 x F32 in mem/xmm to 4 x I32 in
10595       xmm(G), as per the prevailing rounding mode */
10596    if ( ( (have66noF2noF3(pfx) && sz == 2)
10597           || (haveF3no66noF2(pfx) && sz == 4)
10598         )
10599         && insn[0] == 0x0F && insn[1] == 0x5B) {
10600       IRTemp argV   = newTemp(Ity_V128);
10601       IRTemp rmode  = newTemp(Ity_I32);
10602       Bool   r2zero = toBool(sz == 4);
10603
10604       modrm = getUChar(delta+2);
10605       if (epartIsReg(modrm)) {
10606          assign( argV, getXMMReg(eregOfRexRM(pfx,modrm)) );
10607          delta += 2+1;
10608          DIP("cvtps2dq %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)),
10609                                  nameXMMReg(gregOfRexRM(pfx,modrm)));
10610       } else {
10611          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
10612          assign( argV, loadLE(Ity_V128, mkexpr(addr)) );
10613          delta += 2+alen;
10614          DIP("cvtps2dq %s,%s\n", dis_buf,
10615                                  nameXMMReg(gregOfRexRM(pfx,modrm)) );
10616       }
10617          
10618       if (r2zero) {
10619          assign( rmode, mkU32((UInt)Irrm_ZERO) );
10620       } else {
10621          assign( rmode, get_sse_roundingmode() );
10622       }
10623
10624       breakup128to32s( argV, &t3, &t2, &t1, &t0 );
10625
10626       /* This is less than ideal.  If it turns out to be a performance
10627          bottleneck it can be improved. */
10628 #     define CVT(_t)                             \
10629          binop( Iop_F64toI32S,                   \
10630                 mkexpr(rmode),                   \
10631                 unop( Iop_F32toF64,              \
10632                       unop( Iop_ReinterpI32asF32, mkexpr(_t))) )
10633       
10634       putXMMRegLane32( gregOfRexRM(pfx,modrm), 3, CVT(t3) );
10635       putXMMRegLane32( gregOfRexRM(pfx,modrm), 2, CVT(t2) );
10636       putXMMRegLane32( gregOfRexRM(pfx,modrm), 1, CVT(t1) );
10637       putXMMRegLane32( gregOfRexRM(pfx,modrm), 0, CVT(t0) );
10638
10639 #     undef CVT
10640
10641       goto decode_success;
10642    }
10643
10644    /* 0F 5A = CVTPS2PD -- convert 2 x F32 in low half mem/xmm to 2 x
10645       F64 in xmm(G). */
10646    if (haveNo66noF2noF3(pfx) && sz == 4 
10647        && insn[0] == 0x0F && insn[1] == 0x5A) {
10648       IRTemp f32lo = newTemp(Ity_F32);
10649       IRTemp f32hi = newTemp(Ity_F32);
10650
10651       modrm = getUChar(delta+2);
10652       if (epartIsReg(modrm)) {
10653          assign( f32lo, getXMMRegLane32F(eregOfRexRM(pfx,modrm), 0) );
10654          assign( f32hi, getXMMRegLane32F(eregOfRexRM(pfx,modrm), 1) );
10655          delta += 2+1;
10656          DIP("cvtps2pd %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)),
10657                                  nameXMMReg(gregOfRexRM(pfx,modrm)));
10658       } else {
10659          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
10660          assign( f32lo, loadLE(Ity_F32, mkexpr(addr)) );
10661          assign( f32hi, loadLE(Ity_F32, 
10662                                binop(Iop_Add64,mkexpr(addr),mkU64(4))) );
10663          delta += 2+alen;
10664          DIP("cvtps2pd %s,%s\n", dis_buf,
10665                                  nameXMMReg(gregOfRexRM(pfx,modrm)) );
10666       }
10667
10668       putXMMRegLane64F( gregOfRexRM(pfx,modrm), 1,
10669                         unop(Iop_F32toF64, mkexpr(f32hi)) );
10670       putXMMRegLane64F( gregOfRexRM(pfx,modrm), 0,
10671                         unop(Iop_F32toF64, mkexpr(f32lo)) );
10672
10673       goto decode_success;
10674    }
10675
10676    /* F2 0F 2D = CVTSD2SI 
10677       when sz==4 -- convert F64 in mem/low half xmm to I32 in ireg, 
10678                     according to prevailing SSE rounding mode
10679       when sz==8 -- convert F64 in mem/low half xmm to I64 in ireg, 
10680                     according to prevailing SSE rounding mode
10681    */
10682    /* F2 0F 2C = CVTTSD2SI 
10683       when sz==4 -- convert F64 in mem/low half xmm to I32 in ireg, 
10684                     truncating towards zero
10685       when sz==8 -- convert F64 in mem/low half xmm to I64 in ireg, 
10686                     truncating towards zero 
10687    */
10688    if (haveF2no66noF3(pfx) 
10689        && insn[0] == 0x0F 
10690        && (insn[1] == 0x2D || insn[1] == 0x2C)) {
10691       IRTemp rmode  = newTemp(Ity_I32);
10692       IRTemp f64lo  = newTemp(Ity_F64);
10693       Bool   r2zero = toBool(insn[1] == 0x2C);
10694       vassert(sz == 4 || sz == 8);
10695
10696       modrm = getUChar(delta+2);
10697       if (epartIsReg(modrm)) {
10698          delta += 2+1;
10699          assign(f64lo, getXMMRegLane64F(eregOfRexRM(pfx,modrm), 0));
10700          DIP("cvt%ssd2si %s,%s\n", r2zero ? "t" : "",
10701                                    nameXMMReg(eregOfRexRM(pfx,modrm)),
10702                                    nameIReg(sz, gregOfRexRM(pfx,modrm), False));
10703       } else {
10704          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
10705          assign(f64lo, loadLE(Ity_F64, mkexpr(addr)));
10706          delta += 2+alen;
10707          DIP("cvt%ssd2si %s,%s\n", r2zero ? "t" : "",
10708                                    dis_buf,
10709                                    nameIReg(sz, gregOfRexRM(pfx,modrm), False));
10710       }
10711
10712       if (r2zero) {
10713          assign( rmode, mkU32((UInt)Irrm_ZERO) );
10714       } else {
10715          assign( rmode, get_sse_roundingmode() );
10716       }
10717
10718       if (sz == 4) {
10719          putIReg32( gregOfRexRM(pfx,modrm),
10720                     binop( Iop_F64toI32S, mkexpr(rmode), mkexpr(f64lo)) );
10721       } else {
10722          putIReg64( gregOfRexRM(pfx,modrm),
10723                     binop( Iop_F64toI64S, mkexpr(rmode), mkexpr(f64lo)) );
10724       }
10725
10726       goto decode_success;
10727    }
10728
10729    /* F2 0F 5A = CVTSD2SS -- convert F64 in mem/low half xmm to F32 in
10730       low 1/4 xmm(G), according to prevailing SSE rounding mode */
10731    if (haveF2no66noF3(pfx) && sz == 4
10732        && insn[0] == 0x0F && insn[1] == 0x5A) {
10733       IRTemp rmode = newTemp(Ity_I32);
10734       IRTemp f64lo = newTemp(Ity_F64);
10735       vassert(sz == 4);
10736
10737       modrm = getUChar(delta+2);
10738       if (epartIsReg(modrm)) {
10739          delta += 2+1;
10740          assign(f64lo, getXMMRegLane64F(eregOfRexRM(pfx,modrm), 0));
10741          DIP("cvtsd2ss %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)),
10742                                  nameXMMReg(gregOfRexRM(pfx,modrm)));
10743       } else {
10744          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
10745          assign(f64lo, loadLE(Ity_F64, mkexpr(addr)));
10746          delta += 2+alen;
10747          DIP("cvtsd2ss %s,%s\n", dis_buf,
10748                                  nameXMMReg(gregOfRexRM(pfx,modrm)));
10749       }
10750
10751       assign( rmode, get_sse_roundingmode() );
10752       putXMMRegLane32F( 
10753          gregOfRexRM(pfx,modrm), 0, 
10754          binop( Iop_F64toF32, mkexpr(rmode), mkexpr(f64lo) )
10755       );
10756
10757       goto decode_success;
10758    }
10759
10760    /* F2 0F 2A = CVTSI2SD 
10761       when sz==4 -- convert I32 in mem/ireg to F64 in low half xmm
10762       when sz==8 -- convert I64 in mem/ireg to F64 in low half xmm
10763    */
10764    if (haveF2no66noF3(pfx) && (sz == 4 || sz == 8)
10765        && insn[0] == 0x0F && insn[1] == 0x2A) {
10766       modrm = getUChar(delta+2);
10767
10768       if (sz == 4) {
10769          IRTemp arg32 = newTemp(Ity_I32);
10770          if (epartIsReg(modrm)) {
10771             assign( arg32, getIReg32(eregOfRexRM(pfx,modrm)) );
10772             delta += 2+1;
10773             DIP("cvtsi2sd %s,%s\n", nameIReg32(eregOfRexRM(pfx,modrm)),
10774                                     nameXMMReg(gregOfRexRM(pfx,modrm)));
10775          } else {
10776             addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
10777             assign( arg32, loadLE(Ity_I32, mkexpr(addr)) );
10778             delta += 2+alen;
10779             DIP("cvtsi2sd %s,%s\n", dis_buf,
10780                                     nameXMMReg(gregOfRexRM(pfx,modrm)) );
10781          }
10782          putXMMRegLane64F( gregOfRexRM(pfx,modrm), 0,
10783                            unop(Iop_I32StoF64, mkexpr(arg32)) 
10784          );
10785       } else {
10786          /* sz == 8 */
10787          IRTemp arg64 = newTemp(Ity_I64);
10788          if (epartIsReg(modrm)) {
10789             assign( arg64, getIReg64(eregOfRexRM(pfx,modrm)) );
10790             delta += 2+1;
10791             DIP("cvtsi2sdq %s,%s\n", nameIReg64(eregOfRexRM(pfx,modrm)),
10792                                      nameXMMReg(gregOfRexRM(pfx,modrm)));
10793          } else {
10794             addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
10795             assign( arg64, loadLE(Ity_I64, mkexpr(addr)) );
10796             delta += 2+alen;
10797             DIP("cvtsi2sdq %s,%s\n", dis_buf,
10798                                      nameXMMReg(gregOfRexRM(pfx,modrm)) );
10799          }
10800          putXMMRegLane64F( 
10801             gregOfRexRM(pfx,modrm), 
10802             0,
10803             binop( Iop_I64StoF64,
10804                    get_sse_roundingmode(),
10805                    mkexpr(arg64)
10806             ) 
10807          );
10808
10809       }
10810
10811       goto decode_success;
10812    }
10813
10814    /* F3 0F 5A = CVTSS2SD -- convert F32 in mem/low 1/4 xmm to F64 in
10815       low half xmm(G) */
10816    if (haveF3no66noF2(pfx) && sz == 4
10817        && insn[0] == 0x0F && insn[1] == 0x5A) {
10818       IRTemp f32lo = newTemp(Ity_F32);
10819
10820       modrm = getUChar(delta+2);
10821       if (epartIsReg(modrm)) {
10822          delta += 2+1;
10823          assign(f32lo, getXMMRegLane32F(eregOfRexRM(pfx,modrm), 0));
10824          DIP("cvtss2sd %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)),
10825                                  nameXMMReg(gregOfRexRM(pfx,modrm)));
10826       } else {
10827          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
10828          assign(f32lo, loadLE(Ity_F32, mkexpr(addr)));
10829          delta += 2+alen;
10830          DIP("cvtss2sd %s,%s\n", dis_buf,
10831                                  nameXMMReg(gregOfRexRM(pfx,modrm)));
10832       }
10833
10834       putXMMRegLane64F( gregOfRexRM(pfx,modrm), 0, 
10835                         unop( Iop_F32toF64, mkexpr(f32lo) ) );
10836
10837       goto decode_success;
10838    }
10839
10840    /* 66 0F 5E = DIVPD -- div 64Fx2 from R/M to R */
10841    if (have66noF2noF3(pfx) && sz == 2 
10842        && insn[0] == 0x0F && insn[1] == 0x5E) {
10843       delta = dis_SSE_E_to_G_all( vbi, pfx, delta+2, "divpd", Iop_Div64Fx2 );
10844       goto decode_success;
10845    }
10846
10847    /* F2 0F 5E = DIVSD -- div 64F0x2 from R/M to R */
10848    if (haveF2no66noF3(pfx) && insn[0] == 0x0F && insn[1] == 0x5E) {
10849       vassert(sz == 4);
10850       delta = dis_SSE_E_to_G_lo64( vbi, pfx, delta+2, "divsd", Iop_Div64F0x2 );
10851       goto decode_success;
10852    }
10853
10854    /* 0F AE /5 = LFENCE -- flush pending operations to memory */
10855    /* 0F AE /6 = MFENCE -- flush pending operations to memory */
10856    if (haveNo66noF2noF3(pfx) && sz == 4 
10857        && insn[0] == 0x0F && insn[1] == 0xAE
10858        && epartIsReg(insn[2]) 
10859        && (gregLO3ofRM(insn[2]) == 5 || gregLO3ofRM(insn[2]) == 6)) {
10860       delta += 3;
10861       /* Insert a memory fence.  It's sometimes important that these
10862          are carried through to the generated code. */
10863       stmt( IRStmt_MBE(Imbe_Fence) );
10864       DIP("%sfence\n", gregLO3ofRM(insn[2])==5 ? "l" : "m");
10865       goto decode_success;
10866    }
10867
10868    /* 66 0F 5F = MAXPD -- max 64Fx2 from R/M to R */
10869    if (have66noF2noF3(pfx) && sz == 2 
10870        && insn[0] == 0x0F && insn[1] == 0x5F) {
10871       delta = dis_SSE_E_to_G_all( vbi, pfx, delta+2, "maxpd", Iop_Max64Fx2 );
10872       goto decode_success;
10873    }
10874
10875    /* F2 0F 5F = MAXSD -- max 64F0x2 from R/M to R */
10876    if (haveF2no66noF3(pfx) && sz == 4
10877        && insn[0] == 0x0F && insn[1] == 0x5F) {
10878       delta = dis_SSE_E_to_G_lo64( vbi, pfx, delta+2, "maxsd", Iop_Max64F0x2 );
10879       goto decode_success;
10880    }
10881
10882    /* 66 0F 5D = MINPD -- min 64Fx2 from R/M to R */
10883    if (have66noF2noF3(pfx) && sz == 2 
10884        && insn[0] == 0x0F && insn[1] == 0x5D) {
10885       delta = dis_SSE_E_to_G_all( vbi, pfx, delta+2, "minpd", Iop_Min64Fx2 );
10886       goto decode_success;
10887    }
10888
10889    /* F2 0F 5D = MINSD -- min 64F0x2 from R/M to R */
10890    if (haveF2no66noF3(pfx) && sz == 4
10891        && insn[0] == 0x0F && insn[1] == 0x5D) {
10892       delta = dis_SSE_E_to_G_lo64( vbi, pfx, delta+2, "minsd", Iop_Min64F0x2 );
10893       goto decode_success;
10894    }
10895
10896    /* 66 0F 28 = MOVAPD -- move from E (mem or xmm) to G (xmm). */
10897    /* 66 0F 10 = MOVUPD -- move from E (mem or xmm) to G (xmm). */
10898    /* 66 0F 6F = MOVDQA -- move from E (mem or xmm) to G (xmm). */
10899    if (have66noF2noF3(pfx) 
10900        && (sz == 2 || /* ignore redundant REX.W */ sz == 8)
10901        && insn[0] == 0x0F 
10902        && (insn[1] == 0x28 || insn[1] == 0x10 || insn[1] == 0x6F)) {
10903       HChar* wot = insn[1]==0x28 ? "apd" :
10904                    insn[1]==0x10 ? "upd" : "dqa";
10905       modrm = getUChar(delta+2);
10906       if (epartIsReg(modrm)) {
10907          putXMMReg( gregOfRexRM(pfx,modrm), 
10908                     getXMMReg( eregOfRexRM(pfx,modrm) ));
10909          DIP("mov%s %s,%s\n", wot, nameXMMReg(eregOfRexRM(pfx,modrm)),
10910                                    nameXMMReg(gregOfRexRM(pfx,modrm)));
10911          delta += 2+1;
10912       } else {
10913          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
10914          putXMMReg( gregOfRexRM(pfx,modrm), 
10915                     loadLE(Ity_V128, mkexpr(addr)) );
10916          DIP("mov%s %s,%s\n", wot, dis_buf,
10917                                    nameXMMReg(gregOfRexRM(pfx,modrm)));
10918          delta += 2+alen;
10919       }
10920       goto decode_success;
10921    }
10922
10923    /* 66 0F 29 = MOVAPD -- move from G (xmm) to E (mem or xmm). */
10924    /* 66 0F 11 = MOVUPD -- move from G (xmm) to E (mem or xmm). */
10925    if (have66noF2noF3(pfx) && insn[0] == 0x0F 
10926        && (insn[1] == 0x29 || insn[1] == 0x11)) {
10927       modrm = getUChar(delta+2);
10928       if (epartIsReg(modrm)) {
10929          /* fall through; awaiting test case */
10930       } else {
10931          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
10932          storeLE( mkexpr(addr), getXMMReg(gregOfRexRM(pfx,modrm)) );
10933          DIP("mov[ua]pd %s,%s\n", nameXMMReg(gregOfRexRM(pfx,modrm)),
10934                                   dis_buf );
10935          delta += 2+alen;
10936          goto decode_success;
10937       }
10938    }
10939
10940    /* 66 0F 6E = MOVD from ireg32/m32 to xmm lo 1/4, zeroing high 3/4 of xmm. */
10941    /*              or from ireg64/m64 to xmm lo 1/2, zeroing high 1/2 of xmm. */
10942    if (have66noF2noF3(pfx) && insn[0] == 0x0F && insn[1] == 0x6E) {
10943       vassert(sz == 2 || sz == 8);
10944       if (sz == 2) sz = 4;
10945       modrm = getUChar(delta+2);
10946       if (epartIsReg(modrm)) {
10947          delta += 2+1;
10948          if (sz == 4) {
10949             putXMMReg(
10950                gregOfRexRM(pfx,modrm),
10951                unop( Iop_32UtoV128, getIReg32(eregOfRexRM(pfx,modrm)) ) 
10952             );
10953             DIP("movd %s, %s\n", nameIReg32(eregOfRexRM(pfx,modrm)), 
10954                                  nameXMMReg(gregOfRexRM(pfx,modrm)));
10955          } else {
10956             putXMMReg(
10957                gregOfRexRM(pfx,modrm),
10958                unop( Iop_64UtoV128, getIReg64(eregOfRexRM(pfx,modrm)) ) 
10959             );
10960             DIP("movq %s, %s\n", nameIReg64(eregOfRexRM(pfx,modrm)), 
10961                                  nameXMMReg(gregOfRexRM(pfx,modrm)));
10962          }
10963       } else {
10964          addr = disAMode( &alen, vbi, pfx, delta+2, dis_buf, 0 );
10965          delta += 2+alen;
10966          putXMMReg(
10967             gregOfRexRM(pfx,modrm),
10968             sz == 4 
10969                ?  unop( Iop_32UtoV128,loadLE(Ity_I32, mkexpr(addr)) ) 
10970                :  unop( Iop_64UtoV128,loadLE(Ity_I64, mkexpr(addr)) )
10971          );
10972          DIP("mov%c %s, %s\n", sz == 4 ? 'd' : 'q', dis_buf, 
10973                                nameXMMReg(gregOfRexRM(pfx,modrm)));
10974       }
10975       goto decode_success;
10976    }
10977
10978    /* 66 0F 7E = MOVD from xmm low 1/4 to ireg32 or m32. */
10979    /*              or from xmm low 1/2 to ireg64 or m64. */
10980    if (have66noF2noF3(pfx) && insn[0] == 0x0F && insn[1] == 0x7E) {
10981       if (sz == 2) sz = 4;
10982       vassert(sz == 4 || sz == 8);
10983       modrm = getUChar(delta+2);
10984       if (epartIsReg(modrm)) {
10985          delta += 2+1;
10986          if (sz == 4) {
10987             putIReg32( eregOfRexRM(pfx,modrm),
10988                        getXMMRegLane32(gregOfRexRM(pfx,modrm), 0) );
10989             DIP("movd %s, %s\n", nameXMMReg(gregOfRexRM(pfx,modrm)), 
10990                                  nameIReg32(eregOfRexRM(pfx,modrm)));
10991          } else {
10992             putIReg64( eregOfRexRM(pfx,modrm),
10993                        getXMMRegLane64(gregOfRexRM(pfx,modrm), 0) );
10994             DIP("movq %s, %s\n", nameXMMReg(gregOfRexRM(pfx,modrm)), 
10995                                  nameIReg64(eregOfRexRM(pfx,modrm)));
10996          }
10997       } else {
10998          addr = disAMode( &alen, vbi, pfx, delta+2, dis_buf, 0 );
10999          delta += 2+alen;
11000          storeLE( mkexpr(addr),
11001                   sz == 4
11002                      ? getXMMRegLane32(gregOfRexRM(pfx,modrm),0)
11003                      : getXMMRegLane64(gregOfRexRM(pfx,modrm),0) );
11004          DIP("mov%c %s, %s\n", sz == 4 ? 'd' : 'q',
11005                                nameXMMReg(gregOfRexRM(pfx,modrm)), dis_buf);
11006       }
11007       goto decode_success;
11008    }
11009
11010    /* 66 0F 7F = MOVDQA -- move from G (xmm) to E (mem or xmm). */
11011    if (have66noF2noF3(pfx) && sz == 2 
11012        && insn[0] == 0x0F && insn[1] == 0x7F) {
11013       modrm = getUChar(delta+2);
11014       if (epartIsReg(modrm)) {
11015          delta += 2+1;
11016          putXMMReg( eregOfRexRM(pfx,modrm),
11017                     getXMMReg(gregOfRexRM(pfx,modrm)) );
11018          DIP("movdqa %s, %s\n", nameXMMReg(gregOfRexRM(pfx,modrm)), 
11019                                 nameXMMReg(eregOfRexRM(pfx,modrm)));
11020       } else {
11021          addr = disAMode( &alen, vbi, pfx, delta+2, dis_buf, 0 );
11022          delta += 2+alen;
11023          storeLE( mkexpr(addr), getXMMReg(gregOfRexRM(pfx,modrm)) );
11024          DIP("movdqa %s, %s\n", nameXMMReg(gregOfRexRM(pfx,modrm)), dis_buf);
11025       }
11026       goto decode_success;
11027    }
11028
11029    /* F3 0F 6F = MOVDQU -- move from E (mem or xmm) to G (xmm). */
11030    if (haveF3no66noF2(pfx) && sz == 4
11031        && insn[0] == 0x0F && insn[1] == 0x6F) {
11032       modrm = getUChar(delta+2);
11033       if (epartIsReg(modrm)) {
11034          putXMMReg( gregOfRexRM(pfx,modrm), 
11035                     getXMMReg( eregOfRexRM(pfx,modrm) ));
11036          DIP("movdqu %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)),
11037                                nameXMMReg(gregOfRexRM(pfx,modrm)));
11038          delta += 2+1;
11039       } else {
11040          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
11041          putXMMReg( gregOfRexRM(pfx,modrm), 
11042                     loadLE(Ity_V128, mkexpr(addr)) );
11043          DIP("movdqu %s,%s\n", dis_buf,
11044                                nameXMMReg(gregOfRexRM(pfx,modrm)));
11045          delta += 2+alen;
11046       }
11047       goto decode_success;
11048    }
11049
11050    /* F3 0F 7F = MOVDQU -- move from G (xmm) to E (mem or xmm). */
11051    if (haveF3no66noF2(pfx) && sz == 4
11052        && insn[0] == 0x0F && insn[1] == 0x7F) {
11053       modrm = getUChar(delta+2);
11054       if (epartIsReg(modrm)) {
11055          goto decode_failure; /* awaiting test case */
11056          delta += 2+1;
11057          putXMMReg( eregOfRexRM(pfx,modrm),
11058                     getXMMReg(gregOfRexRM(pfx,modrm)) );
11059          DIP("movdqu %s, %s\n", nameXMMReg(gregOfRexRM(pfx,modrm)), 
11060                                 nameXMMReg(eregOfRexRM(pfx,modrm)));
11061       } else {
11062          addr = disAMode( &alen, vbi, pfx, delta+2, dis_buf, 0 );
11063          delta += 2+alen;
11064          storeLE( mkexpr(addr), getXMMReg(gregOfRexRM(pfx,modrm)) );
11065          DIP("movdqu %s, %s\n", nameXMMReg(gregOfRexRM(pfx,modrm)), dis_buf);
11066       }
11067       goto decode_success;
11068    }
11069
11070    /* F2 0F D6 = MOVDQ2Q -- move from E (lo half xmm, not mem) to G (mmx). */
11071    if (haveF2no66noF3(pfx) && sz == 4 
11072        && insn[0] == 0x0F && insn[1] == 0xD6) {
11073       modrm = getUChar(delta+2);
11074       if (epartIsReg(modrm)) {
11075          do_MMX_preamble();
11076          putMMXReg( gregLO3ofRM(modrm), 
11077                     getXMMRegLane64( eregOfRexRM(pfx,modrm), 0 ));
11078          DIP("movdq2q %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)),
11079                                 nameMMXReg(gregLO3ofRM(modrm)));
11080          delta += 2+1;
11081          goto decode_success;
11082       } else {
11083          /* apparently no mem case for this insn */
11084          goto decode_failure;
11085       }
11086    }
11087
11088    /* 66 0F 16 = MOVHPD -- move from mem to high half of XMM. */
11089    /* These seems identical to MOVHPS.  This instruction encoding is
11090       completely crazy. */
11091    if (have66noF2noF3(pfx) && insn[0] == 0x0F && insn[1] == 0x16) {
11092       modrm = getUChar(delta+2);
11093       if (epartIsReg(modrm)) {
11094          /* fall through; apparently reg-reg is not possible */
11095       } else {
11096          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
11097          delta += 2+alen;
11098          putXMMRegLane64( gregOfRexRM(pfx,modrm), 1/*upper lane*/,
11099                           loadLE(Ity_I64, mkexpr(addr)) );
11100          DIP("movhpd %s,%s\n", dis_buf, 
11101                                nameXMMReg( gregOfRexRM(pfx,modrm) ));
11102          goto decode_success;
11103       }
11104    }
11105
11106    /* 66 0F 17 = MOVHPD -- move from high half of XMM to mem. */
11107    /* Again, this seems identical to MOVHPS. */
11108    if (have66noF2noF3(pfx) && insn[0] == 0x0F && insn[1] == 0x17) {
11109       if (!epartIsReg(insn[2])) {
11110          delta += 2;
11111          addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
11112          delta += alen;
11113          storeLE( mkexpr(addr), 
11114                   getXMMRegLane64( gregOfRexRM(pfx,insn[2]),
11115                                    1/*upper lane*/ ) );
11116          DIP("movhpd %s,%s\n", nameXMMReg( gregOfRexRM(pfx,insn[2]) ),
11117                                dis_buf);
11118          goto decode_success;
11119       }
11120       /* else fall through */
11121    }
11122
11123    /* 66 0F 12 = MOVLPD -- move from mem to low half of XMM. */
11124    /* Identical to MOVLPS ? */
11125    if (have66noF2noF3(pfx) && insn[0] == 0x0F && insn[1] == 0x12) {
11126       modrm = getUChar(delta+2);
11127       if (epartIsReg(modrm)) {
11128          /* fall through; apparently reg-reg is not possible */
11129       } else {
11130          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
11131          delta += 2+alen;
11132          putXMMRegLane64( gregOfRexRM(pfx,modrm),
11133                           0/*lower lane*/,
11134                           loadLE(Ity_I64, mkexpr(addr)) );
11135          DIP("movlpd %s, %s\n", 
11136              dis_buf, nameXMMReg( gregOfRexRM(pfx,modrm) ));
11137          goto decode_success;
11138       }
11139    }
11140
11141    /* 66 0F 13 = MOVLPD -- move from low half of XMM to mem. */
11142    /* Identical to MOVLPS ? */
11143    if (have66noF2noF3(pfx) && insn[0] == 0x0F && insn[1] == 0x13) {
11144       modrm = getUChar(delta+2);
11145       if (!epartIsReg(modrm)) {
11146          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
11147          delta += 2+alen;
11148          storeLE( mkexpr(addr), 
11149                   getXMMRegLane64( gregOfRexRM(pfx,modrm), 
11150                                    0/*lower lane*/ ) );
11151          DIP("movlpd %s, %s\n", nameXMMReg( gregOfRexRM(pfx,modrm) ),
11152                                 dis_buf);
11153          goto decode_success;
11154       }
11155       /* else fall through */
11156    }
11157
11158    /* 66 0F 50 = MOVMSKPD - move 2 sign bits from 2 x F64 in xmm(E) to
11159       2 lowest bits of ireg(G) */
11160    if (have66noF2noF3(pfx) && (sz == 2 || sz == 8)
11161        && insn[0] == 0x0F && insn[1] == 0x50) {
11162       /* sz == 8 is a kludge to handle insns with REX.W redundantly
11163          set to 1, which has been known to happen:
11164          66 4c 0f 50 d9          rex64X movmskpd %xmm1,%r11d
11165          20071106: see further comments on MOVMSKPS implementation above.
11166       */
11167       modrm = getUChar(delta+2);
11168       if (epartIsReg(modrm)) {
11169          Int src;
11170          t0 = newTemp(Ity_I32);
11171          t1 = newTemp(Ity_I32);
11172          delta += 2+1;
11173          src = eregOfRexRM(pfx,modrm);
11174          assign( t0, binop( Iop_And32,
11175                             binop(Iop_Shr32, getXMMRegLane32(src,1), mkU8(31)),
11176                             mkU32(1) ));
11177          assign( t1, binop( Iop_And32,
11178                             binop(Iop_Shr32, getXMMRegLane32(src,3), mkU8(30)),
11179                             mkU32(2) ));
11180          putIReg32( gregOfRexRM(pfx,modrm),
11181                     binop(Iop_Or32, mkexpr(t0), mkexpr(t1))
11182                   );
11183          DIP("movmskpd %s,%s\n", nameXMMReg(src), 
11184                                  nameIReg32(gregOfRexRM(pfx,modrm)));
11185          goto decode_success;
11186       }
11187       /* else fall through */
11188       goto decode_failure;
11189    }
11190
11191    /* 66 0F F7 = MASKMOVDQU -- store selected bytes of double quadword */
11192    if (have66noF2noF3(pfx) && sz == 2
11193        && insn[0] == 0x0F && insn[1] == 0xF7) {
11194       modrm = getUChar(delta+2);
11195       if (epartIsReg(modrm)) {
11196          IRTemp regD    = newTemp(Ity_V128);
11197          IRTemp mask    = newTemp(Ity_V128);
11198          IRTemp olddata = newTemp(Ity_V128);
11199          IRTemp newdata = newTemp(Ity_V128);
11200                 addr    = newTemp(Ity_I64);
11201
11202          assign( addr, handleAddrOverrides( vbi, pfx, getIReg64(R_RDI) ));
11203          assign( regD, getXMMReg( gregOfRexRM(pfx,modrm) ));
11204
11205          /* Unfortunately can't do the obvious thing with SarN8x16
11206             here since that can't be re-emitted as SSE2 code - no such
11207             insn. */
11208          assign( 
11209             mask, 
11210             binop(Iop_64HLtoV128,
11211                   binop(Iop_SarN8x8, 
11212                         getXMMRegLane64( eregOfRexRM(pfx,modrm), 1 ), 
11213                         mkU8(7) ),
11214                   binop(Iop_SarN8x8, 
11215                         getXMMRegLane64( eregOfRexRM(pfx,modrm), 0 ), 
11216                         mkU8(7) ) ));
11217          assign( olddata, loadLE( Ity_V128, mkexpr(addr) ));
11218          assign( newdata, 
11219                  binop(Iop_OrV128, 
11220                        binop(Iop_AndV128, 
11221                              mkexpr(regD), 
11222                              mkexpr(mask) ),
11223                        binop(Iop_AndV128, 
11224                              mkexpr(olddata),
11225                              unop(Iop_NotV128, mkexpr(mask)))) );
11226          storeLE( mkexpr(addr), mkexpr(newdata) );
11227
11228          delta += 2+1;
11229          DIP("maskmovdqu %s,%s\n", nameXMMReg( eregOfRexRM(pfx,modrm) ),
11230                                    nameXMMReg( gregOfRexRM(pfx,modrm) ) );
11231          goto decode_success;
11232       }
11233       /* else fall through */
11234    }
11235
11236    /* 66 0F E7 = MOVNTDQ -- for us, just a plain SSE store. */
11237    if (have66noF2noF3(pfx) && sz == 2 
11238        && insn[0] == 0x0F && insn[1] == 0xE7) {
11239       modrm = getUChar(delta+2);
11240       if (!epartIsReg(modrm)) {
11241          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
11242          storeLE( mkexpr(addr), getXMMReg(gregOfRexRM(pfx,modrm)) );
11243          DIP("movntdq %s,%s\n", dis_buf,
11244                                 nameXMMReg(gregOfRexRM(pfx,modrm)));
11245          delta += 2+alen;
11246          goto decode_success;
11247       }
11248       /* else fall through */
11249       goto decode_failure;
11250    }
11251
11252    /* 0F C3 = MOVNTI -- for us, just a plain ireg store. */
11253    if (haveNo66noF2noF3(pfx) &&
11254        insn[0] == 0x0F && insn[1] == 0xC3) {
11255       vassert(sz == 4 || sz == 8);
11256       modrm = getUChar(delta+2);
11257       if (!epartIsReg(modrm)) {
11258          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
11259          storeLE( mkexpr(addr), getIRegG(sz, pfx, modrm) );
11260          DIP("movnti %s,%s\n", dis_buf,
11261                                nameIRegG(sz, pfx, modrm));
11262          delta += 2+alen;
11263          goto decode_success;
11264       }
11265       /* else fall through */
11266    }
11267
11268    /* 66 0F D6 = MOVQ -- move 64 bits from G (lo half xmm) to E (mem
11269       or lo half xmm).  */
11270    if (have66noF2noF3(pfx) 
11271        && (sz == 2 || /* ignore redundant REX.W */ sz == 8)
11272        && insn[0] == 0x0F && insn[1] == 0xD6) {
11273       modrm = getUChar(delta+2);
11274       if (epartIsReg(modrm)) {
11275          /* fall through, awaiting test case */
11276          /* dst: lo half copied, hi half zeroed */
11277       } else {
11278          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
11279          storeLE( mkexpr(addr), 
11280                   getXMMRegLane64( gregOfRexRM(pfx,modrm), 0 ));
11281          DIP("movq %s,%s\n", nameXMMReg(gregOfRexRM(pfx,modrm)), dis_buf );
11282          delta += 2+alen;
11283          goto decode_success;
11284       }
11285    }
11286
11287    /* F3 0F D6 = MOVQ2DQ -- move from E (mmx) to G (lo half xmm, zero
11288       hi half). */
11289    if (haveF3no66noF2(pfx) && sz == 4
11290        && insn[0] == 0x0F && insn[1] == 0xD6) {
11291       modrm = getUChar(delta+2);
11292       if (epartIsReg(modrm)) {
11293          do_MMX_preamble();
11294          putXMMReg( gregOfRexRM(pfx,modrm), 
11295                     unop(Iop_64UtoV128, getMMXReg( eregLO3ofRM(modrm) )) );
11296          DIP("movq2dq %s,%s\n", nameMMXReg(eregLO3ofRM(modrm)),
11297                                 nameXMMReg(gregOfRexRM(pfx,modrm)));
11298          delta += 2+1;
11299          goto decode_success;
11300       } else {
11301          /* apparently no mem case for this insn */
11302          goto decode_failure;
11303       }
11304    }
11305
11306    /* F3 0F 7E = MOVQ -- move 64 bits from E (mem or lo half xmm) to
11307       G (lo half xmm).  Upper half of G is zeroed out. */
11308    /* F2 0F 10 = MOVSD -- move 64 bits from E (mem or lo half xmm) to
11309       G (lo half xmm).  If E is mem, upper half of G is zeroed out.
11310       If E is reg, upper half of G is unchanged. */
11311    if ( (haveF2no66noF3(pfx) 
11312          && (sz == 4 || /* ignore redundant REX.W */ sz == 8)
11313          && insn[0] == 0x0F && insn[1] == 0x10)
11314         || 
11315         (haveF3no66noF2(pfx) 
11316          && (sz == 4 || /* ignore redundant REX.W */ sz == 8)
11317          && insn[0] == 0x0F && insn[1] == 0x7E)
11318       ) {
11319       modrm = getUChar(delta+2);
11320       if (epartIsReg(modrm)) {
11321          putXMMRegLane64( gregOfRexRM(pfx,modrm), 0,
11322                           getXMMRegLane64( eregOfRexRM(pfx,modrm), 0 ));
11323          if (insn[1] == 0x7E/*MOVQ*/) {
11324             /* zero bits 127:64 */
11325             putXMMRegLane64( gregOfRexRM(pfx,modrm), 1, mkU64(0) );
11326          }
11327          DIP("movsd %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)),
11328                               nameXMMReg(gregOfRexRM(pfx,modrm)));
11329          delta += 2+1;
11330       } else {
11331          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
11332          putXMMReg( gregOfRexRM(pfx,modrm), mkV128(0) );
11333          putXMMRegLane64( gregOfRexRM(pfx,modrm), 0,
11334                           loadLE(Ity_I64, mkexpr(addr)) );
11335          DIP("movsd %s,%s\n", dis_buf,
11336                               nameXMMReg(gregOfRexRM(pfx,modrm)));
11337          delta += 2+alen;
11338       }
11339       goto decode_success;
11340    }
11341
11342    /* F2 0F 11 = MOVSD -- move 64 bits from G (lo half xmm) to E (mem
11343       or lo half xmm). */
11344    if (haveF2no66noF3(pfx) 
11345        && (sz == 4 || /* ignore redundant REX.W */ sz == 8)
11346        && insn[0] == 0x0F && insn[1] == 0x11) {
11347       modrm = getUChar(delta+2);
11348       if (epartIsReg(modrm)) {
11349          putXMMRegLane64( eregOfRexRM(pfx,modrm), 0,
11350                           getXMMRegLane64( gregOfRexRM(pfx,modrm), 0 ));
11351          DIP("movsd %s,%s\n", nameXMMReg(gregOfRexRM(pfx,modrm)),
11352                               nameXMMReg(eregOfRexRM(pfx,modrm)));
11353          delta += 2+1;
11354       } else {
11355          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
11356          storeLE( mkexpr(addr),
11357                   getXMMRegLane64(gregOfRexRM(pfx,modrm), 0) );
11358          DIP("movsd %s,%s\n", nameXMMReg(gregOfRexRM(pfx,modrm)),
11359                               dis_buf);
11360          delta += 2+alen;
11361       }
11362       goto decode_success;
11363    }
11364
11365    /* 66 0F 59 = MULPD -- mul 64Fx2 from R/M to R */
11366    if (have66noF2noF3(pfx) 
11367        && (sz == 2 || /* ignore redundant REX.W */ sz == 8)
11368        && insn[0] == 0x0F && insn[1] == 0x59) {
11369       delta = dis_SSE_E_to_G_all( vbi, pfx, delta+2, "mulpd", Iop_Mul64Fx2 );
11370       goto decode_success;
11371    }
11372
11373    /* F2 0F 59 = MULSD -- mul 64F0x2 from R/M to R */
11374    if (haveF2no66noF3(pfx) 
11375        && (sz == 4 || /* ignore redundant REX.W */ sz == 8)
11376        && insn[0] == 0x0F && insn[1] == 0x59) {
11377       delta = dis_SSE_E_to_G_lo64( vbi, pfx, delta+2, "mulsd", Iop_Mul64F0x2 );
11378       goto decode_success;
11379    }
11380
11381    /* 66 0F 56 = ORPD -- G = G and E */
11382    if (have66noF2noF3(pfx) && sz == 2 
11383        && insn[0] == 0x0F && insn[1] == 0x56) {
11384       delta = dis_SSE_E_to_G_all( vbi, pfx, delta+2, "orpd", Iop_OrV128 );
11385       goto decode_success;
11386    }
11387
11388    /* 66 0F C6 /r ib = SHUFPD -- shuffle packed F64s */
11389    if (have66noF2noF3(pfx) && sz == 2 
11390        && insn[0] == 0x0F && insn[1] == 0xC6) {
11391       Int    select;
11392       IRTemp sV = newTemp(Ity_V128);
11393       IRTemp dV = newTemp(Ity_V128);
11394       IRTemp s1 = newTemp(Ity_I64);
11395       IRTemp s0 = newTemp(Ity_I64);
11396       IRTemp d1 = newTemp(Ity_I64);
11397       IRTemp d0 = newTemp(Ity_I64);
11398
11399       modrm = insn[2];
11400       assign( dV, getXMMReg(gregOfRexRM(pfx,modrm)) );
11401
11402       if (epartIsReg(modrm)) {
11403          assign( sV, getXMMReg(eregOfRexRM(pfx,modrm)) );
11404          select = (Int)insn[3];
11405          delta += 2+2;
11406          DIP("shufpd $%d,%s,%s\n", select, 
11407                                    nameXMMReg(eregOfRexRM(pfx,modrm)),
11408                                    nameXMMReg(gregOfRexRM(pfx,modrm)));
11409       } else {
11410          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 1 );
11411          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
11412          select = (Int)insn[2+alen];
11413          delta += 3+alen;
11414          DIP("shufpd $%d,%s,%s\n", select, 
11415                                    dis_buf,
11416                                    nameXMMReg(gregOfRexRM(pfx,modrm)));
11417       }
11418
11419       assign( d1, unop(Iop_V128HIto64, mkexpr(dV)) );
11420       assign( d0, unop(Iop_V128to64,   mkexpr(dV)) );
11421       assign( s1, unop(Iop_V128HIto64, mkexpr(sV)) );
11422       assign( s0, unop(Iop_V128to64,   mkexpr(sV)) );
11423
11424 #     define SELD(n) mkexpr((n)==0 ? d0 : d1)
11425 #     define SELS(n) mkexpr((n)==0 ? s0 : s1)
11426
11427       putXMMReg(
11428          gregOfRexRM(pfx,modrm), 
11429          binop(Iop_64HLtoV128, SELS((select>>1)&1), SELD((select>>0)&1) )
11430       );
11431
11432 #     undef SELD
11433 #     undef SELS
11434
11435       goto decode_success;
11436    }
11437
11438    /* 66 0F 51 = SQRTPD -- approx sqrt 64Fx2 from R/M to R */
11439    if (have66noF2noF3(pfx) && sz == 2 
11440        && insn[0] == 0x0F && insn[1] == 0x51) {
11441       delta = dis_SSE_E_to_G_unary_all( vbi, pfx, delta+2, 
11442                                         "sqrtpd", Iop_Sqrt64Fx2 );
11443       goto decode_success;
11444    }
11445
11446    /* F2 0F 51 = SQRTSD -- approx sqrt 64F0x2 from R/M to R */
11447    if (haveF2no66noF3(pfx) && insn[0] == 0x0F && insn[1] == 0x51) {
11448       vassert(sz == 4);
11449       delta = dis_SSE_E_to_G_unary_lo64( vbi, pfx, delta+2, 
11450                                          "sqrtsd", Iop_Sqrt64F0x2 );
11451       goto decode_success;
11452    }
11453
11454    /* 66 0F 5C = SUBPD -- sub 64Fx2 from R/M to R */
11455    if (have66noF2noF3(pfx) && sz == 2 
11456        && insn[0] == 0x0F && insn[1] == 0x5C) {
11457       delta = dis_SSE_E_to_G_all( vbi, pfx, delta+2, "subpd", Iop_Sub64Fx2 );
11458       goto decode_success;
11459    }
11460
11461    /* F2 0F 5C = SUBSD -- sub 64F0x2 from R/M to R */
11462    if (haveF2no66noF3(pfx) 
11463        && (sz == 4 || /* ignore redundant REX.W */ sz == 8)
11464        && insn[0] == 0x0F && insn[1] == 0x5C) {
11465       delta = dis_SSE_E_to_G_lo64( vbi, pfx, delta+2, "subsd", Iop_Sub64F0x2 );
11466       goto decode_success;
11467    }
11468
11469    /* 66 0F 15 = UNPCKHPD -- unpack and interleave high part F64s */
11470    /* 66 0F 14 = UNPCKLPD -- unpack and interleave low part F64s */
11471    /* These just appear to be special cases of SHUFPS */
11472    if (have66noF2noF3(pfx) 
11473        && sz == 2 /* could be 8 if rex also present */
11474        && insn[0] == 0x0F && (insn[1] == 0x15 || insn[1] == 0x14)) {
11475       IRTemp s1 = newTemp(Ity_I64);
11476       IRTemp s0 = newTemp(Ity_I64);
11477       IRTemp d1 = newTemp(Ity_I64);
11478       IRTemp d0 = newTemp(Ity_I64);
11479       IRTemp sV = newTemp(Ity_V128);
11480       IRTemp dV = newTemp(Ity_V128);
11481       Bool   hi = toBool(insn[1] == 0x15);
11482
11483       modrm = insn[2];
11484       assign( dV, getXMMReg(gregOfRexRM(pfx,modrm)) );
11485
11486       if (epartIsReg(modrm)) {
11487          assign( sV, getXMMReg(eregOfRexRM(pfx,modrm)) );
11488          delta += 2+1;
11489          DIP("unpck%sps %s,%s\n", hi ? "h" : "l",
11490                                   nameXMMReg(eregOfRexRM(pfx,modrm)),
11491                                   nameXMMReg(gregOfRexRM(pfx,modrm)));
11492       } else {
11493          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
11494          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
11495          delta += 2+alen;
11496          DIP("unpck%sps %s,%s\n", hi ? "h" : "l",
11497                                   dis_buf,
11498                                   nameXMMReg(gregOfRexRM(pfx,modrm)));
11499       }
11500
11501       assign( d1, unop(Iop_V128HIto64, mkexpr(dV)) );
11502       assign( d0, unop(Iop_V128to64,   mkexpr(dV)) );
11503       assign( s1, unop(Iop_V128HIto64, mkexpr(sV)) );
11504       assign( s0, unop(Iop_V128to64,   mkexpr(sV)) );
11505
11506       if (hi) {
11507          putXMMReg( gregOfRexRM(pfx,modrm), 
11508                     binop(Iop_64HLtoV128, mkexpr(s1), mkexpr(d1)) );
11509       } else {
11510          putXMMReg( gregOfRexRM(pfx,modrm), 
11511                     binop(Iop_64HLtoV128, mkexpr(s0), mkexpr(d0)) );
11512       }
11513
11514       goto decode_success;
11515    }
11516
11517    /* 66 0F 57 = XORPD -- G = G xor E */
11518    if (have66noF2noF3(pfx) && sz == 2 
11519        && insn[0] == 0x0F && insn[1] == 0x57) {
11520       delta = dis_SSE_E_to_G_all( vbi, pfx, delta+2, "xorpd", Iop_XorV128 );
11521       goto decode_success;
11522    }
11523
11524    /* 66 0F 6B = PACKSSDW */
11525    if (have66noF2noF3(pfx) && sz == 2 
11526        && insn[0] == 0x0F && insn[1] == 0x6B) {
11527       delta = dis_SSEint_E_to_G( vbi, pfx, delta+2, 
11528                                  "packssdw", Iop_QNarrow32Sx4, True );
11529       goto decode_success;
11530    }
11531
11532    /* 66 0F 63 = PACKSSWB */
11533    if (have66noF2noF3(pfx) && sz == 2 
11534        && insn[0] == 0x0F && insn[1] == 0x63) {
11535       delta = dis_SSEint_E_to_G( vbi, pfx, delta+2, 
11536                                  "packsswb", Iop_QNarrow16Sx8, True );
11537       goto decode_success;
11538    }
11539
11540    /* 66 0F 67 = PACKUSWB */
11541    if (have66noF2noF3(pfx) && sz == 2 
11542        && insn[0] == 0x0F && insn[1] == 0x67) {
11543       delta = dis_SSEint_E_to_G( vbi, pfx, delta+2, 
11544                                  "packuswb", Iop_QNarrow16Ux8, True );
11545       goto decode_success;
11546    }
11547
11548    /* 66 0F FC = PADDB */
11549    if (have66noF2noF3(pfx) && sz == 2 
11550        && insn[0] == 0x0F && insn[1] == 0xFC) {
11551       delta = dis_SSEint_E_to_G( vbi, pfx, delta+2, 
11552                                  "paddb", Iop_Add8x16, False );
11553       goto decode_success;
11554    }
11555
11556    /* 66 0F FE = PADDD */
11557    if (have66noF2noF3(pfx) && sz == 2 
11558        && insn[0] == 0x0F && insn[1] == 0xFE) {
11559       delta = dis_SSEint_E_to_G( vbi, pfx, delta+2, 
11560                                  "paddd", Iop_Add32x4, False );
11561       goto decode_success;
11562    }
11563
11564    /* ***--- this is an MMX class insn introduced in SSE2 ---*** */
11565    /* 0F D4 = PADDQ -- add 64x1 */
11566    if (haveNo66noF2noF3(pfx) && sz == 4 
11567        && insn[0] == 0x0F && insn[1] == 0xD4) {
11568       do_MMX_preamble();
11569       delta = dis_MMXop_regmem_to_reg ( 
11570                 vbi, pfx, delta+2, insn[1], "paddq", False );
11571       goto decode_success;
11572    }
11573
11574    /* 66 0F D4 = PADDQ */
11575    if (have66noF2noF3(pfx) && sz == 2 
11576        && insn[0] == 0x0F && insn[1] == 0xD4) {
11577       delta = dis_SSEint_E_to_G( vbi, pfx, delta+2, 
11578                                  "paddq", Iop_Add64x2, False );
11579       goto decode_success;
11580    }
11581
11582    /* 66 0F FD = PADDW */
11583    if (have66noF2noF3(pfx) && sz == 2 
11584        && insn[0] == 0x0F && insn[1] == 0xFD) {
11585       delta = dis_SSEint_E_to_G( vbi, pfx, delta+2, 
11586                                  "paddw", Iop_Add16x8, False );
11587       goto decode_success;
11588    }
11589
11590    /* 66 0F EC = PADDSB */
11591    if (have66noF2noF3(pfx) && sz == 2 
11592        && insn[0] == 0x0F && insn[1] == 0xEC) {
11593       delta = dis_SSEint_E_to_G( vbi, pfx, delta+2, 
11594                                  "paddsb", Iop_QAdd8Sx16, False );
11595       goto decode_success;
11596    }
11597
11598    /* 66 0F ED = PADDSW */
11599    if (have66noF2noF3(pfx) && sz == 2 
11600        && insn[0] == 0x0F && insn[1] == 0xED) {
11601       delta = dis_SSEint_E_to_G( vbi, pfx, delta+2, 
11602                                  "paddsw", Iop_QAdd16Sx8, False );
11603       goto decode_success;
11604    }
11605
11606    /* 66 0F DC = PADDUSB */
11607    if (have66noF2noF3(pfx) && sz == 2 
11608        && insn[0] == 0x0F && insn[1] == 0xDC) {
11609       delta = dis_SSEint_E_to_G( vbi, pfx, delta+2, 
11610                                  "paddusb", Iop_QAdd8Ux16, False );
11611       goto decode_success;
11612    }
11613
11614    /* 66 0F DD = PADDUSW */
11615    if (have66noF2noF3(pfx) && sz == 2 
11616        && insn[0] == 0x0F && insn[1] == 0xDD) {
11617       delta = dis_SSEint_E_to_G( vbi, pfx, delta+2, 
11618                                  "paddusw", Iop_QAdd16Ux8, False );
11619       goto decode_success;
11620    }
11621
11622    /* 66 0F DB = PAND */
11623    if (have66noF2noF3(pfx) && sz == 2 
11624        && insn[0] == 0x0F && insn[1] == 0xDB) {
11625       delta = dis_SSE_E_to_G_all( vbi, pfx, delta+2, "pand", Iop_AndV128 );
11626       goto decode_success;
11627    }
11628
11629    /* 66 0F DF = PANDN */
11630    if (have66noF2noF3(pfx) && sz == 2 
11631        && insn[0] == 0x0F && insn[1] == 0xDF) {
11632       delta = dis_SSE_E_to_G_all_invG( vbi, pfx, delta+2, "pandn", Iop_AndV128 );
11633       goto decode_success;
11634    }
11635
11636    /* 66 0F E0 = PAVGB */
11637    if (have66noF2noF3(pfx) && sz == 2 
11638        && insn[0] == 0x0F && insn[1] == 0xE0) {
11639       delta = dis_SSEint_E_to_G( vbi, pfx, delta+2, 
11640                                  "pavgb", Iop_Avg8Ux16, False );
11641       goto decode_success;
11642    }
11643
11644    /* 66 0F E3 = PAVGW */
11645    if (have66noF2noF3(pfx) && sz == 2 
11646        && insn[0] == 0x0F && insn[1] == 0xE3) {
11647       delta = dis_SSEint_E_to_G( vbi, pfx, delta+2, 
11648                                  "pavgw", Iop_Avg16Ux8, False );
11649       goto decode_success;
11650    }
11651
11652    /* 66 0F 74 = PCMPEQB */
11653    if (have66noF2noF3(pfx) && sz == 2 
11654        && insn[0] == 0x0F && insn[1] == 0x74) {
11655       delta = dis_SSEint_E_to_G( vbi, pfx, delta+2, 
11656                                  "pcmpeqb", Iop_CmpEQ8x16, False );
11657       goto decode_success;
11658    }
11659
11660    /* 66 0F 76 = PCMPEQD */
11661    if (have66noF2noF3(pfx) && sz == 2 
11662        && insn[0] == 0x0F && insn[1] == 0x76) {
11663       delta = dis_SSEint_E_to_G( vbi, pfx, delta+2, 
11664                                  "pcmpeqd", Iop_CmpEQ32x4, False );
11665       goto decode_success;
11666    }
11667
11668    /* 66 0F 75 = PCMPEQW */
11669    if (have66noF2noF3(pfx) && sz == 2 
11670        && insn[0] == 0x0F && insn[1] == 0x75) {
11671       delta = dis_SSEint_E_to_G( vbi, pfx, delta+2, 
11672                                  "pcmpeqw", Iop_CmpEQ16x8, False );
11673       goto decode_success;
11674    }
11675
11676    /* 66 0F 64 = PCMPGTB */
11677    if (have66noF2noF3(pfx) && sz == 2 
11678        && insn[0] == 0x0F && insn[1] == 0x64) {
11679       delta = dis_SSEint_E_to_G( vbi, pfx, delta+2, 
11680                                  "pcmpgtb", Iop_CmpGT8Sx16, False );
11681       goto decode_success;
11682    }
11683
11684    /* 66 0F 66 = PCMPGTD */
11685    if (have66noF2noF3(pfx) && sz == 2 
11686        && insn[0] == 0x0F && insn[1] == 0x66) {
11687       delta = dis_SSEint_E_to_G( vbi, pfx, delta+2, 
11688                                  "pcmpgtd", Iop_CmpGT32Sx4, False );
11689       goto decode_success;
11690    }
11691
11692    /* 66 0F 65 = PCMPGTW */
11693    if (have66noF2noF3(pfx) && sz == 2 
11694        && insn[0] == 0x0F && insn[1] == 0x65) {
11695       delta = dis_SSEint_E_to_G( vbi, pfx, delta+2, 
11696                                  "pcmpgtw", Iop_CmpGT16Sx8, False );
11697       goto decode_success;
11698    }
11699
11700    /* 66 0F C5 = PEXTRW -- extract 16-bit field from xmm(E) and put 
11701       zero-extend of it in ireg(G). */
11702    if (have66noF2noF3(pfx) 
11703        && (sz == 2 || /* ignore redundant REX.W */ sz == 8)
11704        && insn[0] == 0x0F && insn[1] == 0xC5) {
11705       modrm = insn[2];
11706       if (epartIsReg(modrm)) {
11707          t5 = newTemp(Ity_V128);
11708          t4 = newTemp(Ity_I16);
11709          assign(t5, getXMMReg(eregOfRexRM(pfx,modrm)));
11710          breakup128to32s( t5, &t3, &t2, &t1, &t0 );
11711          switch (insn[3] & 7) {
11712             case 0:  assign(t4, unop(Iop_32to16,   mkexpr(t0))); break;
11713             case 1:  assign(t4, unop(Iop_32HIto16, mkexpr(t0))); break;
11714             case 2:  assign(t4, unop(Iop_32to16,   mkexpr(t1))); break;
11715             case 3:  assign(t4, unop(Iop_32HIto16, mkexpr(t1))); break;
11716             case 4:  assign(t4, unop(Iop_32to16,   mkexpr(t2))); break;
11717             case 5:  assign(t4, unop(Iop_32HIto16, mkexpr(t2))); break;
11718             case 6:  assign(t4, unop(Iop_32to16,   mkexpr(t3))); break;
11719             case 7:  assign(t4, unop(Iop_32HIto16, mkexpr(t3))); break;
11720             default: vassert(0);
11721          }
11722          putIReg32(gregOfRexRM(pfx,modrm), unop(Iop_16Uto32, mkexpr(t4)));
11723          DIP("pextrw $%d,%s,%s\n",
11724              (Int)insn[3], nameXMMReg(eregOfRexRM(pfx,modrm)),
11725                            nameIReg32(gregOfRexRM(pfx,modrm)));
11726          delta += 4;
11727          goto decode_success;
11728       } 
11729       /* else fall through */
11730       /* note, if memory case is ever filled in, there is 1 byte after
11731          amode */
11732    }
11733
11734    /* 66 0F C4 = PINSRW -- get 16 bits from E(mem or low half ireg) and
11735       put it into the specified lane of xmm(G). */
11736    if (have66noF2noF3(pfx) 
11737        && (sz == 2 || /* ignore redundant REX.W */ sz == 8)
11738        && insn[0] == 0x0F && insn[1] == 0xC4) {
11739       Int lane;
11740       t4 = newTemp(Ity_I16);
11741       modrm = insn[2];
11742
11743       if (epartIsReg(modrm)) {
11744          assign(t4, getIReg16(eregOfRexRM(pfx,modrm)));
11745          delta += 3+1;
11746          lane = insn[3+1-1];
11747          DIP("pinsrw $%d,%s,%s\n", (Int)lane, 
11748                                    nameIReg16(eregOfRexRM(pfx,modrm)),
11749                                    nameXMMReg(gregOfRexRM(pfx,modrm)));
11750       } else {
11751          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 
11752                            1/*byte after the amode*/ );
11753          delta += 3+alen;
11754          lane = insn[3+alen-1];
11755          assign(t4, loadLE(Ity_I16, mkexpr(addr)));
11756          DIP("pinsrw $%d,%s,%s\n", (Int)lane,
11757                                    dis_buf,
11758                                    nameXMMReg(gregOfRexRM(pfx,modrm)));
11759      }
11760
11761       putXMMRegLane16( gregOfRexRM(pfx,modrm), lane & 7, mkexpr(t4) );
11762       goto decode_success;
11763    }
11764
11765    /* 66 0F F5 = PMADDWD -- Multiply and add packed integers from
11766       E(xmm or mem) to G(xmm) */
11767    if (have66noF2noF3(pfx) && sz == 2 
11768        && insn[0] == 0x0F && insn[1] == 0xF5) {
11769       IRTemp s1V  = newTemp(Ity_V128);
11770       IRTemp s2V  = newTemp(Ity_V128);
11771       IRTemp dV   = newTemp(Ity_V128);
11772       IRTemp s1Hi = newTemp(Ity_I64);
11773       IRTemp s1Lo = newTemp(Ity_I64);
11774       IRTemp s2Hi = newTemp(Ity_I64);
11775       IRTemp s2Lo = newTemp(Ity_I64);
11776       IRTemp dHi  = newTemp(Ity_I64);
11777       IRTemp dLo  = newTemp(Ity_I64);
11778       modrm = insn[2];
11779       if (epartIsReg(modrm)) {
11780          assign( s1V, getXMMReg(eregOfRexRM(pfx,modrm)) );
11781          delta += 2+1;
11782          DIP("pmaddwd %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)),
11783                                 nameXMMReg(gregOfRexRM(pfx,modrm)));
11784       } else {
11785          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
11786          assign( s1V, loadLE(Ity_V128, mkexpr(addr)) );
11787          delta += 2+alen;
11788          DIP("pmaddwd %s,%s\n", dis_buf,
11789                                 nameXMMReg(gregOfRexRM(pfx,modrm)));
11790       }
11791       assign( s2V, getXMMReg(gregOfRexRM(pfx,modrm)) );
11792       assign( s1Hi, unop(Iop_V128HIto64, mkexpr(s1V)) );
11793       assign( s1Lo, unop(Iop_V128to64,   mkexpr(s1V)) );
11794       assign( s2Hi, unop(Iop_V128HIto64, mkexpr(s2V)) );
11795       assign( s2Lo, unop(Iop_V128to64,   mkexpr(s2V)) );
11796       assign( dHi, mkIRExprCCall(
11797                       Ity_I64, 0/*regparms*/,
11798                       "amd64g_calculate_mmx_pmaddwd", 
11799                       &amd64g_calculate_mmx_pmaddwd,
11800                       mkIRExprVec_2( mkexpr(s1Hi), mkexpr(s2Hi))
11801                    ));
11802       assign( dLo, mkIRExprCCall(
11803                       Ity_I64, 0/*regparms*/,
11804                       "amd64g_calculate_mmx_pmaddwd", 
11805                       &amd64g_calculate_mmx_pmaddwd,
11806                       mkIRExprVec_2( mkexpr(s1Lo), mkexpr(s2Lo))
11807                    ));
11808       assign( dV, binop(Iop_64HLtoV128, mkexpr(dHi), mkexpr(dLo))) ;
11809       putXMMReg(gregOfRexRM(pfx,modrm), mkexpr(dV));
11810       goto decode_success;
11811    }
11812
11813    /* 66 0F EE = PMAXSW -- 16x8 signed max */
11814    if (have66noF2noF3(pfx) && sz == 2 
11815        && insn[0] == 0x0F && insn[1] == 0xEE) {
11816       delta = dis_SSEint_E_to_G( vbi, pfx, delta+2, 
11817                                  "pmaxsw", Iop_Max16Sx8, False );
11818       goto decode_success;
11819    }
11820
11821    /* 66 0F DE = PMAXUB -- 8x16 unsigned max */
11822    if (have66noF2noF3(pfx) && sz == 2 
11823        && insn[0] == 0x0F && insn[1] == 0xDE) {
11824       delta = dis_SSEint_E_to_G( vbi, pfx, delta+2, 
11825                                  "pmaxub", Iop_Max8Ux16, False );
11826       goto decode_success;
11827    }
11828
11829    /* 66 0F EA = PMINSW -- 16x8 signed min */
11830    if (have66noF2noF3(pfx) && sz == 2 
11831        && insn[0] == 0x0F && insn[1] == 0xEA) {
11832       delta = dis_SSEint_E_to_G( vbi, pfx, delta+2, 
11833                                  "pminsw", Iop_Min16Sx8, False );
11834       goto decode_success;
11835    }
11836
11837    /* 66 0F DA = PMINUB -- 8x16 unsigned min */
11838    if (have66noF2noF3(pfx) && sz == 2 
11839        && insn[0] == 0x0F && insn[1] == 0xDA) {
11840       delta = dis_SSEint_E_to_G( vbi, pfx, delta+2, 
11841                                  "pminub", Iop_Min8Ux16, False );
11842       goto decode_success;
11843    }
11844
11845    /* 66 0F D7 = PMOVMSKB -- extract sign bits from each of 16 lanes in
11846       xmm(E), turn them into a byte, and put zero-extend of it in
11847       ireg(G).  Doing this directly is just too cumbersome; give up
11848       therefore and call a helper. */
11849    /* UInt x86g_calculate_sse_pmovmskb ( ULong w64hi, ULong w64lo ); */
11850    if (have66noF2noF3(pfx) 
11851        && (sz == 2 || /* ignore redundant REX.W */ sz == 8)
11852        && insn[0] == 0x0F && insn[1] == 0xD7) {
11853       modrm = insn[2];
11854       if (epartIsReg(modrm)) {
11855          t0 = newTemp(Ity_I64);
11856          t1 = newTemp(Ity_I64);
11857          assign(t0, getXMMRegLane64(eregOfRexRM(pfx,modrm), 0));
11858          assign(t1, getXMMRegLane64(eregOfRexRM(pfx,modrm), 1));
11859          t5 = newTemp(Ity_I64);
11860          assign(t5, mkIRExprCCall(
11861                        Ity_I64, 0/*regparms*/, 
11862                        "amd64g_calculate_sse_pmovmskb",
11863                        &amd64g_calculate_sse_pmovmskb,
11864                        mkIRExprVec_2( mkexpr(t1), mkexpr(t0) )));
11865          putIReg32(gregOfRexRM(pfx,modrm), unop(Iop_64to32,mkexpr(t5)));
11866          DIP("pmovmskb %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)),
11867                                  nameIReg32(gregOfRexRM(pfx,modrm)));
11868          delta += 3;
11869          goto decode_success;
11870       } 
11871       /* else fall through */
11872    }
11873
11874    /* 66 0F E4 = PMULHUW -- 16x8 hi-half of unsigned widening multiply */
11875    if (have66noF2noF3(pfx) && sz == 2 
11876        && insn[0] == 0x0F && insn[1] == 0xE4) {
11877       delta = dis_SSEint_E_to_G( vbi, pfx, delta+2, 
11878                                  "pmulhuw", Iop_MulHi16Ux8, False );
11879       goto decode_success;
11880    }
11881
11882    /* 66 0F E5 = PMULHW -- 16x8 hi-half of signed widening multiply */
11883    if (have66noF2noF3(pfx) && sz == 2 
11884        && insn[0] == 0x0F && insn[1] == 0xE5) {
11885       delta = dis_SSEint_E_to_G( vbi, pfx, delta+2, 
11886                                  "pmulhw", Iop_MulHi16Sx8, False );
11887       goto decode_success;
11888    }
11889
11890    /* 66 0F D5 = PMULHL -- 16x8 multiply */
11891    if (have66noF2noF3(pfx) && sz == 2 
11892        && insn[0] == 0x0F && insn[1] == 0xD5) {
11893       delta = dis_SSEint_E_to_G( vbi, pfx, delta+2, 
11894                                  "pmullw", Iop_Mul16x8, False );
11895       goto decode_success;
11896    }
11897
11898    /* ***--- this is an MMX class insn introduced in SSE2 ---*** */
11899    /* 0F F4 = PMULUDQ -- unsigned widening multiply of 32-lanes 0 x
11900       0 to form 64-bit result */
11901    if (haveNo66noF2noF3(pfx) && sz == 4 
11902        && insn[0] == 0x0F && insn[1] == 0xF4) {
11903       IRTemp sV = newTemp(Ity_I64);
11904       IRTemp dV = newTemp(Ity_I64);
11905       t1 = newTemp(Ity_I32);
11906       t0 = newTemp(Ity_I32);
11907       modrm = insn[2];
11908
11909       do_MMX_preamble();
11910       assign( dV, getMMXReg(gregLO3ofRM(modrm)) );
11911
11912       if (epartIsReg(modrm)) {
11913          assign( sV, getMMXReg(eregLO3ofRM(modrm)) );
11914          delta += 2+1;
11915          DIP("pmuludq %s,%s\n", nameMMXReg(eregLO3ofRM(modrm)),
11916                                 nameMMXReg(gregLO3ofRM(modrm)));
11917       } else {
11918          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
11919          assign( sV, loadLE(Ity_I64, mkexpr(addr)) );
11920          delta += 2+alen;
11921          DIP("pmuludq %s,%s\n", dis_buf,
11922                                 nameMMXReg(gregLO3ofRM(modrm)));
11923       }
11924
11925       assign( t0, unop(Iop_64to32, mkexpr(dV)) );
11926       assign( t1, unop(Iop_64to32, mkexpr(sV)) );
11927       putMMXReg( gregLO3ofRM(modrm),
11928                  binop( Iop_MullU32, mkexpr(t0), mkexpr(t1) ) );
11929       goto decode_success;
11930    }
11931
11932    /* 66 0F F4 = PMULUDQ -- unsigned widening multiply of 32-lanes 0 x
11933       0 to form lower 64-bit half and lanes 2 x 2 to form upper 64-bit
11934       half */
11935    /* This is a really poor translation -- could be improved if
11936       performance critical */
11937    if (have66noF2noF3(pfx) && sz == 2 
11938        && insn[0] == 0x0F && insn[1] == 0xF4) {
11939       IRTemp sV, dV;
11940       IRTemp s3, s2, s1, s0, d3, d2, d1, d0;
11941       sV = newTemp(Ity_V128);
11942       dV = newTemp(Ity_V128);
11943       s3 = s2 = s1 = s0 = d3 = d2 = d1 = d0 = IRTemp_INVALID;
11944       t1 = newTemp(Ity_I64);
11945       t0 = newTemp(Ity_I64);
11946       modrm = insn[2];
11947       assign( dV, getXMMReg(gregOfRexRM(pfx,modrm)) );
11948
11949       if (epartIsReg(modrm)) {
11950          assign( sV, getXMMReg(eregOfRexRM(pfx,modrm)) );
11951          delta += 2+1;
11952          DIP("pmuludq %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)),
11953                                 nameXMMReg(gregOfRexRM(pfx,modrm)));
11954       } else {
11955          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
11956          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
11957          delta += 2+alen;
11958          DIP("pmuludq %s,%s\n", dis_buf,
11959                                 nameXMMReg(gregOfRexRM(pfx,modrm)));
11960       }
11961
11962       breakup128to32s( dV, &d3, &d2, &d1, &d0 );
11963       breakup128to32s( sV, &s3, &s2, &s1, &s0 );
11964
11965       assign( t0, binop( Iop_MullU32, mkexpr(d0), mkexpr(s0)) );
11966       putXMMRegLane64( gregOfRexRM(pfx,modrm), 0, mkexpr(t0) );
11967       assign( t1, binop( Iop_MullU32, mkexpr(d2), mkexpr(s2)) );
11968       putXMMRegLane64( gregOfRexRM(pfx,modrm), 1, mkexpr(t1) );
11969       goto decode_success;
11970    }
11971
11972    /* 66 0F EB = POR */
11973    if (have66noF2noF3(pfx) && sz == 2 
11974        && insn[0] == 0x0F && insn[1] == 0xEB) {
11975       delta = dis_SSE_E_to_G_all( vbi, pfx, delta+2, "por", Iop_OrV128 );
11976       goto decode_success;
11977    }
11978
11979    /* 66 0F F6 = PSADBW -- 2 x (8x8 -> 48 zeroes ++ u16) Sum Abs Diffs
11980       from E(xmm or mem) to G(xmm) */
11981    if (have66noF2noF3(pfx) && sz == 2 
11982        && insn[0] == 0x0F && insn[1] == 0xF6) {
11983       IRTemp s1V  = newTemp(Ity_V128);
11984       IRTemp s2V  = newTemp(Ity_V128);
11985       IRTemp dV   = newTemp(Ity_V128);
11986       IRTemp s1Hi = newTemp(Ity_I64);
11987       IRTemp s1Lo = newTemp(Ity_I64);
11988       IRTemp s2Hi = newTemp(Ity_I64);
11989       IRTemp s2Lo = newTemp(Ity_I64);
11990       IRTemp dHi  = newTemp(Ity_I64);
11991       IRTemp dLo  = newTemp(Ity_I64);
11992       modrm = insn[2];
11993       if (epartIsReg(modrm)) {
11994          assign( s1V, getXMMReg(eregOfRexRM(pfx,modrm)) );
11995          delta += 2+1;
11996          DIP("psadbw %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)),
11997                                nameXMMReg(gregOfRexRM(pfx,modrm)));
11998       } else {
11999          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
12000          assign( s1V, loadLE(Ity_V128, mkexpr(addr)) );
12001          delta += 2+alen;
12002          DIP("psadbw %s,%s\n", dis_buf,
12003                                nameXMMReg(gregOfRexRM(pfx,modrm)));
12004       }
12005       assign( s2V, getXMMReg(gregOfRexRM(pfx,modrm)) );
12006       assign( s1Hi, unop(Iop_V128HIto64, mkexpr(s1V)) );
12007       assign( s1Lo, unop(Iop_V128to64,   mkexpr(s1V)) );
12008       assign( s2Hi, unop(Iop_V128HIto64, mkexpr(s2V)) );
12009       assign( s2Lo, unop(Iop_V128to64,   mkexpr(s2V)) );
12010       assign( dHi, mkIRExprCCall(
12011                       Ity_I64, 0/*regparms*/,
12012                       "amd64g_calculate_mmx_psadbw", 
12013                       &amd64g_calculate_mmx_psadbw,
12014                       mkIRExprVec_2( mkexpr(s1Hi), mkexpr(s2Hi))
12015                    ));
12016       assign( dLo, mkIRExprCCall(
12017                       Ity_I64, 0/*regparms*/,
12018                       "amd64g_calculate_mmx_psadbw", 
12019                       &amd64g_calculate_mmx_psadbw,
12020                       mkIRExprVec_2( mkexpr(s1Lo), mkexpr(s2Lo))
12021                    ));
12022       assign( dV, binop(Iop_64HLtoV128, mkexpr(dHi), mkexpr(dLo))) ;
12023       putXMMReg(gregOfRexRM(pfx,modrm), mkexpr(dV));
12024       goto decode_success;
12025    }
12026
12027    /* 66 0F 70 = PSHUFD -- rearrange 4x32 from E(xmm or mem) to G(xmm) */
12028    if (have66noF2noF3(pfx) && sz == 2 
12029        && insn[0] == 0x0F && insn[1] == 0x70) {
12030       Int order;
12031       IRTemp sV, dV, s3, s2, s1, s0;
12032       s3 = s2 = s1 = s0 = IRTemp_INVALID;
12033       sV = newTemp(Ity_V128);
12034       dV = newTemp(Ity_V128);
12035       modrm = insn[2];
12036       if (epartIsReg(modrm)) {
12037          assign( sV, getXMMReg(eregOfRexRM(pfx,modrm)) );
12038          order = (Int)insn[3];
12039          delta += 3+1;
12040          DIP("pshufd $%d,%s,%s\n", order, 
12041                                    nameXMMReg(eregOfRexRM(pfx,modrm)),
12042                                    nameXMMReg(gregOfRexRM(pfx,modrm)));
12043       } else {
12044          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 
12045                            1/*byte after the amode*/ );
12046          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
12047          order = (Int)insn[2+alen];
12048          delta += 2+alen+1;
12049          DIP("pshufd $%d,%s,%s\n", order, 
12050                                    dis_buf,
12051                                    nameXMMReg(gregOfRexRM(pfx,modrm)));
12052       }
12053       breakup128to32s( sV, &s3, &s2, &s1, &s0 );
12054
12055 #     define SEL(n) \
12056                 ((n)==0 ? s0 : ((n)==1 ? s1 : ((n)==2 ? s2 : s3)))
12057       assign(dV,
12058              mk128from32s( SEL((order>>6)&3), SEL((order>>4)&3),
12059                            SEL((order>>2)&3), SEL((order>>0)&3) )
12060       );
12061       putXMMReg(gregOfRexRM(pfx,modrm), mkexpr(dV));
12062 #     undef SEL
12063       goto decode_success;
12064    }
12065
12066    /* F3 0F 70 = PSHUFHW -- rearrange upper half 4x16 from E(xmm or
12067       mem) to G(xmm), and copy lower half */
12068    if (haveF3no66noF2(pfx) && sz == 4 
12069        && insn[0] == 0x0F && insn[1] == 0x70) {
12070       Int order;
12071       IRTemp sVhi, dVhi, sV, dV, s3, s2, s1, s0;
12072       s3 = s2 = s1 = s0 = IRTemp_INVALID;
12073       sV   = newTemp(Ity_V128);
12074       dV   = newTemp(Ity_V128);
12075       sVhi = newTemp(Ity_I64);
12076       dVhi = newTemp(Ity_I64);
12077       modrm = insn[2];
12078       if (epartIsReg(modrm)) {
12079          assign( sV, getXMMReg(eregOfRexRM(pfx,modrm)) );
12080          order = (Int)insn[3];
12081          delta += 3+1;
12082          DIP("pshufhw $%d,%s,%s\n", order, 
12083                                     nameXMMReg(eregOfRexRM(pfx,modrm)),
12084                                     nameXMMReg(gregOfRexRM(pfx,modrm)));
12085       } else {
12086          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 
12087                            1/*byte after the amode*/ );
12088          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
12089          order = (Int)insn[2+alen];
12090          delta += 2+alen+1;
12091          DIP("pshufhw $%d,%s,%s\n", order, 
12092                                     dis_buf,
12093                                     nameXMMReg(gregOfRexRM(pfx,modrm)));
12094       }
12095       assign( sVhi, unop(Iop_V128HIto64, mkexpr(sV)) );
12096       breakup64to16s( sVhi, &s3, &s2, &s1, &s0 );
12097
12098 #     define SEL(n) \
12099                 ((n)==0 ? s0 : ((n)==1 ? s1 : ((n)==2 ? s2 : s3)))
12100       assign(dVhi,
12101              mk64from16s( SEL((order>>6)&3), SEL((order>>4)&3),
12102                           SEL((order>>2)&3), SEL((order>>0)&3) )
12103       );
12104       assign(dV, binop( Iop_64HLtoV128, 
12105                         mkexpr(dVhi),
12106                         unop(Iop_V128to64, mkexpr(sV))) );
12107       putXMMReg(gregOfRexRM(pfx,modrm), mkexpr(dV));
12108 #     undef SEL
12109       goto decode_success;
12110    }
12111
12112    /* F2 0F 70 = PSHUFLW -- rearrange lower half 4x16 from E(xmm or
12113       mem) to G(xmm), and copy upper half */
12114    if (haveF2no66noF3(pfx) && sz == 4 
12115        && insn[0] == 0x0F && insn[1] == 0x70) {
12116       Int order;
12117       IRTemp sVlo, dVlo, sV, dV, s3, s2, s1, s0;
12118       s3 = s2 = s1 = s0 = IRTemp_INVALID;
12119       sV   = newTemp(Ity_V128);
12120       dV   = newTemp(Ity_V128);
12121       sVlo = newTemp(Ity_I64);
12122       dVlo = newTemp(Ity_I64);
12123       modrm = insn[2];
12124       if (epartIsReg(modrm)) {
12125          assign( sV, getXMMReg(eregOfRexRM(pfx,modrm)) );
12126          order = (Int)insn[3];
12127          delta += 3+1;
12128          DIP("pshuflw $%d,%s,%s\n", order, 
12129                                     nameXMMReg(eregOfRexRM(pfx,modrm)),
12130                                     nameXMMReg(gregOfRexRM(pfx,modrm)));
12131       } else {
12132          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 
12133                            1/*byte after the amode*/ );
12134          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
12135          order = (Int)insn[2+alen];
12136          delta += 2+alen+1;
12137          DIP("pshuflw $%d,%s,%s\n", order, 
12138                                     dis_buf,
12139                                     nameXMMReg(gregOfRexRM(pfx,modrm)));
12140       }
12141       assign( sVlo, unop(Iop_V128to64, mkexpr(sV)) );
12142       breakup64to16s( sVlo, &s3, &s2, &s1, &s0 );
12143
12144 #     define SEL(n) \
12145                 ((n)==0 ? s0 : ((n)==1 ? s1 : ((n)==2 ? s2 : s3)))
12146       assign(dVlo,
12147              mk64from16s( SEL((order>>6)&3), SEL((order>>4)&3),
12148                           SEL((order>>2)&3), SEL((order>>0)&3) )
12149       );
12150       assign(dV, binop( Iop_64HLtoV128,
12151                         unop(Iop_V128HIto64, mkexpr(sV)),
12152                         mkexpr(dVlo) ) );
12153       putXMMReg(gregOfRexRM(pfx,modrm), mkexpr(dV));
12154 #     undef SEL
12155       goto decode_success;
12156    }
12157
12158    /* 66 0F 72 /6 ib = PSLLD by immediate */
12159    if (have66noF2noF3(pfx) && sz == 2 
12160        && insn[0] == 0x0F && insn[1] == 0x72
12161        && epartIsReg(insn[2])
12162        && gregLO3ofRM(insn[2]) == 6) {
12163       delta = dis_SSE_shiftE_imm( pfx, delta+2, "pslld", Iop_ShlN32x4 );
12164       goto decode_success;
12165    }
12166
12167    /* 66 0F F2 = PSLLD by E */
12168    if (have66noF2noF3(pfx) && sz == 2 
12169        && insn[0] == 0x0F && insn[1] == 0xF2) {
12170       delta = dis_SSE_shiftG_byE( vbi, pfx, delta+2, "pslld", Iop_ShlN32x4 );
12171       goto decode_success;
12172    }
12173
12174    /* 66 0F 73 /7 ib = PSLLDQ by immediate */
12175    /* note, if mem case ever filled in, 1 byte after amode */
12176    if (have66noF2noF3(pfx) && sz == 2 
12177        && insn[0] == 0x0F && insn[1] == 0x73
12178        && epartIsReg(insn[2])
12179        && gregLO3ofRM(insn[2]) == 7) {
12180       IRTemp sV, dV, hi64, lo64, hi64r, lo64r;
12181       Int    imm = (Int)insn[3];
12182       Int    reg = eregOfRexRM(pfx,insn[2]);
12183       DIP("pslldq $%d,%s\n", imm, nameXMMReg(reg));
12184       vassert(imm >= 0 && imm <= 255);
12185       delta += 4;
12186
12187       sV    = newTemp(Ity_V128);
12188       dV    = newTemp(Ity_V128);
12189       hi64  = newTemp(Ity_I64);
12190       lo64  = newTemp(Ity_I64);
12191       hi64r = newTemp(Ity_I64);
12192       lo64r = newTemp(Ity_I64);
12193
12194       if (imm >= 16) {
12195          putXMMReg(reg, mkV128(0x0000));
12196          goto decode_success;
12197       }
12198
12199       assign( sV, getXMMReg(reg) );
12200       assign( hi64, unop(Iop_V128HIto64, mkexpr(sV)) );
12201       assign( lo64, unop(Iop_V128to64, mkexpr(sV)) );
12202
12203       if (imm == 0) {
12204          assign( lo64r, mkexpr(lo64) );
12205          assign( hi64r, mkexpr(hi64) );
12206       }
12207       else
12208       if (imm == 8) {
12209          assign( lo64r, mkU64(0) );
12210          assign( hi64r, mkexpr(lo64) );
12211       }
12212       else
12213       if (imm > 8) {
12214          assign( lo64r, mkU64(0) );
12215          assign( hi64r, binop( Iop_Shl64, 
12216                                mkexpr(lo64),
12217                                mkU8( 8*(imm-8) ) ));
12218       } else {
12219          assign( lo64r, binop( Iop_Shl64, 
12220                                mkexpr(lo64),
12221                                mkU8(8 * imm) ));
12222          assign( hi64r, 
12223                  binop( Iop_Or64,
12224                         binop(Iop_Shl64, mkexpr(hi64), 
12225                                          mkU8(8 * imm)),
12226                         binop(Iop_Shr64, mkexpr(lo64),
12227                                          mkU8(8 * (8 - imm)) )
12228                       )
12229                );
12230       }
12231       assign( dV, binop(Iop_64HLtoV128, mkexpr(hi64r), mkexpr(lo64r)) );
12232       putXMMReg(reg, mkexpr(dV));
12233       goto decode_success;
12234    }
12235
12236    /* 66 0F 73 /6 ib = PSLLQ by immediate */
12237    if (have66noF2noF3(pfx) && sz == 2 
12238        && insn[0] == 0x0F && insn[1] == 0x73
12239        && epartIsReg(insn[2])
12240        && gregLO3ofRM(insn[2]) == 6) {
12241       delta = dis_SSE_shiftE_imm( pfx, delta+2, "psllq", Iop_ShlN64x2 );
12242       goto decode_success;
12243    }
12244
12245    /* 66 0F F3 = PSLLQ by E */
12246    if (have66noF2noF3(pfx) && sz == 2 
12247        && insn[0] == 0x0F && insn[1] == 0xF3) {
12248       delta = dis_SSE_shiftG_byE( vbi, pfx, delta+2, "psllq", Iop_ShlN64x2 );
12249       goto decode_success;
12250    }
12251
12252    /* 66 0F 71 /6 ib = PSLLW by immediate */
12253    if (have66noF2noF3(pfx) && sz == 2 
12254        && insn[0] == 0x0F && insn[1] == 0x71
12255        && epartIsReg(insn[2])
12256        && gregLO3ofRM(insn[2]) == 6) {
12257       delta = dis_SSE_shiftE_imm( pfx, delta+2, "psllw", Iop_ShlN16x8 );
12258       goto decode_success;
12259    }
12260
12261    /* 66 0F F1 = PSLLW by E */
12262    if (have66noF2noF3(pfx) && sz == 2 
12263        && insn[0] == 0x0F && insn[1] == 0xF1) {
12264       delta = dis_SSE_shiftG_byE( vbi, pfx, delta+2, "psllw", Iop_ShlN16x8 );
12265       goto decode_success;
12266    }
12267
12268    /* 66 0F 72 /4 ib = PSRAD by immediate */
12269    if (have66noF2noF3(pfx) && sz == 2 
12270        && insn[0] == 0x0F && insn[1] == 0x72
12271        && epartIsReg(insn[2])
12272        && gregLO3ofRM(insn[2]) == 4) {
12273       delta = dis_SSE_shiftE_imm( pfx, delta+2, "psrad", Iop_SarN32x4 );
12274       goto decode_success;
12275    }
12276
12277    /* 66 0F E2 = PSRAD by E */
12278    if (have66noF2noF3(pfx) && sz == 2 
12279        && insn[0] == 0x0F && insn[1] == 0xE2) {
12280       delta = dis_SSE_shiftG_byE( vbi, pfx, delta+2, "psrad", Iop_SarN32x4 );
12281       goto decode_success;
12282    }
12283
12284    /* 66 0F 71 /4 ib = PSRAW by immediate */
12285    if (have66noF2noF3(pfx) && sz == 2 
12286        && insn[0] == 0x0F && insn[1] == 0x71
12287        && epartIsReg(insn[2])
12288        && gregLO3ofRM(insn[2]) == 4) {
12289       delta = dis_SSE_shiftE_imm( pfx, delta+2, "psraw", Iop_SarN16x8 );
12290       goto decode_success;
12291    }
12292
12293    /* 66 0F E1 = PSRAW by E */
12294    if (have66noF2noF3(pfx) && sz == 2 
12295        && insn[0] == 0x0F && insn[1] == 0xE1) {
12296       delta = dis_SSE_shiftG_byE( vbi, pfx, delta+2, "psraw", Iop_SarN16x8 );
12297       goto decode_success;
12298    }
12299
12300    /* 66 0F 72 /2 ib = PSRLD by immediate */
12301    if (have66noF2noF3(pfx) && sz == 2 
12302        && insn[0] == 0x0F && insn[1] == 0x72
12303        && epartIsReg(insn[2])
12304        && gregLO3ofRM(insn[2]) == 2) {
12305       delta = dis_SSE_shiftE_imm( pfx, delta+2, "psrld", Iop_ShrN32x4 );
12306       goto decode_success;
12307    }
12308
12309    /* 66 0F D2 = PSRLD by E */
12310    if (have66noF2noF3(pfx) && sz == 2 
12311        && insn[0] == 0x0F && insn[1] == 0xD2) {
12312       delta = dis_SSE_shiftG_byE( vbi, pfx, delta+2, "psrld", Iop_ShrN32x4 );
12313       goto decode_success;
12314    }
12315
12316    /* 66 0F 73 /3 ib = PSRLDQ by immediate */
12317    /* note, if mem case ever filled in, 1 byte after amode */
12318    if (have66noF2noF3(pfx) && sz == 2 
12319        && insn[0] == 0x0F && insn[1] == 0x73
12320        && epartIsReg(insn[2])
12321        && gregLO3ofRM(insn[2]) == 3) {
12322       IRTemp sV, dV, hi64, lo64, hi64r, lo64r;
12323       Int    imm = (Int)insn[3];
12324       Int    reg = eregOfRexRM(pfx,insn[2]);
12325       DIP("psrldq $%d,%s\n", imm, nameXMMReg(reg));
12326       vassert(imm >= 0 && imm <= 255);
12327       delta += 4;
12328
12329       sV    = newTemp(Ity_V128);
12330       dV    = newTemp(Ity_V128);
12331       hi64  = newTemp(Ity_I64);
12332       lo64  = newTemp(Ity_I64);
12333       hi64r = newTemp(Ity_I64);
12334       lo64r = newTemp(Ity_I64);
12335
12336       if (imm >= 16) {
12337          putXMMReg(reg, mkV128(0x0000));
12338          goto decode_success;
12339       }
12340
12341       assign( sV, getXMMReg(reg) );
12342       assign( hi64, unop(Iop_V128HIto64, mkexpr(sV)) );
12343       assign( lo64, unop(Iop_V128to64, mkexpr(sV)) );
12344
12345       if (imm == 0) {
12346          assign( lo64r, mkexpr(lo64) );
12347          assign( hi64r, mkexpr(hi64) );
12348       }
12349       else
12350       if (imm == 8) {
12351          assign( hi64r, mkU64(0) );
12352          assign( lo64r, mkexpr(hi64) );
12353       }
12354       else 
12355       if (imm > 8) {
12356          assign( hi64r, mkU64(0) );
12357          assign( lo64r, binop( Iop_Shr64, 
12358                                mkexpr(hi64),
12359                                mkU8( 8*(imm-8) ) ));
12360       } else {
12361          assign( hi64r, binop( Iop_Shr64, 
12362                                mkexpr(hi64),
12363                                mkU8(8 * imm) ));
12364          assign( lo64r, 
12365                  binop( Iop_Or64,
12366                         binop(Iop_Shr64, mkexpr(lo64), 
12367                                          mkU8(8 * imm)),
12368                         binop(Iop_Shl64, mkexpr(hi64),
12369                                          mkU8(8 * (8 - imm)) )
12370                       )
12371                );
12372       }
12373
12374       assign( dV, binop(Iop_64HLtoV128, mkexpr(hi64r), mkexpr(lo64r)) );
12375       putXMMReg(reg, mkexpr(dV));
12376       goto decode_success;
12377    }
12378
12379    /* 66 0F 73 /2 ib = PSRLQ by immediate */
12380    if (have66noF2noF3(pfx) && sz == 2 
12381        && insn[0] == 0x0F && insn[1] == 0x73
12382        && epartIsReg(insn[2])
12383        && gregLO3ofRM(insn[2]) == 2) {
12384       delta = dis_SSE_shiftE_imm( pfx, delta+2, "psrlq", Iop_ShrN64x2 );
12385       goto decode_success;
12386    }
12387
12388    /* 66 0F D3 = PSRLQ by E */
12389    if (have66noF2noF3(pfx) && sz == 2
12390        && insn[0] == 0x0F && insn[1] == 0xD3) {
12391       delta = dis_SSE_shiftG_byE( vbi, pfx, delta+2, "psrlq", Iop_ShrN64x2 );
12392       goto decode_success;
12393    }
12394
12395    /* 66 0F 71 /2 ib = PSRLW by immediate */
12396    if (have66noF2noF3(pfx) && sz == 2 
12397        && insn[0] == 0x0F && insn[1] == 0x71
12398        && epartIsReg(insn[2])
12399        && gregLO3ofRM(insn[2]) == 2) {
12400       delta = dis_SSE_shiftE_imm( pfx, delta+2, "psrlw", Iop_ShrN16x8 );
12401       goto decode_success;
12402    }
12403
12404    /* 66 0F D1 = PSRLW by E */
12405    if (have66noF2noF3(pfx) && sz == 2 
12406        && insn[0] == 0x0F && insn[1] == 0xD1) {
12407       delta = dis_SSE_shiftG_byE( vbi, pfx, delta+2, "psrlw", Iop_ShrN16x8 );
12408       goto decode_success;
12409    }
12410
12411    /* 66 0F F8 = PSUBB */
12412    if (have66noF2noF3(pfx) && sz == 2 
12413        && insn[0] == 0x0F && insn[1] == 0xF8) {
12414       delta = dis_SSEint_E_to_G( vbi, pfx, delta+2, 
12415                                  "psubb", Iop_Sub8x16, False );
12416       goto decode_success;
12417    }
12418
12419    /* 66 0F FA = PSUBD */
12420    if (have66noF2noF3(pfx) && sz == 2 
12421        && insn[0] == 0x0F && insn[1] == 0xFA) {
12422       delta = dis_SSEint_E_to_G( vbi, pfx, delta+2, 
12423                                  "psubd", Iop_Sub32x4, False );
12424       goto decode_success;
12425    }
12426
12427    /* ***--- this is an MMX class insn introduced in SSE2 ---*** */
12428    /* 0F FB = PSUBQ -- sub 64x1 */
12429    if (haveNo66noF2noF3(pfx) && sz == 4 
12430        && insn[0] == 0x0F && insn[1] == 0xFB) {
12431       do_MMX_preamble();
12432       delta = dis_MMXop_regmem_to_reg ( 
12433                 vbi, pfx, delta+2, insn[1], "psubq", False );
12434       goto decode_success;
12435    }
12436
12437    /* 66 0F FB = PSUBQ */
12438    if (have66noF2noF3(pfx) && sz == 2 
12439        && insn[0] == 0x0F && insn[1] == 0xFB) {
12440       delta = dis_SSEint_E_to_G( vbi, pfx, delta+2, 
12441                                  "psubq", Iop_Sub64x2, False );
12442       goto decode_success;
12443    }
12444
12445    /* 66 0F F9 = PSUBW */
12446    if (have66noF2noF3(pfx) && sz == 2 
12447        && insn[0] == 0x0F && insn[1] == 0xF9) {
12448       delta = dis_SSEint_E_to_G( vbi, pfx, delta+2, 
12449                                  "psubw", Iop_Sub16x8, False );
12450       goto decode_success;
12451    }
12452
12453    /* 66 0F E8 = PSUBSB */
12454    if (have66noF2noF3(pfx) && sz == 2 
12455        && insn[0] == 0x0F && insn[1] == 0xE8) {
12456       delta = dis_SSEint_E_to_G( vbi, pfx, delta+2, 
12457                                  "psubsb", Iop_QSub8Sx16, False );
12458       goto decode_success;
12459    }
12460
12461    /* 66 0F E9 = PSUBSW */
12462    if (have66noF2noF3(pfx) && sz == 2 
12463        && insn[0] == 0x0F && insn[1] == 0xE9) {
12464       delta = dis_SSEint_E_to_G( vbi, pfx, delta+2, 
12465                                  "psubsw", Iop_QSub16Sx8, False );
12466       goto decode_success;
12467    }
12468
12469    /* 66 0F D8 = PSUBSB */
12470    if (have66noF2noF3(pfx) && sz == 2 
12471        && insn[0] == 0x0F && insn[1] == 0xD8) {
12472       delta = dis_SSEint_E_to_G( vbi, pfx, delta+2, 
12473                                  "psubusb", Iop_QSub8Ux16, False );
12474       goto decode_success;
12475    }
12476
12477    /* 66 0F D9 = PSUBSW */
12478    if (have66noF2noF3(pfx) && sz == 2 
12479        && insn[0] == 0x0F && insn[1] == 0xD9) {
12480       delta = dis_SSEint_E_to_G( vbi, pfx, delta+2, 
12481                                  "psubusw", Iop_QSub16Ux8, False );
12482       goto decode_success;
12483    }
12484
12485    /* 66 0F 68 = PUNPCKHBW */
12486    if (have66noF2noF3(pfx) && sz == 2 
12487        && insn[0] == 0x0F && insn[1] == 0x68) {
12488       delta = dis_SSEint_E_to_G( vbi, pfx, delta+2, 
12489                                  "punpckhbw",
12490                                  Iop_InterleaveHI8x16, True );
12491       goto decode_success;
12492    }
12493
12494    /* 66 0F 6A = PUNPCKHDQ */
12495    if (have66noF2noF3(pfx) && sz == 2 
12496        && insn[0] == 0x0F && insn[1] == 0x6A) {
12497       delta = dis_SSEint_E_to_G( vbi, pfx, delta+2, 
12498                                  "punpckhdq",
12499                                  Iop_InterleaveHI32x4, True );
12500       goto decode_success;
12501    }
12502
12503    /* 66 0F 6D = PUNPCKHQDQ */
12504    if (have66noF2noF3(pfx) && sz == 2 
12505        && insn[0] == 0x0F && insn[1] == 0x6D) {
12506       delta = dis_SSEint_E_to_G( vbi, pfx, delta+2, 
12507                                  "punpckhqdq",
12508                                  Iop_InterleaveHI64x2, True );
12509       goto decode_success;
12510    }
12511
12512    /* 66 0F 69 = PUNPCKHWD */
12513    if (have66noF2noF3(pfx) && sz == 2 
12514        && insn[0] == 0x0F && insn[1] == 0x69) {
12515       delta = dis_SSEint_E_to_G( vbi, pfx, delta+2, 
12516                                  "punpckhwd",
12517                                  Iop_InterleaveHI16x8, True );
12518       goto decode_success;
12519    }
12520
12521    /* 66 0F 60 = PUNPCKLBW */
12522    if (have66noF2noF3(pfx) && sz == 2 
12523        && insn[0] == 0x0F && insn[1] == 0x60) {
12524       delta = dis_SSEint_E_to_G( vbi, pfx, delta+2, 
12525                                  "punpcklbw",
12526                                  Iop_InterleaveLO8x16, True );
12527       goto decode_success;
12528    }
12529
12530    /* 66 0F 62 = PUNPCKLDQ */
12531    if (have66noF2noF3(pfx) && sz == 2 
12532        && insn[0] == 0x0F && insn[1] == 0x62) {
12533       delta = dis_SSEint_E_to_G( vbi, pfx, delta+2, 
12534                                  "punpckldq",
12535                                  Iop_InterleaveLO32x4, True );
12536       goto decode_success;
12537    }
12538
12539    /* 66 0F 6C = PUNPCKLQDQ */
12540    if (have66noF2noF3(pfx) && sz == 2 
12541        && insn[0] == 0x0F && insn[1] == 0x6C) {
12542       delta = dis_SSEint_E_to_G( vbi, pfx, delta+2, 
12543                                  "punpcklqdq",
12544                                  Iop_InterleaveLO64x2, True );
12545       goto decode_success;
12546    }
12547
12548    /* 66 0F 61 = PUNPCKLWD */
12549    if (have66noF2noF3(pfx) && sz == 2 
12550        && insn[0] == 0x0F && insn[1] == 0x61) {
12551       delta = dis_SSEint_E_to_G( vbi, pfx, delta+2, 
12552                                  "punpcklwd",
12553                                  Iop_InterleaveLO16x8, True );
12554       goto decode_success;
12555    }
12556
12557    /* 66 0F EF = PXOR */
12558    if (have66noF2noF3(pfx) && sz == 2 
12559        && insn[0] == 0x0F && insn[1] == 0xEF) {
12560       delta = dis_SSE_E_to_G_all( vbi, pfx, delta+2, "pxor", Iop_XorV128 );
12561       goto decode_success;
12562    }
12563
12564 //.. //--    /* FXSAVE/FXRSTOR m32 -- load/store the FPU/MMX/SSE state. */
12565 //.. //--    if (insn[0] == 0x0F && insn[1] == 0xAE 
12566 //.. //--        && (!epartIsReg(insn[2]))
12567 //.. //--        && (gregOfRM(insn[2]) == 1 || gregOfRM(insn[2]) == 0) ) {
12568 //.. //--       Bool store = gregOfRM(insn[2]) == 0;
12569 //.. //--       vg_assert(sz == 4);
12570 //.. //--       pair = disAMode ( cb, sorb, eip+2, dis_buf );
12571 //.. //--       t1   = LOW24(pair);
12572 //.. //--       eip += 2+HI8(pair);
12573 //.. //--       uInstr3(cb, store ? SSE2a_MemWr : SSE2a_MemRd, 512,
12574 //.. //--                   Lit16, (((UShort)insn[0]) << 8) | (UShort)insn[1],
12575 //.. //--                   Lit16, (UShort)insn[2],
12576 //.. //--                   TempReg, t1 );
12577 //.. //--       DIP("fx%s %s\n", store ? "save" : "rstor", dis_buf );
12578 //.. //--       goto decode_success;
12579 //.. //--    }
12580
12581    /* 0F AE /7 = CLFLUSH -- flush cache line */
12582    if (haveNo66noF2noF3(pfx) && sz == 4 
12583        && insn[0] == 0x0F && insn[1] == 0xAE
12584        && !epartIsReg(insn[2]) && gregLO3ofRM(insn[2]) == 7) {
12585
12586       /* This is something of a hack.  We need to know the size of the
12587          cache line containing addr.  Since we don't (easily), assume
12588          256 on the basis that no real cache would have a line that
12589          big.  It's safe to invalidate more stuff than we need, just
12590          inefficient. */
12591       ULong lineszB = 256ULL;
12592
12593       addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
12594       delta += 2+alen;
12595
12596       /* Round addr down to the start of the containing block. */
12597       stmt( IRStmt_Put(
12598                OFFB_TISTART,
12599                binop( Iop_And64, 
12600                       mkexpr(addr), 
12601                       mkU64( ~(lineszB-1) ))) );
12602
12603       stmt( IRStmt_Put(OFFB_TILEN, mkU64(lineszB) ) );
12604
12605       irsb->jumpkind = Ijk_TInval;
12606       irsb->next     = mkU64(guest_RIP_bbstart+delta);
12607       dres.whatNext  = Dis_StopHere;
12608
12609       DIP("clflush %s\n", dis_buf);
12610       goto decode_success;
12611    }
12612
12613    /* ---------------------------------------------------- */
12614    /* --- end of the SSE/SSE2 decoder.                 --- */
12615    /* ---------------------------------------------------- */
12616
12617    /* ---------------------------------------------------- */
12618    /* --- start of the SSE3 decoder.                   --- */
12619    /* ---------------------------------------------------- */
12620
12621    /* F3 0F 12 = MOVSLDUP -- move from E (mem or xmm) to G (xmm),
12622       duplicating some lanes (2:2:0:0). */
12623    /* F3 0F 16 = MOVSHDUP -- move from E (mem or xmm) to G (xmm),
12624       duplicating some lanes (3:3:1:1). */
12625    if (haveF3no66noF2(pfx) && sz == 4
12626        && insn[0] == 0x0F && (insn[1] == 0x12 || insn[1] == 0x16)) {
12627       IRTemp s3, s2, s1, s0;
12628       IRTemp sV  = newTemp(Ity_V128);
12629       Bool   isH = insn[1] == 0x16;
12630       s3 = s2 = s1 = s0 = IRTemp_INVALID;
12631
12632       modrm = insn[2];
12633       if (epartIsReg(modrm)) {
12634          assign( sV, getXMMReg( eregOfRexRM(pfx,modrm)) );
12635          DIP("movs%cdup %s,%s\n", isH ? 'h' : 'l',
12636                                   nameXMMReg(eregOfRexRM(pfx,modrm)),
12637                                   nameXMMReg(gregOfRexRM(pfx,modrm)));
12638          delta += 2+1;
12639       } else {
12640          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
12641          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
12642          DIP("movs%cdup %s,%s\n", isH ? 'h' : 'l',
12643              dis_buf,
12644              nameXMMReg(gregOfRexRM(pfx,modrm)));
12645          delta += 2+alen;
12646       }
12647
12648       breakup128to32s( sV, &s3, &s2, &s1, &s0 );
12649       putXMMReg( gregOfRexRM(pfx,modrm), 
12650                  isH ? mk128from32s( s3, s3, s1, s1 )
12651                      : mk128from32s( s2, s2, s0, s0 ) );
12652       goto decode_success;
12653    }
12654
12655    /* F2 0F 12 = MOVDDUP -- move from E (mem or xmm) to G (xmm),
12656       duplicating some lanes (0:1:0:1). */
12657    if (haveF2no66noF3(pfx) 
12658        && (sz == 4 || /* ignore redundant REX.W */ sz == 8)
12659        && insn[0] == 0x0F && insn[1] == 0x12) {
12660       IRTemp sV = newTemp(Ity_V128);
12661       IRTemp d0 = newTemp(Ity_I64);
12662
12663       modrm = insn[2];
12664       if (epartIsReg(modrm)) {
12665          assign( sV, getXMMReg( eregOfRexRM(pfx,modrm)) );
12666          DIP("movddup %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)),
12667                                 nameXMMReg(gregOfRexRM(pfx,modrm)));
12668          delta += 2+1;
12669          assign ( d0, unop(Iop_V128to64, mkexpr(sV)) );
12670       } else {
12671          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
12672          assign( d0, loadLE(Ity_I64, mkexpr(addr)) );
12673          DIP("movddup %s,%s\n", dis_buf,
12674                                 nameXMMReg(gregOfRexRM(pfx,modrm)));
12675          delta += 2+alen;
12676       }
12677
12678       putXMMReg( gregOfRexRM(pfx,modrm), 
12679                  binop(Iop_64HLtoV128,mkexpr(d0),mkexpr(d0)) );
12680       goto decode_success;
12681    }
12682
12683    /* F2 0F D0 = ADDSUBPS -- 32x4 +/-/+/- from E (mem or xmm) to G (xmm). */
12684    if (haveF2no66noF3(pfx) && sz == 4 
12685        && insn[0] == 0x0F && insn[1] == 0xD0) {
12686       IRTemp a3, a2, a1, a0, s3, s2, s1, s0;
12687       IRTemp eV   = newTemp(Ity_V128);
12688       IRTemp gV   = newTemp(Ity_V128);
12689       IRTemp addV = newTemp(Ity_V128);
12690       IRTemp subV = newTemp(Ity_V128);
12691       a3 = a2 = a1 = a0 = s3 = s2 = s1 = s0 = IRTemp_INVALID;
12692
12693       modrm = insn[2];
12694       if (epartIsReg(modrm)) {
12695          assign( eV, getXMMReg( eregOfRexRM(pfx,modrm)) );
12696          DIP("addsubps %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)),
12697                                  nameXMMReg(gregOfRexRM(pfx,modrm)));
12698          delta += 2+1;
12699       } else {
12700          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
12701          assign( eV, loadLE(Ity_V128, mkexpr(addr)) );
12702          DIP("addsubps %s,%s\n", dis_buf,
12703                                  nameXMMReg(gregOfRexRM(pfx,modrm)));
12704          delta += 2+alen;
12705       }
12706
12707       assign( gV, getXMMReg(gregOfRexRM(pfx,modrm)) );
12708
12709       assign( addV, binop(Iop_Add32Fx4, mkexpr(gV), mkexpr(eV)) );
12710       assign( subV, binop(Iop_Sub32Fx4, mkexpr(gV), mkexpr(eV)) );
12711
12712       breakup128to32s( addV, &a3, &a2, &a1, &a0 );
12713       breakup128to32s( subV, &s3, &s2, &s1, &s0 );
12714
12715       putXMMReg( gregOfRexRM(pfx,modrm), mk128from32s( a3, s2, a1, s0 ));
12716       goto decode_success;
12717    }
12718
12719    /* 66 0F D0 = ADDSUBPD -- 64x4 +/- from E (mem or xmm) to G (xmm). */
12720    if (have66noF2noF3(pfx) && sz == 2 
12721        && insn[0] == 0x0F && insn[1] == 0xD0) {
12722       IRTemp eV   = newTemp(Ity_V128);
12723       IRTemp gV   = newTemp(Ity_V128);
12724       IRTemp addV = newTemp(Ity_V128);
12725       IRTemp subV = newTemp(Ity_V128);
12726       IRTemp a1     = newTemp(Ity_I64);
12727       IRTemp s0     = newTemp(Ity_I64);
12728
12729       modrm = insn[2];
12730       if (epartIsReg(modrm)) {
12731          assign( eV, getXMMReg( eregOfRexRM(pfx,modrm)) );
12732          DIP("addsubpd %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)),
12733                                  nameXMMReg(gregOfRexRM(pfx,modrm)));
12734          delta += 2+1;
12735       } else {
12736          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
12737          assign( eV, loadLE(Ity_V128, mkexpr(addr)) );
12738          DIP("addsubpd %s,%s\n", dis_buf,
12739                                  nameXMMReg(gregOfRexRM(pfx,modrm)));
12740          delta += 2+alen;
12741       }
12742
12743       assign( gV, getXMMReg(gregOfRexRM(pfx,modrm)) );
12744
12745       assign( addV, binop(Iop_Add64Fx2, mkexpr(gV), mkexpr(eV)) );
12746       assign( subV, binop(Iop_Sub64Fx2, mkexpr(gV), mkexpr(eV)) );
12747
12748       assign( a1, unop(Iop_V128HIto64, mkexpr(addV) ));
12749       assign( s0, unop(Iop_V128to64,   mkexpr(subV) ));
12750
12751       putXMMReg( gregOfRexRM(pfx,modrm), 
12752                  binop(Iop_64HLtoV128, mkexpr(a1), mkexpr(s0)) );
12753       goto decode_success;
12754    }
12755
12756    /* F2 0F 7D = HSUBPS -- 32x4 sub across from E (mem or xmm) to G (xmm). */
12757    /* F2 0F 7C = HADDPS -- 32x4 add across from E (mem or xmm) to G (xmm). */
12758    if (haveF2no66noF3(pfx) && sz == 4 
12759        && insn[0] == 0x0F && (insn[1] == 0x7C || insn[1] == 0x7D)) {
12760       IRTemp e3, e2, e1, e0, g3, g2, g1, g0;
12761       IRTemp eV     = newTemp(Ity_V128);
12762       IRTemp gV     = newTemp(Ity_V128);
12763       IRTemp leftV  = newTemp(Ity_V128);
12764       IRTemp rightV = newTemp(Ity_V128);
12765       Bool   isAdd  = insn[1] == 0x7C;
12766       HChar* str    = isAdd ? "add" : "sub";
12767       e3 = e2 = e1 = e0 = g3 = g2 = g1 = g0 = IRTemp_INVALID;
12768
12769       modrm = insn[2];
12770       if (epartIsReg(modrm)) {
12771          assign( eV, getXMMReg( eregOfRexRM(pfx,modrm)) );
12772          DIP("h%sps %s,%s\n", str, nameXMMReg(eregOfRexRM(pfx,modrm)),
12773                                    nameXMMReg(gregOfRexRM(pfx,modrm)));
12774          delta += 2+1;
12775       } else {
12776          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
12777          assign( eV, loadLE(Ity_V128, mkexpr(addr)) );
12778          DIP("h%sps %s,%s\n", str, dis_buf,
12779                                    nameXMMReg(gregOfRexRM(pfx,modrm)));
12780          delta += 2+alen;
12781       }
12782
12783       assign( gV, getXMMReg(gregOfRexRM(pfx,modrm)) );
12784
12785       breakup128to32s( eV, &e3, &e2, &e1, &e0 );
12786       breakup128to32s( gV, &g3, &g2, &g1, &g0 );
12787
12788       assign( leftV,  mk128from32s( e2, e0, g2, g0 ) );
12789       assign( rightV, mk128from32s( e3, e1, g3, g1 ) );
12790
12791       putXMMReg( gregOfRexRM(pfx,modrm), 
12792                  binop(isAdd ? Iop_Add32Fx4 : Iop_Sub32Fx4, 
12793                        mkexpr(leftV), mkexpr(rightV) ) );
12794       goto decode_success;
12795    }
12796
12797    /* 66 0F 7D = HSUBPD -- 64x2 sub across from E (mem or xmm) to G (xmm). */
12798    /* 66 0F 7C = HADDPD -- 64x2 add across from E (mem or xmm) to G (xmm). */
12799    if (have66noF2noF3(pfx) && sz == 2 
12800        && insn[0] == 0x0F && (insn[1] == 0x7C || insn[1] == 0x7D)) {
12801       IRTemp e1     = newTemp(Ity_I64);
12802       IRTemp e0     = newTemp(Ity_I64);
12803       IRTemp g1     = newTemp(Ity_I64);
12804       IRTemp g0     = newTemp(Ity_I64);
12805       IRTemp eV     = newTemp(Ity_V128);
12806       IRTemp gV     = newTemp(Ity_V128);
12807       IRTemp leftV  = newTemp(Ity_V128);
12808       IRTemp rightV = newTemp(Ity_V128);
12809       Bool   isAdd  = insn[1] == 0x7C;
12810       HChar* str    = isAdd ? "add" : "sub";
12811
12812       modrm = insn[2];
12813       if (epartIsReg(modrm)) {
12814          assign( eV, getXMMReg( eregOfRexRM(pfx,modrm)) );
12815          DIP("h%spd %s,%s\n", str, nameXMMReg(eregOfRexRM(pfx,modrm)),
12816                                    nameXMMReg(gregOfRexRM(pfx,modrm)));
12817          delta += 2+1;
12818       } else {
12819          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
12820          assign( eV, loadLE(Ity_V128, mkexpr(addr)) );
12821          DIP("h%spd %s,%s\n", str, dis_buf,
12822                               nameXMMReg(gregOfRexRM(pfx,modrm)));
12823          delta += 2+alen;
12824       }
12825
12826       assign( gV, getXMMReg(gregOfRexRM(pfx,modrm)) );
12827
12828       assign( e1, unop(Iop_V128HIto64, mkexpr(eV) ));
12829       assign( e0, unop(Iop_V128to64, mkexpr(eV) ));
12830       assign( g1, unop(Iop_V128HIto64, mkexpr(gV) ));
12831       assign( g0, unop(Iop_V128to64, mkexpr(gV) ));
12832
12833       assign( leftV,  binop(Iop_64HLtoV128, mkexpr(e0),mkexpr(g0)) );
12834       assign( rightV, binop(Iop_64HLtoV128, mkexpr(e1),mkexpr(g1)) );
12835
12836       putXMMReg( gregOfRexRM(pfx,modrm), 
12837                  binop(isAdd ? Iop_Add64Fx2 : Iop_Sub64Fx2, 
12838                        mkexpr(leftV), mkexpr(rightV) ) );
12839       goto decode_success;
12840    }
12841
12842    /* F2 0F F0 = LDDQU -- move from E (mem or xmm) to G (xmm). */
12843    if (haveF2no66noF3(pfx) && sz == 4 
12844        && insn[0] == 0x0F && insn[1] == 0xF0) {
12845       modrm = insn[2];
12846       if (epartIsReg(modrm)) {
12847          goto decode_failure;
12848       } else {
12849          addr = disAMode ( &alen, vbi, pfx, delta+2, dis_buf, 0 );
12850          putXMMReg( gregOfRexRM(pfx,modrm), 
12851                     loadLE(Ity_V128, mkexpr(addr)) );
12852          DIP("lddqu %s,%s\n", dis_buf,
12853                               nameXMMReg(gregOfRexRM(pfx,modrm)));
12854          delta += 2+alen;
12855       }
12856       goto decode_success;
12857    }
12858
12859    /* ---------------------------------------------------- */
12860    /* --- end of the SSE3 decoder.                     --- */
12861    /* ---------------------------------------------------- */
12862
12863    /* ---------------------------------------------------- */
12864    /* --- start of the SSSE3 decoder.                  --- */
12865    /* ---------------------------------------------------- */
12866
12867    /* 0F 38 04 = PMADDUBSW -- Multiply and Add Packed Signed and
12868       Unsigned Bytes (MMX) */
12869    if (haveNo66noF2noF3(pfx) 
12870        && sz == 4 
12871        && insn[0] == 0x0F && insn[1] == 0x38 && insn[2] == 0x04) {
12872       IRTemp sV        = newTemp(Ity_I64);
12873       IRTemp dV        = newTemp(Ity_I64);
12874       IRTemp sVoddsSX  = newTemp(Ity_I64);
12875       IRTemp sVevensSX = newTemp(Ity_I64);
12876       IRTemp dVoddsZX  = newTemp(Ity_I64);
12877       IRTemp dVevensZX = newTemp(Ity_I64);
12878
12879       modrm = insn[3];
12880       do_MMX_preamble();
12881       assign( dV, getMMXReg(gregLO3ofRM(modrm)) );
12882
12883       if (epartIsReg(modrm)) {
12884          assign( sV, getMMXReg(eregLO3ofRM(modrm)) );
12885          delta += 3+1;
12886          DIP("pmaddubsw %s,%s\n", nameMMXReg(eregLO3ofRM(modrm)),
12887                                   nameMMXReg(gregLO3ofRM(modrm)));
12888       } else {
12889          addr = disAMode ( &alen, vbi, pfx, delta+3, dis_buf, 0 );
12890          assign( sV, loadLE(Ity_I64, mkexpr(addr)) );
12891          delta += 3+alen;
12892          DIP("pmaddubsw %s,%s\n", dis_buf,
12893                                   nameMMXReg(gregLO3ofRM(modrm)));
12894       }
12895
12896       /* compute dV unsigned x sV signed */
12897       assign( sVoddsSX,
12898               binop(Iop_SarN16x4, mkexpr(sV), mkU8(8)) );
12899       assign( sVevensSX,
12900               binop(Iop_SarN16x4, 
12901                     binop(Iop_ShlN16x4, mkexpr(sV), mkU8(8)), 
12902                     mkU8(8)) );
12903       assign( dVoddsZX,
12904               binop(Iop_ShrN16x4, mkexpr(dV), mkU8(8)) );
12905       assign( dVevensZX,
12906               binop(Iop_ShrN16x4,
12907                     binop(Iop_ShlN16x4, mkexpr(dV), mkU8(8)),
12908                     mkU8(8)) );
12909
12910       putMMXReg(
12911          gregLO3ofRM(modrm),
12912          binop(Iop_QAdd16Sx4,
12913                binop(Iop_Mul16x4, mkexpr(sVoddsSX), mkexpr(dVoddsZX)),
12914                binop(Iop_Mul16x4, mkexpr(sVevensSX), mkexpr(dVevensZX))
12915          )
12916       );
12917       goto decode_success;
12918    }
12919
12920    /* 66 0F 38 04 = PMADDUBSW -- Multiply and Add Packed Signed and
12921       Unsigned Bytes (XMM) */
12922    if (have66noF2noF3(pfx) 
12923        && (sz == 2 || /*redundant REX.W*/ sz == 8)
12924        && insn[0] == 0x0F && insn[1] == 0x38 && insn[2] == 0x04) {
12925       IRTemp sV        = newTemp(Ity_V128);
12926       IRTemp dV        = newTemp(Ity_V128);
12927       IRTemp sVoddsSX  = newTemp(Ity_V128);
12928       IRTemp sVevensSX = newTemp(Ity_V128);
12929       IRTemp dVoddsZX  = newTemp(Ity_V128);
12930       IRTemp dVevensZX = newTemp(Ity_V128);
12931
12932       modrm = insn[3];
12933       assign( dV, getXMMReg(gregOfRexRM(pfx,modrm)) );
12934
12935       if (epartIsReg(modrm)) {
12936          assign( sV, getXMMReg(eregOfRexRM(pfx,modrm)) );
12937          delta += 3+1;
12938          DIP("pmaddubsw %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)),
12939                                   nameXMMReg(gregOfRexRM(pfx,modrm)));
12940       } else {
12941          addr = disAMode ( &alen, vbi, pfx, delta+3, dis_buf, 0 );
12942          gen_SEGV_if_not_16_aligned( addr );
12943          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
12944          delta += 3+alen;
12945          DIP("pmaddubsw %s,%s\n", dis_buf,
12946                                   nameXMMReg(gregOfRexRM(pfx,modrm)));
12947       }
12948
12949       /* compute dV unsigned x sV signed */
12950       assign( sVoddsSX,
12951               binop(Iop_SarN16x8, mkexpr(sV), mkU8(8)) );
12952       assign( sVevensSX,
12953               binop(Iop_SarN16x8, 
12954                     binop(Iop_ShlN16x8, mkexpr(sV), mkU8(8)), 
12955                     mkU8(8)) );
12956       assign( dVoddsZX,
12957               binop(Iop_ShrN16x8, mkexpr(dV), mkU8(8)) );
12958       assign( dVevensZX,
12959               binop(Iop_ShrN16x8,
12960                     binop(Iop_ShlN16x8, mkexpr(dV), mkU8(8)),
12961                     mkU8(8)) );
12962
12963       putXMMReg(
12964          gregOfRexRM(pfx,modrm),
12965          binop(Iop_QAdd16Sx8,
12966                binop(Iop_Mul16x8, mkexpr(sVoddsSX), mkexpr(dVoddsZX)),
12967                binop(Iop_Mul16x8, mkexpr(sVevensSX), mkexpr(dVevensZX))
12968          )
12969       );
12970       goto decode_success;
12971    }
12972
12973    /* ***--- these are MMX class insns introduced in SSSE3 ---*** */
12974    /* 0F 38 03 = PHADDSW -- 16x4 signed qadd across from E (mem or
12975       mmx) and G to G (mmx). */
12976    /* 0F 38 07 = PHSUBSW -- 16x4 signed qsub across from E (mem or
12977       mmx) and G to G (mmx). */
12978    /* 0F 38 01 = PHADDW -- 16x4 add across from E (mem or mmx) and G
12979       to G (mmx). */
12980    /* 0F 38 05 = PHSUBW -- 16x4 sub across from E (mem or mmx) and G
12981       to G (mmx). */
12982    /* 0F 38 02 = PHADDD -- 32x2 add across from E (mem or mmx) and G
12983       to G (mmx). */
12984    /* 0F 38 06 = PHSUBD -- 32x2 sub across from E (mem or mmx) and G
12985       to G (mmx). */
12986
12987    if (haveNo66noF2noF3(pfx) 
12988        && sz == 4 
12989        && insn[0] == 0x0F && insn[1] == 0x38 
12990        && (insn[2] == 0x03 || insn[2] == 0x07 || insn[2] == 0x01
12991            || insn[2] == 0x05 || insn[2] == 0x02 || insn[2] == 0x06)) {
12992       HChar* str    = "???";
12993       IROp   opV64  = Iop_INVALID;
12994       IROp   opCatO = Iop_CatOddLanes16x4;
12995       IROp   opCatE = Iop_CatEvenLanes16x4;
12996       IRTemp sV     = newTemp(Ity_I64);
12997       IRTemp dV     = newTemp(Ity_I64);
12998
12999       modrm = insn[3];
13000
13001       switch (insn[2]) {
13002          case 0x03: opV64 = Iop_QAdd16Sx4; str = "addsw"; break;
13003          case 0x07: opV64 = Iop_QSub16Sx4; str = "subsw"; break;
13004          case 0x01: opV64 = Iop_Add16x4;   str = "addw";  break;
13005          case 0x05: opV64 = Iop_Sub16x4;   str = "subw";  break;
13006          case 0x02: opV64 = Iop_Add32x2;   str = "addd";  break;
13007          case 0x06: opV64 = Iop_Sub32x2;   str = "subd";  break;
13008          default: vassert(0);
13009       }
13010       if (insn[2] == 0x02 || insn[2] == 0x06) {
13011          opCatO = Iop_InterleaveHI32x2;
13012          opCatE = Iop_InterleaveLO32x2;
13013       }
13014
13015       do_MMX_preamble();
13016       assign( dV, getMMXReg(gregLO3ofRM(modrm)) );
13017
13018       if (epartIsReg(modrm)) {
13019          assign( sV, getMMXReg(eregLO3ofRM(modrm)) );
13020          delta += 3+1;
13021          DIP("ph%s %s,%s\n", str, nameMMXReg(eregLO3ofRM(modrm)),
13022                                   nameMMXReg(gregLO3ofRM(modrm)));
13023       } else {
13024          addr = disAMode ( &alen, vbi, pfx, delta+3, dis_buf, 0 );
13025          assign( sV, loadLE(Ity_I64, mkexpr(addr)) );
13026          delta += 3+alen;
13027          DIP("ph%s %s,%s\n", str, dis_buf,
13028                                   nameMMXReg(gregLO3ofRM(modrm)));
13029       }
13030
13031       putMMXReg(
13032          gregLO3ofRM(modrm),
13033          binop(opV64,
13034                binop(opCatE,mkexpr(sV),mkexpr(dV)),
13035                binop(opCatO,mkexpr(sV),mkexpr(dV))
13036          )
13037       );
13038       goto decode_success;
13039    }
13040
13041    /* 66 0F 38 03 = PHADDSW -- 16x8 signed qadd across from E (mem or
13042       xmm) and G to G (xmm). */
13043    /* 66 0F 38 07 = PHSUBSW -- 16x8 signed qsub across from E (mem or
13044       xmm) and G to G (xmm). */
13045    /* 66 0F 38 01 = PHADDW -- 16x8 add across from E (mem or xmm) and
13046       G to G (xmm). */
13047    /* 66 0F 38 05 = PHSUBW -- 16x8 sub across from E (mem or xmm) and
13048       G to G (xmm). */
13049    /* 66 0F 38 02 = PHADDD -- 32x4 add across from E (mem or xmm) and
13050       G to G (xmm). */
13051    /* 66 0F 38 06 = PHSUBD -- 32x4 sub across from E (mem or xmm) and
13052       G to G (xmm). */
13053
13054    if (have66noF2noF3(pfx) 
13055        && (sz == 2 || /*redundant REX.W*/ sz == 8)
13056        && insn[0] == 0x0F && insn[1] == 0x38 
13057        && (insn[2] == 0x03 || insn[2] == 0x07 || insn[2] == 0x01
13058            || insn[2] == 0x05 || insn[2] == 0x02 || insn[2] == 0x06)) {
13059       HChar* str    = "???";
13060       IROp   opV64  = Iop_INVALID;
13061       IROp   opCatO = Iop_CatOddLanes16x4;
13062       IROp   opCatE = Iop_CatEvenLanes16x4;
13063       IRTemp sV     = newTemp(Ity_V128);
13064       IRTemp dV     = newTemp(Ity_V128);
13065       IRTemp sHi    = newTemp(Ity_I64);
13066       IRTemp sLo    = newTemp(Ity_I64);
13067       IRTemp dHi    = newTemp(Ity_I64);
13068       IRTemp dLo    = newTemp(Ity_I64);
13069
13070       modrm = insn[3];
13071
13072       switch (insn[2]) {
13073          case 0x03: opV64 = Iop_QAdd16Sx4; str = "addsw"; break;
13074          case 0x07: opV64 = Iop_QSub16Sx4; str = "subsw"; break;
13075          case 0x01: opV64 = Iop_Add16x4;   str = "addw";  break;
13076          case 0x05: opV64 = Iop_Sub16x4;   str = "subw";  break;
13077          case 0x02: opV64 = Iop_Add32x2;   str = "addd";  break;
13078          case 0x06: opV64 = Iop_Sub32x2;   str = "subd";  break;
13079          default: vassert(0);
13080       }
13081       if (insn[2] == 0x02 || insn[2] == 0x06) {
13082          opCatO = Iop_InterleaveHI32x2;
13083          opCatE = Iop_InterleaveLO32x2;
13084       }
13085
13086       assign( dV, getXMMReg(gregOfRexRM(pfx,modrm)) );
13087
13088       if (epartIsReg(modrm)) {
13089          assign( sV, getXMMReg( eregOfRexRM(pfx,modrm)) );
13090          DIP("ph%s %s,%s\n", str, nameXMMReg(eregOfRexRM(pfx,modrm)),
13091                                   nameXMMReg(gregOfRexRM(pfx,modrm)));
13092          delta += 3+1;
13093       } else {
13094          addr = disAMode ( &alen, vbi, pfx, delta+3, dis_buf, 0 );
13095          gen_SEGV_if_not_16_aligned( addr );
13096          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
13097          DIP("ph%s %s,%s\n", str, dis_buf,
13098                              nameXMMReg(gregOfRexRM(pfx,modrm)));
13099          delta += 3+alen;
13100       }
13101
13102       assign( dHi, unop(Iop_V128HIto64, mkexpr(dV)) );
13103       assign( dLo, unop(Iop_V128to64,   mkexpr(dV)) );
13104       assign( sHi, unop(Iop_V128HIto64, mkexpr(sV)) );
13105       assign( sLo, unop(Iop_V128to64,   mkexpr(sV)) );
13106
13107       /* This isn't a particularly efficient way to compute the
13108          result, but at least it avoids a proliferation of IROps,
13109          hence avoids complication all the backends. */
13110       putXMMReg(
13111          gregOfRexRM(pfx,modrm), 
13112          binop(Iop_64HLtoV128,
13113                binop(opV64,
13114                      binop(opCatE,mkexpr(sHi),mkexpr(sLo)),
13115                      binop(opCatO,mkexpr(sHi),mkexpr(sLo))
13116                ),
13117                binop(opV64,
13118                      binop(opCatE,mkexpr(dHi),mkexpr(dLo)),
13119                      binop(opCatO,mkexpr(dHi),mkexpr(dLo))
13120                )
13121          )
13122       );
13123       goto decode_success;
13124    }
13125
13126    /* 0F 38 0B = PMULHRSW -- Packed Multiply High with Round and Scale
13127       (MMX) */
13128    if (haveNo66noF2noF3(pfx) 
13129        && sz == 4 
13130        && insn[0] == 0x0F && insn[1] == 0x38 && insn[2] == 0x0B) {
13131       IRTemp sV = newTemp(Ity_I64);
13132       IRTemp dV = newTemp(Ity_I64);
13133
13134       modrm = insn[3];
13135       do_MMX_preamble();
13136       assign( dV, getMMXReg(gregLO3ofRM(modrm)) );
13137
13138       if (epartIsReg(modrm)) {
13139          assign( sV, getMMXReg(eregLO3ofRM(modrm)) );
13140          delta += 3+1;
13141          DIP("pmulhrsw %s,%s\n", nameMMXReg(eregLO3ofRM(modrm)),
13142                                  nameMMXReg(gregLO3ofRM(modrm)));
13143       } else {
13144          addr = disAMode ( &alen, vbi, pfx, delta+3, dis_buf, 0 );
13145          assign( sV, loadLE(Ity_I64, mkexpr(addr)) );
13146          delta += 3+alen;
13147          DIP("pmulhrsw %s,%s\n", dis_buf,
13148                                  nameMMXReg(gregLO3ofRM(modrm)));
13149       }
13150
13151       putMMXReg(
13152          gregLO3ofRM(modrm),
13153          dis_PMULHRSW_helper( mkexpr(sV), mkexpr(dV) )
13154       );
13155       goto decode_success;
13156    }
13157
13158    /* 66 0F 38 0B = PMULHRSW -- Packed Multiply High with Round and
13159       Scale (XMM) */
13160    if (have66noF2noF3(pfx) 
13161        && (sz == 2 || /*redundant REX.W*/ sz == 8)
13162        && insn[0] == 0x0F && insn[1] == 0x38 && insn[2] == 0x0B) {
13163       IRTemp sV  = newTemp(Ity_V128);
13164       IRTemp dV  = newTemp(Ity_V128);
13165       IRTemp sHi = newTemp(Ity_I64);
13166       IRTemp sLo = newTemp(Ity_I64);
13167       IRTemp dHi = newTemp(Ity_I64);
13168       IRTemp dLo = newTemp(Ity_I64);
13169
13170       modrm = insn[3];
13171       assign( dV, getXMMReg(gregOfRexRM(pfx,modrm)) );
13172
13173       if (epartIsReg(modrm)) {
13174          assign( sV, getXMMReg(eregOfRexRM(pfx,modrm)) );
13175          delta += 3+1;
13176          DIP("pmulhrsw %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)),
13177                                  nameXMMReg(gregOfRexRM(pfx,modrm)));
13178       } else {
13179          addr = disAMode ( &alen, vbi, pfx, delta+3, dis_buf, 0 );
13180          gen_SEGV_if_not_16_aligned( addr );
13181          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
13182          delta += 3+alen;
13183          DIP("pmulhrsw %s,%s\n", dis_buf,
13184                                  nameXMMReg(gregOfRexRM(pfx,modrm)));
13185       }
13186
13187       assign( dHi, unop(Iop_V128HIto64, mkexpr(dV)) );
13188       assign( dLo, unop(Iop_V128to64,   mkexpr(dV)) );
13189       assign( sHi, unop(Iop_V128HIto64, mkexpr(sV)) );
13190       assign( sLo, unop(Iop_V128to64,   mkexpr(sV)) );
13191
13192       putXMMReg(
13193          gregOfRexRM(pfx,modrm),
13194          binop(Iop_64HLtoV128,
13195                dis_PMULHRSW_helper( mkexpr(sHi), mkexpr(dHi) ),
13196                dis_PMULHRSW_helper( mkexpr(sLo), mkexpr(dLo) )
13197          )
13198       );
13199       goto decode_success;
13200    }
13201
13202    /* 0F 38 08 = PSIGNB -- Packed Sign 8x8  (MMX) */
13203    /* 0F 38 09 = PSIGNW -- Packed Sign 16x4 (MMX) */
13204    /* 0F 38 09 = PSIGND -- Packed Sign 32x2 (MMX) */
13205    if (haveNo66noF2noF3(pfx) 
13206        && sz == 4 
13207        && insn[0] == 0x0F && insn[1] == 0x38 
13208        && (insn[2] == 0x08 || insn[2] == 0x09 || insn[2] == 0x0A)) {
13209       IRTemp sV      = newTemp(Ity_I64);
13210       IRTemp dV      = newTemp(Ity_I64);
13211       HChar* str     = "???";
13212       Int    laneszB = 0;
13213
13214       switch (insn[2]) {
13215          case 0x08: laneszB = 1; str = "b"; break;
13216          case 0x09: laneszB = 2; str = "w"; break;
13217          case 0x0A: laneszB = 4; str = "d"; break;
13218          default: vassert(0);
13219       }
13220
13221       modrm = insn[3];
13222       do_MMX_preamble();
13223       assign( dV, getMMXReg(gregLO3ofRM(modrm)) );
13224
13225       if (epartIsReg(modrm)) {
13226          assign( sV, getMMXReg(eregLO3ofRM(modrm)) );
13227          delta += 3+1;
13228          DIP("psign%s %s,%s\n", str, nameMMXReg(eregLO3ofRM(modrm)),
13229                                      nameMMXReg(gregLO3ofRM(modrm)));
13230       } else {
13231          addr = disAMode ( &alen, vbi, pfx, delta+3, dis_buf, 0 );
13232          assign( sV, loadLE(Ity_I64, mkexpr(addr)) );
13233          delta += 3+alen;
13234          DIP("psign%s %s,%s\n", str, dis_buf,
13235                                      nameMMXReg(gregLO3ofRM(modrm)));
13236       }
13237
13238       putMMXReg(
13239          gregLO3ofRM(modrm),
13240          dis_PSIGN_helper( mkexpr(sV), mkexpr(dV), laneszB )
13241       );
13242       goto decode_success;
13243    }
13244
13245    /* 66 0F 38 08 = PSIGNB -- Packed Sign 8x16 (XMM) */
13246    /* 66 0F 38 09 = PSIGNW -- Packed Sign 16x8 (XMM) */
13247    /* 66 0F 38 09 = PSIGND -- Packed Sign 32x4 (XMM) */
13248    if (have66noF2noF3(pfx) 
13249        && (sz == 2 || /*redundant REX.W*/ sz == 8)
13250        && insn[0] == 0x0F && insn[1] == 0x38 
13251        && (insn[2] == 0x08 || insn[2] == 0x09 || insn[2] == 0x0A)) {
13252       IRTemp sV      = newTemp(Ity_V128);
13253       IRTemp dV      = newTemp(Ity_V128);
13254       IRTemp sHi     = newTemp(Ity_I64);
13255       IRTemp sLo     = newTemp(Ity_I64);
13256       IRTemp dHi     = newTemp(Ity_I64);
13257       IRTemp dLo     = newTemp(Ity_I64);
13258       HChar* str     = "???";
13259       Int    laneszB = 0;
13260
13261       switch (insn[2]) {
13262          case 0x08: laneszB = 1; str = "b"; break;
13263          case 0x09: laneszB = 2; str = "w"; break;
13264          case 0x0A: laneszB = 4; str = "d"; break;
13265          default: vassert(0);
13266       }
13267
13268       modrm = insn[3];
13269       assign( dV, getXMMReg(gregOfRexRM(pfx,modrm)) );
13270
13271       if (epartIsReg(modrm)) {
13272          assign( sV, getXMMReg(eregOfRexRM(pfx,modrm)) );
13273          delta += 3+1;
13274          DIP("psign%s %s,%s\n", str, nameXMMReg(eregOfRexRM(pfx,modrm)),
13275                                      nameXMMReg(gregOfRexRM(pfx,modrm)));
13276       } else {
13277          addr = disAMode ( &alen, vbi, pfx, delta+3, dis_buf, 0 );
13278          gen_SEGV_if_not_16_aligned( addr );
13279          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
13280          delta += 3+alen;
13281          DIP("psign%s %s,%s\n", str, dis_buf,
13282                                      nameXMMReg(gregOfRexRM(pfx,modrm)));
13283       }
13284
13285       assign( dHi, unop(Iop_V128HIto64, mkexpr(dV)) );
13286       assign( dLo, unop(Iop_V128to64,   mkexpr(dV)) );
13287       assign( sHi, unop(Iop_V128HIto64, mkexpr(sV)) );
13288       assign( sLo, unop(Iop_V128to64,   mkexpr(sV)) );
13289
13290       putXMMReg(
13291          gregOfRexRM(pfx,modrm),
13292          binop(Iop_64HLtoV128,
13293                dis_PSIGN_helper( mkexpr(sHi), mkexpr(dHi), laneszB ),
13294                dis_PSIGN_helper( mkexpr(sLo), mkexpr(dLo), laneszB )
13295          )
13296       );
13297       goto decode_success;
13298    }
13299
13300    /* 0F 38 1C = PABSB -- Packed Absolute Value 8x8  (MMX) */
13301    /* 0F 38 1D = PABSW -- Packed Absolute Value 16x4 (MMX) */
13302    /* 0F 38 1E = PABSD -- Packed Absolute Value 32x2 (MMX) */
13303    if (haveNo66noF2noF3(pfx) 
13304        && sz == 4 
13305        && insn[0] == 0x0F && insn[1] == 0x38 
13306        && (insn[2] == 0x1C || insn[2] == 0x1D || insn[2] == 0x1E)) {
13307       IRTemp sV      = newTemp(Ity_I64);
13308       HChar* str     = "???";
13309       Int    laneszB = 0;
13310
13311       switch (insn[2]) {
13312          case 0x1C: laneszB = 1; str = "b"; break;
13313          case 0x1D: laneszB = 2; str = "w"; break;
13314          case 0x1E: laneszB = 4; str = "d"; break;
13315          default: vassert(0);
13316       }
13317
13318       modrm = insn[3];
13319       do_MMX_preamble();
13320
13321       if (epartIsReg(modrm)) {
13322          assign( sV, getMMXReg(eregLO3ofRM(modrm)) );
13323          delta += 3+1;
13324          DIP("pabs%s %s,%s\n", str, nameMMXReg(eregLO3ofRM(modrm)),
13325                                     nameMMXReg(gregLO3ofRM(modrm)));
13326       } else {
13327          addr = disAMode ( &alen, vbi, pfx, delta+3, dis_buf, 0 );
13328          assign( sV, loadLE(Ity_I64, mkexpr(addr)) );
13329          delta += 3+alen;
13330          DIP("pabs%s %s,%s\n", str, dis_buf,
13331                                     nameMMXReg(gregLO3ofRM(modrm)));
13332       }
13333
13334       putMMXReg(
13335          gregLO3ofRM(modrm),
13336          dis_PABS_helper( mkexpr(sV), laneszB )
13337       );
13338       goto decode_success;
13339    }
13340
13341    /* 66 0F 38 1C = PABSB -- Packed Absolute Value 8x16 (XMM) */
13342    /* 66 0F 38 1D = PABSW -- Packed Absolute Value 16x8 (XMM) */
13343    /* 66 0F 38 1E = PABSD -- Packed Absolute Value 32x4 (XMM) */
13344    if (have66noF2noF3(pfx) 
13345        && (sz == 2 || /*redundant REX.W*/ sz == 8)
13346        && insn[0] == 0x0F && insn[1] == 0x38 
13347        && (insn[2] == 0x1C || insn[2] == 0x1D || insn[2] == 0x1E)) {
13348       IRTemp sV      = newTemp(Ity_V128);
13349       IRTemp sHi     = newTemp(Ity_I64);
13350       IRTemp sLo     = newTemp(Ity_I64);
13351       HChar* str     = "???";
13352       Int    laneszB = 0;
13353
13354       switch (insn[2]) {
13355          case 0x1C: laneszB = 1; str = "b"; break;
13356          case 0x1D: laneszB = 2; str = "w"; break;
13357          case 0x1E: laneszB = 4; str = "d"; break;
13358          default: vassert(0);
13359       }
13360
13361       modrm = insn[3];
13362
13363       if (epartIsReg(modrm)) {
13364          assign( sV, getXMMReg(eregOfRexRM(pfx,modrm)) );
13365          delta += 3+1;
13366          DIP("pabs%s %s,%s\n", str, nameXMMReg(eregOfRexRM(pfx,modrm)),
13367                                     nameXMMReg(gregOfRexRM(pfx,modrm)));
13368       } else {
13369          addr = disAMode ( &alen, vbi, pfx, delta+3, dis_buf, 0 );
13370          gen_SEGV_if_not_16_aligned( addr );
13371          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
13372          delta += 3+alen;
13373          DIP("pabs%s %s,%s\n", str, dis_buf,
13374                                     nameXMMReg(gregOfRexRM(pfx,modrm)));
13375       }
13376
13377       assign( sHi, unop(Iop_V128HIto64, mkexpr(sV)) );
13378       assign( sLo, unop(Iop_V128to64,   mkexpr(sV)) );
13379
13380       putXMMReg(
13381          gregOfRexRM(pfx,modrm),
13382          binop(Iop_64HLtoV128,
13383                dis_PABS_helper( mkexpr(sHi), laneszB ),
13384                dis_PABS_helper( mkexpr(sLo), laneszB )
13385          )
13386       );
13387       goto decode_success;
13388    }
13389
13390    /* 0F 3A 0F = PALIGNR -- Packed Align Right (MMX) */
13391    if (haveNo66noF2noF3(pfx) && sz == 4 
13392        && insn[0] == 0x0F && insn[1] == 0x3A && insn[2] == 0x0F) {
13393       IRTemp sV  = newTemp(Ity_I64);
13394       IRTemp dV  = newTemp(Ity_I64);
13395       IRTemp res = newTemp(Ity_I64);
13396
13397       modrm = insn[3];
13398       do_MMX_preamble();
13399       assign( dV, getMMXReg(gregLO3ofRM(modrm)) );
13400
13401       if (epartIsReg(modrm)) {
13402          assign( sV, getMMXReg(eregLO3ofRM(modrm)) );
13403          d64 = (Long)insn[3+1];
13404          delta += 3+1+1;
13405          DIP("palignr $%d,%s,%s\n",  (Int)d64, 
13406                                      nameMMXReg(eregLO3ofRM(modrm)),
13407                                      nameMMXReg(gregLO3ofRM(modrm)));
13408       } else {
13409          addr = disAMode ( &alen, vbi, pfx, delta+3, dis_buf, 1 );
13410          assign( sV, loadLE(Ity_I64, mkexpr(addr)) );
13411          d64 = (Long)insn[3+alen];
13412          delta += 3+alen+1;
13413          DIP("palignr $%d%s,%s\n", (Int)d64,
13414                                    dis_buf,
13415                                    nameMMXReg(gregLO3ofRM(modrm)));
13416       }
13417
13418       if (d64 == 0) {
13419          assign( res, mkexpr(sV) );
13420       }
13421       else if (d64 >= 1 && d64 <= 7) {
13422          assign(res, 
13423                 binop(Iop_Or64,
13424                       binop(Iop_Shr64, mkexpr(sV), mkU8(8*d64)),
13425                       binop(Iop_Shl64, mkexpr(dV), mkU8(8*(8-d64))
13426                      )));
13427       }
13428       else if (d64 == 8) {
13429         assign( res, mkexpr(dV) );
13430       }
13431       else if (d64 >= 9 && d64 <= 15) {
13432          assign( res, binop(Iop_Shr64, mkexpr(dV), mkU8(8*(d64-8))) );
13433       }
13434       else if (d64 >= 16 && d64 <= 255) {
13435          assign( res, mkU64(0) );
13436       }
13437       else
13438          vassert(0);
13439
13440       putMMXReg( gregLO3ofRM(modrm), mkexpr(res) );
13441       goto decode_success;
13442    }
13443
13444    /* 66 0F 3A 0F = PALIGNR -- Packed Align Right (XMM) */
13445    if (have66noF2noF3(pfx) 
13446        && (sz == 2 || /*redundant REX.W*/ sz == 8)
13447        && insn[0] == 0x0F && insn[1] == 0x3A && insn[2] == 0x0F) {
13448       IRTemp sV  = newTemp(Ity_V128);
13449       IRTemp dV  = newTemp(Ity_V128);
13450       IRTemp sHi = newTemp(Ity_I64);
13451       IRTemp sLo = newTemp(Ity_I64);
13452       IRTemp dHi = newTemp(Ity_I64);
13453       IRTemp dLo = newTemp(Ity_I64);
13454       IRTemp rHi = newTemp(Ity_I64);
13455       IRTemp rLo = newTemp(Ity_I64);
13456
13457       modrm = insn[3];
13458       assign( dV, getXMMReg(gregOfRexRM(pfx,modrm)) );
13459
13460       if (epartIsReg(modrm)) {
13461          assign( sV, getXMMReg(eregOfRexRM(pfx,modrm)) );
13462          d64 = (Long)insn[3+1];
13463          delta += 3+1+1;
13464          DIP("palignr $%d,%s,%s\n", (Int)d64,
13465                                     nameXMMReg(eregOfRexRM(pfx,modrm)),
13466                                     nameXMMReg(gregOfRexRM(pfx,modrm)));
13467       } else {
13468          addr = disAMode ( &alen, vbi, pfx, delta+3, dis_buf, 1 );
13469          gen_SEGV_if_not_16_aligned( addr );
13470          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
13471          d64 = (Long)insn[3+alen];
13472          delta += 3+alen+1;
13473          DIP("palignr $%d,%s,%s\n", (Int)d64,
13474                                     dis_buf,
13475                                     nameXMMReg(gregOfRexRM(pfx,modrm)));
13476       }
13477
13478       assign( dHi, unop(Iop_V128HIto64, mkexpr(dV)) );
13479       assign( dLo, unop(Iop_V128to64,   mkexpr(dV)) );
13480       assign( sHi, unop(Iop_V128HIto64, mkexpr(sV)) );
13481       assign( sLo, unop(Iop_V128to64,   mkexpr(sV)) );
13482
13483       if (d64 == 0) {
13484          assign( rHi, mkexpr(sHi) );
13485          assign( rLo, mkexpr(sLo) );
13486       }
13487       else if (d64 >= 1 && d64 <= 7) {
13488          assign( rHi, dis_PALIGNR_XMM_helper(dLo, sHi, d64) );
13489          assign( rLo, dis_PALIGNR_XMM_helper(sHi, sLo, d64) );
13490       }
13491       else if (d64 == 8) {
13492          assign( rHi, mkexpr(dLo) );
13493          assign( rLo, mkexpr(sHi) );
13494       }
13495       else if (d64 >= 9 && d64 <= 15) {
13496          assign( rHi, dis_PALIGNR_XMM_helper(dHi, dLo, d64-8) );
13497          assign( rLo, dis_PALIGNR_XMM_helper(dLo, sHi, d64-8) );
13498       }
13499       else if (d64 == 16) {
13500          assign( rHi, mkexpr(dHi) );
13501          assign( rLo, mkexpr(dLo) );
13502       }
13503       else if (d64 >= 17 && d64 <= 23) {
13504          assign( rHi, binop(Iop_Shr64, mkexpr(dHi), mkU8(8*(d64-16))) );
13505          assign( rLo, dis_PALIGNR_XMM_helper(dHi, dLo, d64-16) );
13506       }
13507       else if (d64 == 24) {
13508          assign( rHi, mkU64(0) );
13509          assign( rLo, mkexpr(dHi) );
13510       }
13511       else if (d64 >= 25 && d64 <= 31) {
13512          assign( rHi, mkU64(0) );
13513          assign( rLo, binop(Iop_Shr64, mkexpr(dHi), mkU8(8*(d64-24))) );
13514       }
13515       else if (d64 >= 32 && d64 <= 255) {
13516          assign( rHi, mkU64(0) );
13517          assign( rLo, mkU64(0) );
13518       }
13519       else
13520          vassert(0);
13521
13522       putXMMReg(
13523          gregOfRexRM(pfx,modrm),
13524          binop(Iop_64HLtoV128, mkexpr(rHi), mkexpr(rLo))
13525       );
13526       goto decode_success;
13527    }
13528
13529    /* 0F 38 00 = PSHUFB -- Packed Shuffle Bytes 8x8 (MMX) */
13530    if (haveNo66noF2noF3(pfx) 
13531        && sz == 4 
13532        && insn[0] == 0x0F && insn[1] == 0x38 && insn[2] == 0x00) {
13533       IRTemp sV      = newTemp(Ity_I64);
13534       IRTemp dV      = newTemp(Ity_I64);
13535
13536       modrm = insn[3];
13537       do_MMX_preamble();
13538       assign( dV, getMMXReg(gregLO3ofRM(modrm)) );
13539
13540       if (epartIsReg(modrm)) {
13541          assign( sV, getMMXReg(eregLO3ofRM(modrm)) );
13542          delta += 3+1;
13543          DIP("pshufb %s,%s\n", nameMMXReg(eregLO3ofRM(modrm)),
13544                                nameMMXReg(gregLO3ofRM(modrm)));
13545       } else {
13546          addr = disAMode ( &alen, vbi, pfx, delta+3, dis_buf, 0 );
13547          assign( sV, loadLE(Ity_I64, mkexpr(addr)) );
13548          delta += 3+alen;
13549          DIP("pshufb %s,%s\n", dis_buf,
13550                                nameMMXReg(gregLO3ofRM(modrm)));
13551       }
13552
13553       putMMXReg(
13554          gregLO3ofRM(modrm),
13555          binop(
13556             Iop_And64,
13557             /* permute the lanes */
13558             binop(
13559                Iop_Perm8x8,
13560                mkexpr(dV),
13561                binop(Iop_And64, mkexpr(sV), mkU64(0x0707070707070707ULL))
13562             ),
13563             /* mask off lanes which have (index & 0x80) == 0x80 */
13564             unop(Iop_Not64, binop(Iop_SarN8x8, mkexpr(sV), mkU8(7)))
13565          )
13566       );
13567       goto decode_success;
13568    }
13569
13570    /* 66 0F 38 00 = PSHUFB -- Packed Shuffle Bytes 8x16 (XMM) */
13571    if (have66noF2noF3(pfx) 
13572        && (sz == 2 || /*redundant REX.W*/ sz == 8)
13573        && insn[0] == 0x0F && insn[1] == 0x38 && insn[2] == 0x00) {
13574       IRTemp sV         = newTemp(Ity_V128);
13575       IRTemp dV         = newTemp(Ity_V128);
13576       IRTemp sHi        = newTemp(Ity_I64);
13577       IRTemp sLo        = newTemp(Ity_I64);
13578       IRTemp dHi        = newTemp(Ity_I64);
13579       IRTemp dLo        = newTemp(Ity_I64);
13580       IRTemp rHi        = newTemp(Ity_I64);
13581       IRTemp rLo        = newTemp(Ity_I64);
13582       IRTemp sevens     = newTemp(Ity_I64);
13583       IRTemp mask0x80hi = newTemp(Ity_I64);
13584       IRTemp mask0x80lo = newTemp(Ity_I64);
13585       IRTemp maskBit3hi = newTemp(Ity_I64);
13586       IRTemp maskBit3lo = newTemp(Ity_I64);
13587       IRTemp sAnd7hi    = newTemp(Ity_I64);
13588       IRTemp sAnd7lo    = newTemp(Ity_I64);
13589       IRTemp permdHi    = newTemp(Ity_I64);
13590       IRTemp permdLo    = newTemp(Ity_I64);
13591
13592       modrm = insn[3];
13593       assign( dV, getXMMReg(gregOfRexRM(pfx,modrm)) );
13594
13595       if (epartIsReg(modrm)) {
13596          assign( sV, getXMMReg(eregOfRexRM(pfx,modrm)) );
13597          delta += 3+1;
13598          DIP("pshufb %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)),
13599                                nameXMMReg(gregOfRexRM(pfx,modrm)));
13600       } else {
13601          addr = disAMode ( &alen, vbi, pfx, delta+3, dis_buf, 0 );
13602          gen_SEGV_if_not_16_aligned( addr );
13603          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
13604          delta += 3+alen;
13605          DIP("pshufb %s,%s\n", dis_buf,
13606                                nameXMMReg(gregOfRexRM(pfx,modrm)));
13607       }
13608
13609       assign( dHi, unop(Iop_V128HIto64, mkexpr(dV)) );
13610       assign( dLo, unop(Iop_V128to64,   mkexpr(dV)) );
13611       assign( sHi, unop(Iop_V128HIto64, mkexpr(sV)) );
13612       assign( sLo, unop(Iop_V128to64,   mkexpr(sV)) );
13613
13614       assign( sevens, mkU64(0x0707070707070707ULL) );
13615
13616       /*
13617       mask0x80hi = Not(SarN8x8(sHi,7))
13618       maskBit3hi = SarN8x8(ShlN8x8(sHi,4),7)
13619       sAnd7hi    = And(sHi,sevens)
13620       permdHi    = Or( And(Perm8x8(dHi,sAnd7hi),maskBit3hi),
13621                        And(Perm8x8(dLo,sAnd7hi),Not(maskBit3hi)) )
13622       rHi        = And(permdHi,mask0x80hi)
13623       */
13624       assign(
13625          mask0x80hi,
13626          unop(Iop_Not64, binop(Iop_SarN8x8,mkexpr(sHi),mkU8(7))));
13627
13628       assign(
13629          maskBit3hi,
13630          binop(Iop_SarN8x8,
13631                binop(Iop_ShlN8x8,mkexpr(sHi),mkU8(4)),
13632                mkU8(7)));
13633
13634       assign(sAnd7hi, binop(Iop_And64,mkexpr(sHi),mkexpr(sevens)));
13635
13636       assign(
13637          permdHi,
13638          binop(
13639             Iop_Or64,
13640             binop(Iop_And64,
13641                   binop(Iop_Perm8x8,mkexpr(dHi),mkexpr(sAnd7hi)),
13642                   mkexpr(maskBit3hi)),
13643             binop(Iop_And64,
13644                   binop(Iop_Perm8x8,mkexpr(dLo),mkexpr(sAnd7hi)),
13645                   unop(Iop_Not64,mkexpr(maskBit3hi))) ));
13646
13647       assign(rHi, binop(Iop_And64,mkexpr(permdHi),mkexpr(mask0x80hi)) );
13648
13649       /* And the same for the lower half of the result.  What fun. */
13650
13651       assign(
13652          mask0x80lo,
13653          unop(Iop_Not64, binop(Iop_SarN8x8,mkexpr(sLo),mkU8(7))));
13654
13655       assign(
13656          maskBit3lo,
13657          binop(Iop_SarN8x8,
13658                binop(Iop_ShlN8x8,mkexpr(sLo),mkU8(4)),
13659                mkU8(7)));
13660
13661       assign(sAnd7lo, binop(Iop_And64,mkexpr(sLo),mkexpr(sevens)));
13662
13663       assign(
13664          permdLo,
13665          binop(
13666             Iop_Or64,
13667             binop(Iop_And64,
13668                   binop(Iop_Perm8x8,mkexpr(dHi),mkexpr(sAnd7lo)),
13669                   mkexpr(maskBit3lo)),
13670             binop(Iop_And64,
13671                   binop(Iop_Perm8x8,mkexpr(dLo),mkexpr(sAnd7lo)),
13672                   unop(Iop_Not64,mkexpr(maskBit3lo))) ));
13673
13674       assign(rLo, binop(Iop_And64,mkexpr(permdLo),mkexpr(mask0x80lo)) );
13675
13676       putXMMReg(
13677          gregOfRexRM(pfx,modrm),
13678          binop(Iop_64HLtoV128, mkexpr(rHi), mkexpr(rLo))
13679       );
13680       goto decode_success;
13681    }
13682
13683    /* ---------------------------------------------------- */
13684    /* --- end of the SSSE3 decoder.                    --- */
13685    /* ---------------------------------------------------- */
13686
13687    /* ---------------------------------------------------- */
13688    /* --- start of the SSE4 decoder                    --- */
13689    /* ---------------------------------------------------- */
13690
13691    /* 66 0F 3A 0D /r ib = BLENDPD xmm1, xmm2/m128, imm8
13692       Blend Packed Double Precision Floating-Point Values (XMM) */
13693    if ( have66noF2noF3( pfx ) 
13694         && sz == 2
13695         && insn[0] == 0x0F && insn[1] == 0x3A && insn[2] == 0x0D ) {
13696
13697       Int imm8;
13698       UShort imm8_mask_16;
13699
13700       IRTemp dst_vec = newTemp(Ity_V128);
13701       IRTemp src_vec = newTemp(Ity_V128);
13702       IRTemp imm8_mask = newTemp(Ity_V128);
13703
13704       modrm = insn[3];
13705       assign( dst_vec, getXMMReg( gregOfRexRM(pfx, modrm) ) );
13706
13707       if ( epartIsReg( modrm ) ) {
13708          imm8 = (Int)insn[4];
13709          assign( src_vec, getXMMReg( eregOfRexRM(pfx, modrm) ) );
13710          delta += 3+1+1;
13711          DIP( "blendpd $%d, %s,%s\n", imm8,
13712               nameXMMReg( eregOfRexRM(pfx, modrm) ),
13713               nameXMMReg( gregOfRexRM(pfx, modrm) ) );
13714       } else {
13715          addr = disAMode( &alen, vbi, pfx, delta+3, dis_buf, 
13716                           1/* imm8 is 1 byte after the amode */ );
13717          assign( src_vec, loadLE( Ity_V128, mkexpr(addr) ) );
13718          imm8 = (Int)insn[2+alen+1];
13719          delta += 3+alen+1;
13720          DIP( "blendpd $%d, %s,%s\n", 
13721               imm8, dis_buf, nameXMMReg( gregOfRexRM(pfx, modrm) ) );
13722       }
13723
13724       switch( imm8 & 3 ) {
13725          case 0:  imm8_mask_16 = 0x0000; break;
13726          case 1:  imm8_mask_16 = 0x00FF; break;
13727          case 2:  imm8_mask_16 = 0xFF00; break;
13728          case 3:  imm8_mask_16 = 0xFFFF; break;
13729          default: vassert(0);            break;
13730       }
13731       assign( imm8_mask, mkV128( imm8_mask_16 ) );
13732
13733       putXMMReg( gregOfRexRM(pfx, modrm), 
13734                  binop( Iop_OrV128, 
13735                         binop( Iop_AndV128, mkexpr(src_vec), mkexpr(imm8_mask) ), 
13736                         binop( Iop_AndV128, mkexpr(dst_vec), 
13737                                unop( Iop_NotV128, mkexpr(imm8_mask) ) ) ) );
13738
13739       goto decode_success;
13740    }
13741
13742
13743    /* 66 0F 3A 0C /r ib = BLENDPS xmm1, xmm2/m128, imm8
13744       Blend Packed Single Precision Floating-Point Values (XMM) */
13745    if ( have66noF2noF3( pfx ) 
13746         && sz == 2
13747         && insn[0] == 0x0F && insn[1] == 0x3A && insn[2] == 0x0C ) {
13748
13749       Int imm8;
13750       IRTemp dst_vec = newTemp(Ity_V128);
13751       IRTemp src_vec = newTemp(Ity_V128);
13752
13753       modrm = insn[3];
13754
13755       assign( dst_vec, getXMMReg( gregOfRexRM(pfx, modrm) ) );
13756
13757       if ( epartIsReg( modrm ) ) {
13758          imm8 = (Int)insn[3+1];
13759          assign( src_vec, getXMMReg( eregOfRexRM(pfx, modrm) ) );
13760          delta += 3+1+1;
13761          DIP( "blendps $%d, %s,%s\n", imm8,
13762               nameXMMReg( eregOfRexRM(pfx, modrm) ),
13763               nameXMMReg( gregOfRexRM(pfx, modrm) ) );    
13764       } else {
13765          addr = disAMode( &alen, vbi, pfx, delta+3, dis_buf, 
13766                           1/* imm8 is 1 byte after the amode */ );
13767          assign( src_vec, loadLE( Ity_V128, mkexpr(addr) ) );
13768          imm8 = (Int)insn[3+alen];
13769          delta += 3+alen+1;
13770          DIP( "blendpd $%d, %s,%s\n", 
13771               imm8, dis_buf, nameXMMReg( gregOfRexRM(pfx, modrm) ) );
13772       }
13773
13774       UShort imm8_perms[16] = { 0x0000, 0x000F, 0x00F0, 0x00FF, 0x0F00, 0x0F0F, 
13775                                 0x0FF0, 0x0FFF, 0xF000, 0xF00F, 0xF0F0, 0xF0FF, 
13776                                 0xFF00, 0xFF0F, 0xFFF0, 0xFFFF };
13777       IRTemp imm8_mask = newTemp(Ity_V128);
13778       assign( imm8_mask, mkV128( imm8_perms[ (imm8 & 15) ] ) );
13779
13780       putXMMReg( gregOfRexRM(pfx, modrm), 
13781                  binop( Iop_OrV128, 
13782                         binop( Iop_AndV128, mkexpr(src_vec), mkexpr(imm8_mask) ),
13783                         binop( Iop_AndV128, mkexpr(dst_vec),
13784                                unop( Iop_NotV128, mkexpr(imm8_mask) ) ) ) );
13785
13786       goto decode_success;
13787    }
13788
13789
13790    /* 66 0F 3A 41 /r ib = DPPD xmm1, xmm2/m128, imm8
13791       Dot Product of Packed Double Precision Floating-Point Values (XMM) */
13792    if ( have66noF2noF3( pfx ) 
13793         && sz == 2
13794         && insn[0] == 0x0F && insn[1] == 0x3A && insn[2] == 0x41 ) {
13795   
13796       Int imm8;
13797       IRTemp src_vec = newTemp(Ity_V128);
13798       IRTemp dst_vec = newTemp(Ity_V128);
13799       IRTemp and_vec = newTemp(Ity_V128);
13800       IRTemp sum_vec = newTemp(Ity_V128);
13801
13802       modrm = insn[3];
13803
13804       assign( dst_vec, getXMMReg( gregOfRexRM(pfx, modrm) ) );
13805   
13806       if ( epartIsReg( modrm ) ) {
13807          imm8 = (Int)insn[4];
13808          assign( src_vec, getXMMReg( eregOfRexRM(pfx, modrm) ) );
13809          delta += 3+1+1;
13810          DIP( "dppd $%d, %s,%s\n", imm8,
13811               nameXMMReg( eregOfRexRM(pfx, modrm) ),
13812               nameXMMReg( gregOfRexRM(pfx, modrm) ) );    
13813       } else {
13814          addr = disAMode( &alen, vbi, pfx, delta+3, dis_buf, 
13815                           1/* imm8 is 1 byte after the amode */ );
13816          assign( src_vec, loadLE( Ity_V128, mkexpr(addr) ) );
13817          imm8 = (Int)insn[2+alen+1];
13818          delta += 3+alen+1;
13819          DIP( "dppd $%d, %s,%s\n", 
13820               imm8, dis_buf, nameXMMReg( gregOfRexRM(pfx, modrm) ) );
13821       }
13822
13823       UShort imm8_perms[4] = { 0x0000, 0x00FF, 0xFF00, 0xFFFF };
13824
13825       assign( and_vec, binop( Iop_AndV128,
13826                               binop( Iop_Mul64Fx2,
13827                                      mkexpr(dst_vec), mkexpr(src_vec) ),
13828                               mkV128( imm8_perms[ ((imm8 >> 4) & 3) ] ) ) );
13829
13830       assign( sum_vec, binop( Iop_Add64F0x2,
13831                               binop( Iop_InterleaveHI64x2,
13832                                      mkexpr(and_vec), mkexpr(and_vec) ),
13833                               binop( Iop_InterleaveLO64x2,
13834                                      mkexpr(and_vec), mkexpr(and_vec) ) ) );
13835
13836       putXMMReg( gregOfRexRM( pfx, modrm ),
13837                  binop( Iop_AndV128,
13838                         binop( Iop_InterleaveLO64x2,
13839                                mkexpr(sum_vec), mkexpr(sum_vec) ),
13840                         mkV128( imm8_perms[ (imm8 & 3) ] ) ) );
13841
13842       goto decode_success;
13843    }
13844
13845
13846    /* 66 0F 3A 40 /r ib = DPPS xmm1, xmm2/m128, imm8
13847       Dot Product of Packed Single Precision Floating-Point Values (XMM) */
13848    if ( have66noF2noF3( pfx ) 
13849         && sz == 2
13850         && insn[0] == 0x0F
13851         && insn[1] == 0x3A
13852         && insn[2] == 0x40 ) {
13853
13854       Int imm8;
13855       IRTemp xmm1_vec     = newTemp(Ity_V128);
13856       IRTemp xmm2_vec     = newTemp(Ity_V128);
13857       IRTemp tmp_prod_vec = newTemp(Ity_V128);
13858       IRTemp prod_vec     = newTemp(Ity_V128);
13859       IRTemp sum_vec      = newTemp(Ity_V128);
13860       IRTemp v3, v2, v1, v0;
13861       v3 = v2 = v1 = v0   = IRTemp_INVALID;
13862
13863       modrm = insn[3];
13864
13865       assign( xmm1_vec, getXMMReg( gregOfRexRM(pfx, modrm) ) );
13866
13867       if ( epartIsReg( modrm ) ) {
13868          imm8 = (Int)insn[4];
13869          assign( xmm2_vec, getXMMReg( eregOfRexRM(pfx, modrm) ) );
13870          delta += 3+1+1;
13871          DIP( "dpps $%d, %s,%s\n", imm8,
13872               nameXMMReg( eregOfRexRM(pfx, modrm) ),
13873               nameXMMReg( gregOfRexRM(pfx, modrm) ) );    
13874       } else {
13875          addr = disAMode( &alen, vbi, pfx, delta+3, dis_buf, 
13876                           1/* imm8 is 1 byte after the amode */ );
13877          assign( xmm2_vec, loadLE( Ity_V128, mkexpr(addr) ) );
13878          imm8 = (Int)insn[2+alen+1];
13879          delta += 3+alen+1;
13880          DIP( "dpps $%d, %s,%s\n", 
13881               imm8, dis_buf, nameXMMReg( gregOfRexRM(pfx, modrm) ) );
13882       }
13883
13884       UShort imm8_perms[16] = { 0x0000, 0x000F, 0x00F0, 0x00FF, 0x0F00, 
13885                                 0x0F0F, 0x0FF0, 0x0FFF, 0xF000, 0xF00F,
13886                                 0xF0F0, 0xF0FF, 0xFF00, 0xFF0F, 0xFFF0, 0xFFFF };
13887
13888       assign( tmp_prod_vec, 
13889               binop( Iop_AndV128, 
13890                      binop( Iop_Mul32Fx4, mkexpr(xmm1_vec), mkexpr(xmm2_vec) ), 
13891                      mkV128( imm8_perms[((imm8 >> 4)& 15)] ) ) );
13892       breakup128to32s( tmp_prod_vec, &v3, &v2, &v1, &v0 );
13893       assign( prod_vec, mk128from32s( v3, v1, v2, v0 ) );
13894
13895       assign( sum_vec, binop( Iop_Add32Fx4,
13896                               binop( Iop_InterleaveHI32x4, 
13897                                      mkexpr(prod_vec), mkexpr(prod_vec) ), 
13898                               binop( Iop_InterleaveLO32x4, 
13899                                      mkexpr(prod_vec), mkexpr(prod_vec) ) ) );
13900
13901       putXMMReg( gregOfRexRM(pfx, modrm), 
13902                  binop( Iop_AndV128, 
13903                         binop( Iop_Add32Fx4,
13904                                binop( Iop_InterleaveHI32x4,
13905                                       mkexpr(sum_vec), mkexpr(sum_vec) ), 
13906                                binop( Iop_InterleaveLO32x4,
13907                                       mkexpr(sum_vec), mkexpr(sum_vec) ) ), 
13908                         mkV128( imm8_perms[ (imm8 & 15) ] ) ) );
13909
13910       goto decode_success;
13911    }
13912
13913
13914    /* 66 0F 3A 21 /r ib = INSERTPS xmm1, xmm2/m32, imm8
13915       Insert Packed Single Precision Floating-Point Value (XMM) */
13916    if ( have66noF2noF3( pfx ) 
13917         && sz == 2 
13918         && insn[0] == 0x0F && insn[1] == 0x3A && insn[2] == 0x21 ) {
13919
13920       Int imm8;
13921       Int imm8_count_s;
13922       Int imm8_count_d;
13923       Int imm8_zmask;
13924       IRTemp dstVec   = newTemp(Ity_V128);
13925       IRTemp srcDWord = newTemp(Ity_I32);   
13926
13927       modrm = insn[3];
13928
13929       assign( dstVec, getXMMReg( gregOfRexRM(pfx, modrm) ) );
13930
13931       if ( epartIsReg( modrm ) ) {
13932          IRTemp src_vec = newTemp(Ity_V128);
13933          assign( src_vec, getXMMReg( eregOfRexRM(pfx, modrm) ) );
13934
13935          IRTemp src_lane_0 = IRTemp_INVALID;
13936          IRTemp src_lane_1 = IRTemp_INVALID;
13937          IRTemp src_lane_2 = IRTemp_INVALID;
13938          IRTemp src_lane_3 = IRTemp_INVALID;
13939          breakup128to32s( src_vec, 
13940                           &src_lane_3, &src_lane_2, &src_lane_1, &src_lane_0 );
13941
13942          imm8 = (Int)insn[4];
13943          imm8_count_s = ((imm8 >> 6) & 3);
13944          switch( imm8_count_s ) {
13945            case 0:  assign( srcDWord, mkexpr(src_lane_0) ); break;
13946            case 1:  assign( srcDWord, mkexpr(src_lane_1) ); break;
13947            case 2:  assign( srcDWord, mkexpr(src_lane_2) ); break;
13948            case 3:  assign( srcDWord, mkexpr(src_lane_3) ); break;
13949            default: vassert(0);                             break;
13950          }
13951
13952          delta += 3+1+1;
13953          DIP( "insertps $%d, %s,%s\n", imm8,
13954               nameXMMReg( eregOfRexRM(pfx, modrm) ),
13955               nameXMMReg( gregOfRexRM(pfx, modrm) ) );
13956       } else {
13957          addr = disAMode( &alen, vbi, pfx, delta+3, dis_buf, 
13958                           1/* const imm8 is 1 byte after the amode */ );
13959          assign( srcDWord, loadLE( Ity_I32, mkexpr(addr) ) );
13960          imm8 = (Int)insn[2+alen+1];
13961          imm8_count_s = 0;
13962          delta += 3+alen+1;
13963          DIP( "insertps $%d, %s,%s\n", 
13964               imm8, dis_buf, nameXMMReg( gregOfRexRM(pfx, modrm) ) );
13965       }
13966
13967       IRTemp dst_lane_0 = IRTemp_INVALID;
13968       IRTemp dst_lane_1 = IRTemp_INVALID;
13969       IRTemp dst_lane_2 = IRTemp_INVALID;
13970       IRTemp dst_lane_3 = IRTemp_INVALID;
13971       breakup128to32s( dstVec,
13972                        &dst_lane_3, &dst_lane_2, &dst_lane_1, &dst_lane_0 );
13973
13974       imm8_count_d = ((imm8 >> 4) & 3);
13975       switch( imm8_count_d ) {
13976          case 0:  dst_lane_0 = srcDWord; break;
13977          case 1:  dst_lane_1 = srcDWord; break;
13978          case 2:  dst_lane_2 = srcDWord; break;
13979          case 3:  dst_lane_3 = srcDWord; break;
13980          default: vassert(0);            break;
13981       }
13982
13983       imm8_zmask = (imm8 & 15);
13984       IRTemp zero_32 = newTemp(Ity_I32);
13985       assign( zero_32, mkU32(0) );
13986
13987       IRExpr* ire_vec_128 = mk128from32s( 
13988                                ((imm8_zmask & 8) == 8) ? zero_32 : dst_lane_3, 
13989                                ((imm8_zmask & 4) == 4) ? zero_32 : dst_lane_2, 
13990                                ((imm8_zmask & 2) == 2) ? zero_32 : dst_lane_1, 
13991                                ((imm8_zmask & 1) == 1) ? zero_32 : dst_lane_0 );
13992
13993       putXMMReg( gregOfRexRM(pfx, modrm), ire_vec_128 );
13994  
13995       goto decode_success;
13996    }
13997
13998
13999   /* 66 0F 3A 14 /r ib = PEXTRB r/m16, xmm, imm8
14000      Extract Byte from xmm, store in mem or zero-extend + store in gen.reg. (XMM) */
14001   if ( have66noF2noF3( pfx ) 
14002        && sz == 2 
14003        && insn[0] == 0x0F && insn[1] == 0x3A && insn[2] == 0x14 ) {
14004
14005      Int imm8;
14006      IRTemp xmm_vec  = newTemp(Ity_V128);
14007      IRTemp sel_lane = newTemp(Ity_I32);
14008      IRTemp shr_lane = newTemp(Ity_I32);
14009
14010      modrm = insn[3];
14011      assign( xmm_vec, getXMMReg( gregOfRexRM(pfx,modrm) ) );
14012      breakup128to32s( xmm_vec, &t3, &t2, &t1, &t0 );
14013
14014      if ( epartIsReg( modrm ) ) {
14015         imm8 = (Int)insn[3+1];
14016      } else {
14017         addr = disAMode( &alen, vbi, pfx, delta+3, dis_buf, 1 );
14018         imm8 = (Int)insn[3+alen];
14019      }
14020      switch( (imm8 >> 2) & 3 ) {
14021         case 0:  assign( sel_lane, mkexpr(t0) ); break;
14022         case 1:  assign( sel_lane, mkexpr(t1) ); break;
14023         case 2:  assign( sel_lane, mkexpr(t2) ); break;
14024         case 3:  assign( sel_lane, mkexpr(t3) ); break;
14025         default: vassert(0);
14026      }
14027      assign( shr_lane, 
14028              binop( Iop_Shr32, mkexpr(sel_lane), mkU8(((imm8 & 3)*8)) ) );
14029
14030      if ( epartIsReg( modrm ) ) {
14031         putIReg64( eregOfRexRM(pfx,modrm), 
14032                    unop( Iop_32Uto64, 
14033                          binop(Iop_And32, mkexpr(shr_lane), mkU32(255)) ) );
14034
14035         delta += 3+1+1;
14036         DIP( "pextrb $%d, %s,%s\n", imm8, 
14037              nameXMMReg( gregOfRexRM(pfx, modrm) ), 
14038              nameIReg64( eregOfRexRM(pfx, modrm) ) );
14039      } else {
14040         storeLE( mkexpr(addr), unop(Iop_32to8, mkexpr(shr_lane) ) );
14041         delta += 3+alen+1;
14042         DIP( "$%d, pextrb %s,%s\n", 
14043              imm8, nameXMMReg( gregOfRexRM(pfx, modrm) ), dis_buf );
14044      }
14045
14046      goto decode_success;
14047   }
14048
14049
14050    /* 66 0F 3A 16 /r ib = PEXTRD reg/mem32, xmm2, imm8
14051       Extract Doubleword int from xmm reg and store in gen.reg or mem. (XMM) 
14052       Note that this insn has the same opcodes as PEXTRQ, but 
14053       here the REX.W bit is _not_ present */
14054    if ( have66noF2noF3( pfx ) 
14055         && sz == 2  /* REX.W is _not_ present */
14056         && insn[0] == 0x0F && insn[1] == 0x3A && insn[2] == 0x16 ) {
14057
14058       Int imm8_10;
14059       IRTemp xmm_vec   = newTemp(Ity_V128);
14060       IRTemp src_dword = newTemp(Ity_I32);
14061
14062       modrm = insn[3];
14063       assign( xmm_vec, getXMMReg( gregOfRexRM(pfx,modrm) ) );
14064       breakup128to32s( xmm_vec, &t3, &t2, &t1, &t0 );
14065
14066       if ( epartIsReg( modrm ) ) {
14067          imm8_10 = (Int)(insn[3+1] & 3);
14068       } else { 
14069          addr = disAMode( &alen, vbi, pfx, delta+3, dis_buf, 1 );
14070          imm8_10 = (Int)(insn[3+alen] & 3);
14071       }
14072
14073       switch ( imm8_10 ) {
14074          case 0:  assign( src_dword, mkexpr(t0) ); break;
14075          case 1:  assign( src_dword, mkexpr(t1) ); break;
14076          case 2:  assign( src_dword, mkexpr(t2) ); break;
14077          case 3:  assign( src_dword, mkexpr(t3) ); break;
14078          default: vassert(0);
14079       }
14080
14081       if ( epartIsReg( modrm ) ) {
14082          putIReg32( eregOfRexRM(pfx,modrm), mkexpr(src_dword) );
14083          delta += 3+1+1;
14084          DIP( "pextrd $%d, %s,%s\n", imm8_10,
14085               nameXMMReg( gregOfRexRM(pfx, modrm) ),
14086               nameIReg32( eregOfRexRM(pfx, modrm) ) );
14087       } else {
14088          storeLE( mkexpr(addr), mkexpr(src_dword) );
14089          delta += 3+alen+1;
14090          DIP( "pextrd $%d, %s,%s\n", 
14091               imm8_10, nameXMMReg( gregOfRexRM(pfx, modrm) ), dis_buf );
14092       }
14093
14094       goto decode_success;
14095    }
14096
14097
14098    /* 66 REX.W 0F 3A 16 /r ib = PEXTRQ reg/mem64, xmm2, imm8
14099       Extract Quadword int from xmm reg and store in gen.reg or mem. (XMM) 
14100       Note that this insn has the same opcodes as PEXTRD, but 
14101       here the REX.W bit is present */
14102    if ( have66noF2noF3( pfx ) 
14103         && sz == 8  /* REX.W is present */
14104         && insn[0] == 0x0F && insn[1] == 0x3A && insn[2] == 0x16 ) {
14105
14106       Int imm8_0;
14107       IRTemp xmm_vec   = newTemp(Ity_V128);
14108       IRTemp src_qword = newTemp(Ity_I64);
14109
14110       modrm = insn[3];
14111       assign( xmm_vec, getXMMReg( gregOfRexRM(pfx,modrm) ) );
14112
14113       if ( epartIsReg( modrm ) ) {
14114          imm8_0 = (Int)(insn[3+1] & 1);
14115       } else {
14116          addr   = disAMode( &alen, vbi, pfx, delta+3, dis_buf, 1 );
14117          imm8_0 = (Int)(insn[3+alen] & 1);
14118       }
14119       switch ( imm8_0 ) {
14120          case 0:  assign( src_qword, unop(Iop_V128to64,   mkexpr(xmm_vec)) ); break;
14121          case 1:  assign( src_qword, unop(Iop_V128HIto64, mkexpr(xmm_vec)) ); break;
14122          default: vassert(0);
14123       }
14124
14125       if ( epartIsReg( modrm ) ) {
14126          putIReg64( eregOfRexRM(pfx,modrm), mkexpr(src_qword) );
14127          delta += 3+1+1;
14128          DIP( "pextrq $%d, %s,%s\n", imm8_0,
14129               nameXMMReg( gregOfRexRM(pfx, modrm) ),
14130               nameIReg64( eregOfRexRM(pfx, modrm) ) );
14131       } else {
14132          storeLE( mkexpr(addr), mkexpr(src_qword) );
14133          delta += 3+alen+1;
14134          DIP( "pextrq $%d, %s,%s\n", 
14135               imm8_0, nameXMMReg( gregOfRexRM(pfx, modrm) ), dis_buf );
14136       }
14137
14138       goto decode_success;
14139    }
14140
14141
14142    /* 66 0F 3A 15 /r ib = PEXTRW r/m16, xmm, imm8
14143       Extract Word from xmm, store in mem or zero-extend + store in gen.reg. (XMM) */
14144    if ( have66noF2noF3( pfx ) 
14145         && sz == 2 
14146         && insn[0] == 0x0F && insn[1] == 0x3A && insn[2] == 0x15 ) {
14147
14148       Int imm8_20;
14149       IRTemp xmm_vec = newTemp(Ity_V128);
14150       IRTemp src_word = newTemp(Ity_I16);
14151
14152       modrm = insn[3];
14153       assign( xmm_vec, getXMMReg( gregOfRexRM(pfx,modrm) ) );
14154       breakup128to32s( xmm_vec, &t3, &t2, &t1, &t0 );
14155
14156       if ( epartIsReg( modrm ) ) {
14157          imm8_20 = (Int)(insn[3+1] & 7);
14158       } else {
14159          addr = disAMode( &alen, vbi, pfx, delta+3, dis_buf, 1 );
14160          imm8_20 = (Int)(insn[3+alen] & 7);
14161       }
14162
14163       switch ( imm8_20 ) {
14164          case 0:  assign( src_word, unop(Iop_32to16,   mkexpr(t0)) ); break;
14165          case 1:  assign( src_word, unop(Iop_32HIto16, mkexpr(t0)) ); break;
14166          case 2:  assign( src_word, unop(Iop_32to16,   mkexpr(t1)) ); break;
14167          case 3:  assign( src_word, unop(Iop_32HIto16, mkexpr(t1)) ); break;
14168          case 4:  assign( src_word, unop(Iop_32to16,   mkexpr(t2)) ); break;
14169          case 5:  assign( src_word, unop(Iop_32HIto16, mkexpr(t2)) ); break;
14170          case 6:  assign( src_word, unop(Iop_32to16,   mkexpr(t3)) ); break;
14171          case 7:  assign( src_word, unop(Iop_32HIto16, mkexpr(t3)) ); break;
14172          default: vassert(0);
14173       }
14174
14175       if ( epartIsReg( modrm ) ) {
14176          putIReg64( eregOfRexRM(pfx,modrm), unop(Iop_16Uto64, mkexpr(src_word)) );
14177          delta += 3+1+1;
14178          DIP( "pextrw $%d, %s,%s\n", imm8_20, 
14179               nameXMMReg( gregOfRexRM(pfx, modrm) ),
14180               nameIReg64( eregOfRexRM(pfx, modrm) ) );
14181       } else {
14182          storeLE( mkexpr(addr), mkexpr(src_word) );
14183          delta += 3+alen+1;
14184          DIP( "pextrw $%d, %s,%s\n", 
14185               imm8_20, nameXMMReg( gregOfRexRM(pfx, modrm) ), dis_buf );
14186       }
14187
14188       goto decode_success;
14189    }
14190
14191
14192    /* 66 REX.W 0F 3A 22 /r ib = PINSRQ xmm1, r/m64, imm8
14193       Extract Quadword int from gen.reg/mem64 and insert into xmm1 */
14194    if ( have66noF2noF3( pfx ) 
14195         && sz == 8  /* REX.W is present */
14196         && insn[0] == 0x0F && insn[1] == 0x3A && insn[2] == 0x22 ) {
14197
14198       Int imm8_0;
14199       IRTemp src_elems = newTemp(Ity_I64);
14200       IRTemp src_vec   = newTemp(Ity_V128);
14201
14202       modrm = insn[3];
14203
14204       if ( epartIsReg( modrm ) ) {
14205          imm8_0 = (Int)(insn[3+1] & 1);
14206          assign( src_elems, getIReg64( eregOfRexRM(pfx,modrm) ) );
14207          delta += 3+1+1;
14208          DIP( "pinsrq $%d, %s,%s\n", imm8_0,
14209               nameIReg64( eregOfRexRM(pfx, modrm) ),
14210               nameXMMReg( gregOfRexRM(pfx, modrm) ) );
14211       } else {
14212          addr = disAMode( &alen, vbi, pfx, delta+3, dis_buf, 1 );
14213          imm8_0 = (Int)(insn[3+alen] & 1);
14214          assign( src_elems, loadLE( Ity_I64, mkexpr(addr) ) );
14215          delta += 3+alen+1;
14216          DIP( "pinsrq $%d, %s,%s\n", 
14217               imm8_0, dis_buf, nameXMMReg( gregOfRexRM(pfx, modrm) ) );
14218       }
14219
14220       UShort mask = 0;
14221       if ( imm8_0 == 0 ) { 
14222          mask = 0xFF00; 
14223          assign( src_vec,  binop( Iop_64HLtoV128, mkU64(0), mkexpr(src_elems) ) );
14224       } else {
14225          mask = 0x00FF;
14226          assign( src_vec, binop( Iop_64HLtoV128, mkexpr(src_elems), mkU64(0) ) );
14227       }
14228
14229       putXMMReg( gregOfRexRM(pfx, modrm), 
14230                  binop( Iop_OrV128, mkexpr(src_vec),
14231                         binop( Iop_AndV128, 
14232                                getXMMReg( gregOfRexRM(pfx, modrm) ),
14233                                mkV128(mask) ) ) );
14234
14235       goto decode_success;
14236    }
14237
14238
14239    /* 66 0F 38 3D /r = PMAXSD xmm1, xmm2/m128
14240       Maximum of Packed Signed Double Word Integers (XMM) 
14241       --
14242       66 0F 38 39 /r = PMINSD xmm1, xmm2/m128
14243       Minimum of Packed Signed Double Word Integers (XMM) */
14244    if ( have66noF2noF3( pfx ) 
14245         && sz == 2 
14246         && insn[0] == 0x0F && insn[1] == 0x38
14247         && ( (insn[2] == 0x3D) || (insn[2] == 0x39) ) ) {
14248
14249       IRTemp reg_vec  = newTemp(Ity_V128);
14250       IRTemp rom_vec  = newTemp(Ity_V128);
14251       IRTemp mask_vec = newTemp(Ity_V128);
14252
14253       Bool isPMAX     = (insn[2] == 0x3D) ? True : False;
14254
14255       HChar* str      = isPMAX ? "pmaxsd" : "pminsd";
14256
14257       modrm = insn[3];
14258       assign( reg_vec, getXMMReg( gregOfRexRM(pfx, modrm) ) );
14259
14260       if ( epartIsReg( modrm ) ) {
14261          assign( rom_vec, getXMMReg( eregOfRexRM(pfx, modrm) ) );
14262          delta += 3+1;
14263          DIP( "%s %s,%s\n", str,
14264               nameXMMReg( eregOfRexRM(pfx, modrm) ),
14265               nameXMMReg( gregOfRexRM(pfx, modrm) ) );    
14266       } else {
14267          addr = disAMode( &alen, vbi, pfx, delta+3, dis_buf, 0 );
14268          assign( rom_vec, loadLE( Ity_V128, mkexpr(addr) ) );
14269          delta += 3+alen;
14270          DIP( "%s %s,%s\n", str, dis_buf, nameXMMReg( gregOfRexRM(pfx, modrm) ) );
14271       }
14272
14273       assign( mask_vec, binop( Iop_CmpGT32Sx4, mkexpr(reg_vec), mkexpr(rom_vec) ) );
14274
14275       IRTemp max_min_vec = newTemp(Ity_V128);
14276       if ( isPMAX ) {
14277          assign( max_min_vec,
14278                  binop( Iop_OrV128, 
14279                         binop( Iop_AndV128, mkexpr(rom_vec),
14280                                unop( Iop_NotV128, mkexpr(mask_vec) ) ),
14281                         binop( Iop_AndV128, mkexpr(reg_vec), mkexpr(mask_vec) ) ) );
14282       } else {
14283          assign( max_min_vec, 
14284                  binop( Iop_OrV128, 
14285                         binop( Iop_AndV128, mkexpr(reg_vec),
14286                                unop( Iop_NotV128, mkexpr(mask_vec) ) ), 
14287                         binop( Iop_AndV128, mkexpr(rom_vec), mkexpr(mask_vec) ) ) );
14288       }
14289
14290       putXMMReg( gregOfRexRM(pfx, modrm), mkexpr(max_min_vec) );
14291
14292       goto decode_success;
14293    }
14294
14295
14296    /* 66 0F 38 3F /r = PMAXUD xmm1, xmm2/m128
14297       Maximum of Packed Unsigned Doubleword Integers (XMM) */
14298    if ( have66noF2noF3( pfx ) 
14299         && sz == 2 
14300         && insn[0] == 0x0F && insn[1] == 0x38 && insn[2] == 0x3F ) {
14301
14302       IRTemp reg_vec  = newTemp(Ity_V128);
14303       IRTemp rom_vec  = newTemp(Ity_V128);
14304       IRTemp mask_vec = newTemp(Ity_V128);
14305       IRTemp and_vec  = newTemp(Ity_V128);
14306       IRTemp not_vec  = newTemp(Ity_V128);
14307   
14308       modrm = insn[3];
14309       assign( reg_vec, getXMMReg( gregOfRexRM(pfx, modrm) ) );
14310
14311       if ( epartIsReg( modrm ) ) {
14312          assign( rom_vec, getXMMReg( eregOfRexRM(pfx, modrm) ) );
14313          delta += 3+1;
14314          DIP( "pmaxud %s,%s\n", 
14315               nameXMMReg( eregOfRexRM(pfx, modrm) ),
14316               nameXMMReg( gregOfRexRM(pfx, modrm) ) );    
14317       } else {
14318          addr = disAMode( &alen, vbi, pfx, delta+3, dis_buf, 0 );
14319          assign( rom_vec, loadLE( Ity_V128, mkexpr(addr) ) );
14320          delta += 3+alen;
14321          DIP( "pmaxud %s,%s\n", dis_buf, nameXMMReg( gregOfRexRM(pfx, modrm) ) );
14322       }
14323
14324       /* the foll. simulates Iop_CmpGT32Ux4 (not implemented) 
14325          c.f. Hacker's Delight, S2-11, p.23 */
14326       assign( mask_vec, 
14327               binop( Iop_XorV128, 
14328                      binop( Iop_XorV128, 
14329                             binop( Iop_CmpGT32Sx4, mkexpr(reg_vec), mkexpr(rom_vec) ),
14330                             binop( Iop_SarN32x4, mkexpr(reg_vec), mkU8(31) ) ), 
14331                      binop( Iop_SarN32x4, mkexpr(rom_vec), mkU8(31) ) ) );
14332
14333       assign( and_vec, binop( Iop_AndV128, mkexpr(reg_vec), mkexpr(mask_vec) ) );
14334       assign( not_vec, binop( Iop_AndV128, mkexpr(rom_vec), 
14335                               unop( Iop_NotV128, mkexpr(mask_vec) ) ) );
14336
14337       putXMMReg( gregOfRexRM(pfx, modrm), 
14338                  binop( Iop_OrV128, mkexpr(not_vec), mkexpr(and_vec) ) );
14339  
14340       goto decode_success;
14341    }
14342
14343
14344    /* 66 0f 38 20 /r = PMOVSXBW xmm1, xmm2/m64 
14345       Packed Move with Sign Extend from Byte to Word (XMM) */
14346    if ( have66noF2noF3( pfx ) 
14347         && sz == 2 
14348         && insn[0] == 0x0F && insn[1] == 0x38 && insn[2] == 0x20 ) {
14349   
14350       modrm = insn[3];
14351
14352       IRTemp srcVec = newTemp(Ity_V128);
14353
14354       if ( epartIsReg( modrm ) ) {
14355          assign( srcVec, getXMMReg( eregOfRexRM(pfx, modrm) ) );
14356          delta += 3+1;
14357          DIP( "pmovsxbw %s,%s\n",
14358               nameXMMReg( eregOfRexRM(pfx, modrm) ),
14359               nameXMMReg( gregOfRexRM(pfx, modrm) ) );
14360       } else { 
14361          addr = disAMode( &alen, vbi, pfx, delta+3, dis_buf, 0 );
14362          assign( srcVec, 
14363                  unop( Iop_64UtoV128, loadLE( Ity_I64, mkexpr(addr) ) ) );
14364          delta += 3+alen;
14365          DIP( "pmovsxbw %s,%s\n",
14366               dis_buf, nameXMMReg( gregOfRexRM(pfx, modrm) ) );
14367       }
14368      
14369       putXMMReg( gregOfRexRM(pfx, modrm), 
14370                  binop( Iop_SarN16x8, 
14371                         binop( Iop_ShlN16x8, 
14372                                binop( Iop_InterleaveLO8x16,
14373                                       IRExpr_Const( IRConst_V128(0) ),
14374                                       mkexpr(srcVec) ),
14375                                mkU8(8) ),
14376                         mkU8(8) ) );
14377      
14378       goto decode_success;
14379    }
14380
14381
14382    /* 66 0f 38 21 /r = PMOVSXBD xmm1, xmm2/m32 
14383       Packed Move with Sign Extend from Byte to DWord (XMM) */
14384    if ( have66noF2noF3( pfx ) 
14385         && sz == 2 
14386         && insn[0] == 0x0F && insn[1] == 0x38 && insn[2] == 0x21 ) {
14387   
14388       modrm = insn[3];
14389
14390       IRTemp srcVec = newTemp(Ity_V128);
14391
14392       if ( epartIsReg( modrm ) ) {
14393          assign( srcVec, getXMMReg( eregOfRexRM(pfx, modrm) ) );
14394          delta += 3+1;
14395          DIP( "pmovsxbd %s,%s\n",
14396               nameXMMReg( eregOfRexRM(pfx, modrm) ),
14397               nameXMMReg( gregOfRexRM(pfx, modrm) )  );
14398       } else {
14399          addr = disAMode( &alen, vbi, pfx, delta+3, dis_buf, 0 );
14400          assign( srcVec, 
14401                  unop( Iop_32UtoV128, loadLE( Ity_I32, mkexpr(addr) ) ) );
14402          delta += 3+alen;
14403          DIP( "pmovsxbd %s,%s\n",
14404               dis_buf, nameXMMReg( gregOfRexRM(pfx, modrm) ) );
14405       }
14406
14407       IRTemp zeroVec = newTemp(Ity_V128);
14408       assign( zeroVec, IRExpr_Const( IRConst_V128(0) ) );
14409
14410       putXMMReg( gregOfRexRM(pfx, modrm), 
14411                  binop( Iop_SarN32x4, 
14412                         binop( Iop_ShlN32x4, 
14413                                binop( Iop_InterleaveLO8x16, 
14414                                       mkexpr(zeroVec), 
14415                                       binop( Iop_InterleaveLO8x16, 
14416                                              mkexpr(zeroVec), 
14417                                              mkexpr(srcVec) ) ), 
14418                                mkU8(24) ), mkU8(24) ) );
14419
14420       goto decode_success;
14421    }
14422
14423
14424    /* 66 0f 38 22 /r = PMOVSXBQ xmm1, xmm2/m16
14425       Packed Move with Sign Extend from Byte to QWord (XMM) */
14426    if ( have66noF2noF3(pfx) 
14427         && sz == 2 
14428         && insn[0] == 0x0F && insn[1] == 0x38 && insn[2] == 0x22 ) {
14429      
14430       modrm = insn[3];
14431
14432       IRTemp srcBytes = newTemp(Ity_I16);
14433
14434       if ( epartIsReg(modrm) ) {
14435          assign( srcBytes, getXMMRegLane16( eregOfRexRM(pfx, modrm), 0 ) );
14436          delta += 3+1;
14437          DIP( "pmovsxbq %s,%s\n",
14438               nameXMMReg( eregOfRexRM(pfx, modrm) ),
14439               nameXMMReg( gregOfRexRM(pfx, modrm) ) );
14440       } else {
14441          addr = disAMode( &alen, vbi, pfx, delta+3, dis_buf, 0 );
14442          assign( srcBytes, loadLE( Ity_I16, mkexpr(addr) ) );
14443          delta += 3+alen;
14444          DIP( "pmovsxbq %s,%s\n",
14445               dis_buf, nameXMMReg( gregOfRexRM(pfx, modrm) ) );
14446       }
14447
14448       putXMMReg( gregOfRexRM( pfx, modrm ),
14449                  binop( Iop_64HLtoV128,
14450                         unop( Iop_8Sto64,
14451                               unop( Iop_16HIto8,
14452                                     mkexpr(srcBytes) ) ),
14453                         unop( Iop_8Sto64,
14454                               unop( Iop_16to8, mkexpr(srcBytes) ) ) ) );
14455
14456       goto decode_success;
14457    }
14458
14459
14460    /* 66 0f 38 23 /r = PMOVSXWD xmm1, xmm2/m64 
14461       Packed Move with Sign Extend from Word to DWord (XMM) */
14462    if ( have66noF2noF3( pfx ) 
14463         && sz == 2 
14464         && insn[0] == 0x0F && insn[1] == 0x38 && insn[2] == 0x23 ) {
14465
14466       modrm = insn[3];
14467
14468       IRTemp srcVec = newTemp(Ity_V128);
14469
14470       if ( epartIsReg(modrm) ) {
14471          assign( srcVec, getXMMReg( eregOfRexRM(pfx, modrm) ) );
14472          delta += 3+1;
14473          DIP( "pmovsxwd %s,%s\n", 
14474               nameXMMReg( eregOfRexRM(pfx, modrm) ),
14475               nameXMMReg( gregOfRexRM(pfx, modrm) ) );
14476       } else {
14477          addr = disAMode( &alen, vbi, pfx, delta+3, dis_buf, 0 );
14478          assign( srcVec, 
14479                  unop( Iop_64UtoV128, loadLE( Ity_I64, mkexpr(addr) ) ) );
14480          delta += 3+alen;
14481          DIP( "pmovsxwd %s,%s\n", 
14482               dis_buf, nameXMMReg( gregOfRexRM(pfx, modrm) ) );
14483       }
14484
14485       putXMMReg( gregOfRexRM(pfx, modrm), 
14486                  binop( Iop_SarN32x4, 
14487                         binop( Iop_ShlN32x4, 
14488                                binop( Iop_InterleaveLO16x8, 
14489                                       IRExpr_Const( IRConst_V128(0) ), 
14490                                       mkexpr(srcVec) ), 
14491                                mkU8(16) ), 
14492                         mkU8(16) ) );
14493
14494       goto decode_success;
14495    }
14496
14497
14498    /* 66 0f 38 24 /r = PMOVSXWQ xmm1, xmm2/m32
14499       Packed Move with Sign Extend from Word to QWord (XMM) */
14500    if ( have66noF2noF3( pfx ) 
14501         && sz == 2 
14502         && insn[0] == 0x0F && insn[1] == 0x38 && insn[2] == 0x24 ) {
14503
14504       modrm = insn[3];
14505
14506       IRTemp srcBytes = newTemp(Ity_I32);
14507
14508       if ( epartIsReg( modrm ) ) {
14509          assign( srcBytes, getXMMRegLane32( eregOfRexRM(pfx, modrm), 0 ) );
14510          delta += 3+1;
14511          DIP( "pmovsxwq %s,%s\n", 
14512               nameXMMReg( eregOfRexRM(pfx, modrm) ), 
14513               nameXMMReg( gregOfRexRM(pfx, modrm) ) );
14514       } else {
14515          addr = disAMode( &alen, vbi, pfx, delta+3, dis_buf, 0 );
14516          assign( srcBytes, loadLE( Ity_I32, mkexpr(addr) ) );
14517          delta += 3+alen;
14518          DIP( "pmovsxwq %s,%s\n",
14519               dis_buf, nameXMMReg( gregOfRexRM(pfx, modrm) ) );
14520       }
14521
14522       putXMMReg( gregOfRexRM( pfx, modrm ), 
14523                  binop( Iop_64HLtoV128, 
14524                         unop( Iop_16Sto64, 
14525                               unop( Iop_32HIto16, mkexpr(srcBytes) ) ), 
14526                         unop( Iop_16Sto64, 
14527                               unop( Iop_32to16, mkexpr(srcBytes) ) ) ) );
14528
14529       goto decode_success;
14530    }
14531
14532
14533    /* 66 0f 38 25 /r = PMOVSXDQ xmm1, xmm2/m64
14534       Packed Move with Sign Extend from Double Word to Quad Word (XMM) */
14535    if ( have66noF2noF3( pfx )
14536         && sz == 2 
14537         && insn[0] == 0x0F && insn[1] == 0x38 && insn[2] == 0x25 ) {
14538   
14539       modrm = insn[3];
14540
14541       IRTemp srcBytes = newTemp(Ity_I64);
14542
14543       if ( epartIsReg(modrm) ) {
14544          assign( srcBytes, getXMMRegLane64( eregOfRexRM(pfx, modrm), 0 ) );
14545          delta += 3+1;
14546          DIP( "pmovsxdq %s,%s\n", 
14547               nameXMMReg( eregOfRexRM(pfx, modrm) ),
14548               nameXMMReg( gregOfRexRM(pfx, modrm) ) );
14549       } else {
14550          addr = disAMode( &alen, vbi, pfx, delta+3, dis_buf, 0 );
14551          assign( srcBytes, loadLE( Ity_I64, mkexpr(addr) ) );
14552          delta += 3+alen;
14553          DIP( "pmovsxdq %s,%s\n",
14554               dis_buf, nameXMMReg( gregOfRexRM(pfx, modrm) ) );
14555       }
14556
14557       putXMMReg( gregOfRexRM(pfx, modrm), 
14558                  binop( Iop_64HLtoV128, 
14559                         unop( Iop_32Sto64, 
14560                               unop( Iop_64HIto32, mkexpr(srcBytes) ) ), 
14561                         unop( Iop_32Sto64, 
14562                               unop( Iop_64to32, mkexpr(srcBytes) ) ) ) );
14563
14564       goto decode_success;
14565    }
14566
14567
14568    /* 66 0f 38 30 /r = PMOVZXBW xmm1, xmm2/m64 
14569       Packed Move with Zero Extend from Byte to Word (XMM) */
14570    if ( have66noF2noF3(pfx) 
14571         && sz == 2 
14572         && insn[0] == 0x0F && insn[1] == 0x38 && insn[2] == 0x30 ) {
14573   
14574       modrm = insn[3];
14575
14576       IRTemp srcVec = newTemp(Ity_V128);
14577
14578       if ( epartIsReg(modrm) ) {
14579          assign( srcVec, getXMMReg( eregOfRexRM(pfx, modrm) ) );
14580          delta += 3+1;
14581          DIP( "pmovzxbw %s,%s\n",
14582               nameXMMReg( eregOfRexRM(pfx, modrm) ),
14583               nameXMMReg( gregOfRexRM(pfx, modrm) ) );
14584       } else {
14585          addr = disAMode( &alen, vbi, pfx, delta+3, dis_buf, 0 );
14586          assign( srcVec, 
14587                  unop( Iop_64UtoV128, loadLE( Ity_I64, mkexpr(addr) ) ) );
14588          delta += 3+alen;
14589          DIP( "pmovzxbw %s,%s\n",
14590               dis_buf, nameXMMReg( gregOfRexRM(pfx, modrm) ) );
14591       }
14592
14593       putXMMReg( gregOfRexRM(pfx, modrm), 
14594                  binop( Iop_InterleaveLO8x16, 
14595                         IRExpr_Const( IRConst_V128(0) ), mkexpr(srcVec) ) );
14596
14597       goto decode_success;
14598    }
14599
14600
14601    /* 66 0f 38 31 /r = PMOVZXBD xmm1, xmm2/m32 
14602       Packed Move with Zero Extend from Byte to DWord (XMM) */
14603    if ( have66noF2noF3( pfx ) 
14604         && sz == 2 
14605         && insn[0] == 0x0F && insn[1] == 0x38 && insn[2] == 0x31 ) {
14606   
14607       modrm = insn[3];
14608
14609       IRTemp srcVec = newTemp(Ity_V128);
14610
14611       if ( epartIsReg(modrm) ) {
14612          assign( srcVec, getXMMReg( eregOfRexRM(pfx, modrm) ) );
14613          delta += 3+1;
14614          DIP( "pmovzxbd %s,%s\n",
14615               nameXMMReg( eregOfRexRM(pfx, modrm) ),
14616               nameXMMReg( gregOfRexRM(pfx, modrm) ) );
14617       } else {
14618          addr = disAMode( &alen, vbi, pfx, delta+3, dis_buf, 0 );
14619          assign( srcVec, 
14620                  unop( Iop_32UtoV128, loadLE( Ity_I32, mkexpr(addr) ) ) );
14621          delta += 3+alen;
14622          DIP( "pmovzxbd %s,%s\n",
14623               dis_buf, nameXMMReg( gregOfRexRM(pfx, modrm) ) );
14624       }
14625
14626       IRTemp zeroVec = newTemp(Ity_V128);
14627       assign( zeroVec, IRExpr_Const( IRConst_V128(0) ) );
14628
14629       putXMMReg( gregOfRexRM( pfx, modrm ), 
14630                  binop( Iop_InterleaveLO8x16,
14631                         mkexpr(zeroVec),
14632                         binop( Iop_InterleaveLO8x16, 
14633                                mkexpr(zeroVec), mkexpr(srcVec) ) ) );
14634
14635       goto decode_success;
14636    }
14637
14638
14639    /* 66 0f 38 32 /r = PMOVZXBQ xmm1, xmm2/m16
14640       Packed Move with Zero Extend from Byte to QWord (XMM) */
14641    if ( have66noF2noF3( pfx ) 
14642         && sz == 2 
14643         && insn[0] == 0x0F && insn[1] == 0x38 && insn[2] == 0x32 ) {
14644
14645       modrm = insn[3];
14646
14647       IRTemp srcVec = newTemp(Ity_V128);
14648
14649       if ( epartIsReg(modrm) ) {
14650          assign( srcVec, getXMMReg( eregOfRexRM(pfx, modrm) ) );
14651          delta += 3+1;
14652          DIP( "pmovzxbq %s,%s\n",
14653               nameXMMReg( eregOfRexRM(pfx, modrm) ),
14654               nameXMMReg( gregOfRexRM(pfx, modrm) ) );
14655       } else {
14656          addr = disAMode( &alen, vbi, pfx, delta+3, dis_buf, 0 );
14657          assign( srcVec, 
14658                  unop( Iop_32UtoV128, 
14659                        unop( Iop_16Uto32, loadLE( Ity_I16, mkexpr(addr) ) ) ) );
14660          delta += 3+alen;
14661          DIP( "pmovzxbq %s,%s\n",
14662               dis_buf, nameXMMReg( gregOfRexRM(pfx, modrm) ) );
14663       }
14664
14665       IRTemp zeroVec = newTemp(Ity_V128);
14666       assign( zeroVec, IRExpr_Const( IRConst_V128(0) ) );
14667
14668       putXMMReg( gregOfRexRM( pfx, modrm ), 
14669                  binop( Iop_InterleaveLO8x16, 
14670                         mkexpr(zeroVec), 
14671                         binop( Iop_InterleaveLO8x16, 
14672                                mkexpr(zeroVec), 
14673                                binop( Iop_InterleaveLO8x16, 
14674                                       mkexpr(zeroVec), mkexpr(srcVec) ) ) ) );
14675
14676       goto decode_success;
14677    }
14678
14679
14680    /* 66 0f 38 33 /r = PMOVZXWD xmm1, xmm2/m64 
14681       Packed Move with Zero Extend from Word to DWord (XMM) */
14682    if ( have66noF2noF3( pfx ) 
14683         && sz == 2 
14684         && insn[0] == 0x0F && insn[1] == 0x38 && insn[2] == 0x33 ) {
14685   
14686       modrm = insn[3];
14687
14688       IRTemp srcVec = newTemp(Ity_V128);
14689
14690       if ( epartIsReg(modrm) ) {
14691          assign( srcVec, getXMMReg( eregOfRexRM(pfx, modrm) ) );
14692          delta += 3+1;
14693          DIP( "pmovzxwd %s,%s\n", 
14694               nameXMMReg( eregOfRexRM(pfx, modrm) ),
14695               nameXMMReg( gregOfRexRM(pfx, modrm) ) );
14696       } else {
14697          addr = disAMode( &alen, vbi, pfx, delta+3, dis_buf, 0 );
14698          assign( srcVec, 
14699                  unop( Iop_64UtoV128, loadLE( Ity_I64, mkexpr(addr) ) ) );
14700          delta += 3+alen;
14701          DIP( "pmovzxwd %s,%s\n",
14702               dis_buf, nameXMMReg( gregOfRexRM(pfx, modrm) ) );
14703       }
14704
14705       putXMMReg( gregOfRexRM(pfx, modrm), 
14706                  binop( Iop_InterleaveLO16x8,  
14707                         IRExpr_Const( IRConst_V128(0) ),
14708                         mkexpr(srcVec) ) );
14709
14710       goto decode_success;
14711    }
14712
14713
14714    /* 66 0f 38 34 /r = PMOVZXWQ xmm1, xmm2/m32
14715       Packed Move with Zero Extend from Word to QWord (XMM) */
14716    if ( have66noF2noF3( pfx ) 
14717         && sz == 2 
14718         && insn[0] == 0x0F && insn[1] == 0x38 && insn[2] == 0x34 ) {
14719   
14720       modrm = insn[3];
14721
14722       IRTemp srcVec = newTemp(Ity_V128);
14723
14724       if ( epartIsReg( modrm ) ) {
14725          assign( srcVec, getXMMReg( eregOfRexRM(pfx, modrm) ) );
14726          delta += 3+1;
14727          DIP( "pmovzxwq %s,%s\n", 
14728               nameXMMReg( eregOfRexRM(pfx, modrm) ),
14729               nameXMMReg( gregOfRexRM(pfx, modrm) ) );
14730       } else {
14731          addr = disAMode( &alen, vbi, pfx, delta+3, dis_buf, 0 );
14732          assign( srcVec, 
14733                  unop( Iop_32UtoV128, loadLE( Ity_I32, mkexpr(addr) ) ) );
14734          delta += 3+alen;
14735          DIP( "pmovzxwq %s,%s\n",
14736               dis_buf, nameXMMReg( gregOfRexRM(pfx, modrm) ) );
14737       }
14738
14739       IRTemp zeroVec = newTemp( Ity_V128 );
14740       assign( zeroVec, IRExpr_Const( IRConst_V128(0) ) );
14741
14742       putXMMReg( gregOfRexRM( pfx, modrm ),
14743                  binop( Iop_InterleaveLO16x8, 
14744                         mkexpr(zeroVec), 
14745                         binop( Iop_InterleaveLO16x8, 
14746                                mkexpr(zeroVec), mkexpr(srcVec) ) ) );
14747
14748       goto decode_success;
14749    }
14750
14751
14752    /* 66 0f 38 35 /r = PMOVZXDQ xmm1, xmm2/m64
14753       Packed Move with Zero Extend from DWord to QWord (XMM) */
14754    if ( have66noF2noF3( pfx ) 
14755         && sz == 2 
14756         && insn[0] == 0x0F && insn[1] == 0x38 && insn[2] == 0x35 ) {
14757   
14758       modrm = insn[3];
14759
14760       IRTemp srcVec = newTemp(Ity_V128);
14761
14762       if ( epartIsReg(modrm) ) {
14763          assign( srcVec, getXMMReg( eregOfRexRM(pfx, modrm) ) );
14764          delta += 3+1;
14765          DIP( "pmovzxdq %s,%s\n", 
14766               nameXMMReg( eregOfRexRM(pfx, modrm) ),
14767               nameXMMReg( gregOfRexRM(pfx, modrm) ) );
14768       } else {
14769          addr = disAMode( &alen, vbi, pfx, delta+3, dis_buf, 0 );
14770          assign( srcVec, 
14771                  unop( Iop_64UtoV128, loadLE( Ity_I64, mkexpr(addr) ) ) );
14772          delta += 3+alen;
14773          DIP( "pmovzxdq %s,%s\n",
14774               dis_buf, nameXMMReg( gregOfRexRM(pfx, modrm) ) );
14775       }
14776
14777       putXMMReg( gregOfRexRM(pfx, modrm), 
14778                  binop( Iop_InterleaveLO32x4, 
14779                         IRExpr_Const( IRConst_V128(0) ), 
14780                         mkexpr(srcVec) ) );
14781
14782       goto decode_success;
14783    }
14784
14785
14786    /* ---------------------------------------------------- */
14787    /* --- end of the SSE4 decoder                      --- */
14788    /* ---------------------------------------------------- */
14789
14790    /*after_sse_decoders:*/
14791
14792    /* Get the primary opcode. */
14793    opc = getUChar(delta); delta++;
14794
14795    /* We get here if the current insn isn't SSE, or this CPU doesn't
14796       support SSE. */
14797
14798    switch (opc) {
14799
14800    /* ------------------------ Control flow --------------- */
14801
14802    case 0xC2: /* RET imm16 */
14803       if (have66orF2orF3(pfx)) goto decode_failure;
14804       d64 = getUDisp16(delta); 
14805       delta += 2;
14806       dis_ret(vbi, d64);
14807       dres.whatNext = Dis_StopHere;
14808       DIP("ret %lld\n", d64);
14809       break;
14810
14811    case 0xC3: /* RET */
14812       if (have66orF2(pfx)) goto decode_failure;
14813       /* F3 is acceptable on AMD. */
14814       dis_ret(vbi, 0);
14815       dres.whatNext = Dis_StopHere;
14816       DIP(haveF3(pfx) ? "rep ; ret\n" : "ret\n");
14817       break;
14818       
14819    case 0xE8: /* CALL J4 */
14820       if (haveF2orF3(pfx)) goto decode_failure;
14821       d64 = getSDisp32(delta); delta += 4;
14822       d64 += (guest_RIP_bbstart+delta); 
14823       /* (guest_RIP_bbstart+delta) == return-to addr, d64 == call-to addr */
14824       t1 = newTemp(Ity_I64); 
14825       assign(t1, binop(Iop_Sub64, getIReg64(R_RSP), mkU64(8)));
14826       putIReg64(R_RSP, mkexpr(t1));
14827       storeLE( mkexpr(t1), mkU64(guest_RIP_bbstart+delta));
14828       t2 = newTemp(Ity_I64);
14829       assign(t2, mkU64((Addr64)d64));
14830       make_redzone_AbiHint(vbi, t1, t2/*nia*/, "call-d32");
14831       if (resteerOkFn( callback_opaque, (Addr64)d64) ) {
14832          /* follow into the call target. */
14833          dres.whatNext   = Dis_ResteerU;
14834          dres.continueAt = d64;
14835       } else {
14836          jmp_lit(Ijk_Call,d64);
14837          dres.whatNext = Dis_StopHere;
14838       }
14839       DIP("call 0x%llx\n",d64);
14840       break;
14841
14842 //.. //--    case 0xC8: /* ENTER */ 
14843 //.. //--       d32 = getUDisp16(eip); eip += 2;
14844 //.. //--       abyte = getUChar(delta); delta++;
14845 //.. //-- 
14846 //.. //--       vg_assert(sz == 4);           
14847 //.. //--       vg_assert(abyte == 0);
14848 //.. //-- 
14849 //.. //--       t1 = newTemp(cb); t2 = newTemp(cb);
14850 //.. //--       uInstr2(cb, GET,   sz, ArchReg, R_EBP, TempReg, t1);
14851 //.. //--       uInstr2(cb, GET,    4, ArchReg, R_ESP, TempReg, t2);
14852 //.. //--       uInstr2(cb, SUB,    4, Literal, 0,     TempReg, t2);
14853 //.. //--       uLiteral(cb, sz);
14854 //.. //--       uInstr2(cb, PUT,    4, TempReg, t2,    ArchReg, R_ESP);
14855 //.. //--       uInstr2(cb, STORE,  4, TempReg, t1,    TempReg, t2);
14856 //.. //--       uInstr2(cb, PUT,    4, TempReg, t2,    ArchReg, R_EBP);
14857 //.. //--       if (d32) {
14858 //.. //--          uInstr2(cb, SUB,    4, Literal, 0,     TempReg, t2);
14859 //.. //--          uLiteral(cb, d32);
14860 //.. //--          uInstr2(cb, PUT,    4, TempReg, t2,    ArchReg, R_ESP);
14861 //.. //--       }
14862 //.. //--       DIP("enter 0x%x, 0x%x", d32, abyte);
14863 //.. //--       break;
14864
14865    case 0xC9: /* LEAVE */
14866       /* In 64-bit mode this defaults to a 64-bit operand size.  There
14867          is no way to encode a 32-bit variant.  Hence sz==4 but we do
14868          it as if sz=8. */
14869       if (sz != 4) 
14870          goto decode_failure;
14871       t1 = newTemp(Ity_I64); 
14872       t2 = newTemp(Ity_I64);
14873       assign(t1, getIReg64(R_RBP));
14874       /* First PUT RSP looks redundant, but need it because RSP must
14875          always be up-to-date for Memcheck to work... */
14876       putIReg64(R_RSP, mkexpr(t1));
14877       assign(t2, loadLE(Ity_I64,mkexpr(t1)));
14878       putIReg64(R_RBP, mkexpr(t2));
14879       putIReg64(R_RSP, binop(Iop_Add64, mkexpr(t1), mkU64(8)) );
14880       DIP("leave\n");
14881       break;
14882
14883 //.. //--    /* ---------------- Misc weird-ass insns --------------- */
14884 //.. //-- 
14885 //.. //--    case 0x27: /* DAA */
14886 //.. //--    case 0x2F: /* DAS */
14887 //.. //--       t1 = newTemp(cb);
14888 //.. //--       uInstr2(cb, GET, 1, ArchReg, R_AL, TempReg, t1);
14889 //.. //--       /* Widen %AL to 32 bits, so it's all defined when we push it. */
14890 //.. //--       uInstr1(cb, WIDEN, 4, TempReg, t1);
14891 //.. //--       uWiden(cb, 1, False);
14892 //.. //--       uInstr0(cb, CALLM_S, 0);
14893 //.. //--       uInstr1(cb, PUSH, 4, TempReg, t1);
14894 //.. //--       uInstr1(cb, CALLM, 0, Lit16, 
14895 //.. //--                   opc == 0x27 ? VGOFF_(helper_DAA) : VGOFF_(helper_DAS) );
14896 //.. //--       uFlagsRWU(cb, FlagsAC, FlagsSZACP, FlagO);
14897 //.. //--       uInstr1(cb, POP, 4, TempReg, t1);
14898 //.. //--       uInstr0(cb, CALLM_E, 0);
14899 //.. //--       uInstr2(cb, PUT, 1, TempReg, t1, ArchReg, R_AL);
14900 //.. //--       DIP(opc == 0x27 ? "daa\n" : "das\n");
14901 //.. //--       break;
14902 //.. //-- 
14903 //.. //--    case 0x37: /* AAA */
14904 //.. //--    case 0x3F: /* AAS */
14905 //.. //--       t1 = newTemp(cb);
14906 //.. //--       uInstr2(cb, GET, 2, ArchReg, R_EAX, TempReg, t1);
14907 //.. //--       /* Widen %AL to 32 bits, so it's all defined when we push it. */
14908 //.. //--       uInstr1(cb, WIDEN, 4, TempReg, t1);
14909 //.. //--       uWiden(cb, 2, False);
14910 //.. //--       uInstr0(cb, CALLM_S, 0);
14911 //.. //--       uInstr1(cb, PUSH, 4, TempReg, t1);
14912 //.. //--       uInstr1(cb, CALLM, 0, Lit16, 
14913 //.. //--                   opc == 0x37 ? VGOFF_(helper_AAA) : VGOFF_(helper_AAS) );
14914 //.. //--       uFlagsRWU(cb, FlagA, FlagsAC, FlagsEmpty);
14915 //.. //--       uInstr1(cb, POP, 4, TempReg, t1);
14916 //.. //--       uInstr0(cb, CALLM_E, 0);
14917 //.. //--       uInstr2(cb, PUT, 2, TempReg, t1, ArchReg, R_EAX);
14918 //.. //--       DIP(opc == 0x37 ? "aaa\n" : "aas\n");
14919 //.. //--       break;
14920 //.. //-- 
14921 //.. //--    case 0xD4: /* AAM */
14922 //.. //--    case 0xD5: /* AAD */
14923 //.. //--       d32 = getUChar(delta); delta++;
14924 //.. //--       if (d32 != 10) VG_(core_panic)("disInstr: AAM/AAD but base not 10 !");
14925 //.. //--       t1 = newTemp(cb);
14926 //.. //--       uInstr2(cb, GET, 2, ArchReg, R_EAX, TempReg, t1);
14927 //.. //--       /* Widen %AX to 32 bits, so it's all defined when we push it. */
14928 //.. //--       uInstr1(cb, WIDEN, 4, TempReg, t1);
14929 //.. //--       uWiden(cb, 2, False);
14930 //.. //--       uInstr0(cb, CALLM_S, 0);
14931 //.. //--       uInstr1(cb, PUSH, 4, TempReg, t1);
14932 //.. //--       uInstr1(cb, CALLM, 0, Lit16, 
14933 //.. //--                   opc == 0xD4 ? VGOFF_(helper_AAM) : VGOFF_(helper_AAD) );
14934 //.. //--       uFlagsRWU(cb, FlagsEmpty, FlagsSZP, FlagsEmpty);
14935 //.. //--       uInstr1(cb, POP, 4, TempReg, t1);
14936 //.. //--       uInstr0(cb, CALLM_E, 0);
14937 //.. //--       uInstr2(cb, PUT, 2, TempReg, t1, ArchReg, R_EAX);
14938 //.. //--       DIP(opc == 0xD4 ? "aam\n" : "aad\n");
14939 //.. //--       break;
14940
14941    /* ------------------------ CWD/CDQ -------------------- */
14942
14943    case 0x98: /* CBW */
14944       if (haveF2orF3(pfx)) goto decode_failure;
14945       if (sz == 8) {
14946          putIRegRAX( 8, unop(Iop_32Sto64, getIRegRAX(4)) );
14947          DIP(/*"cdqe\n"*/"cltq");
14948          break;
14949       }
14950       if (sz == 4) {
14951          putIRegRAX( 4, unop(Iop_16Sto32, getIRegRAX(2)) );
14952          DIP("cwtl\n");
14953          break;
14954       }
14955       if (sz == 2) {
14956          putIRegRAX( 2, unop(Iop_8Sto16, getIRegRAX(1)) );
14957          DIP("cbw\n");
14958          break;
14959       }
14960       goto decode_failure;
14961
14962    case 0x99: /* CWD/CDQ/CQO */
14963       if (haveF2orF3(pfx)) goto decode_failure;
14964       vassert(sz == 2 || sz == 4 || sz == 8);
14965       ty = szToITy(sz);
14966       putIRegRDX( sz, 
14967                   binop(mkSizedOp(ty,Iop_Sar8), 
14968                         getIRegRAX(sz),
14969                         mkU8(sz == 2 ? 15 : (sz == 4 ? 31 : 63))) );
14970       DIP(sz == 2 ? "cwd\n" 
14971                   : (sz == 4 ? /*"cdq\n"*/ "cltd\n" 
14972                              : "cqo\n"));
14973       break;
14974
14975    /* ------------------------ FPU ops -------------------- */
14976
14977    case 0x9E: /* SAHF */
14978       codegen_SAHF();
14979       DIP("sahf\n");
14980       break;
14981
14982    case 0x9F: /* LAHF */
14983       codegen_LAHF();
14984       DIP("lahf\n");
14985       break;
14986
14987    case 0x9B: /* FWAIT */
14988       /* ignore? */
14989       DIP("fwait\n");
14990       break;
14991
14992    case 0xD8:
14993    case 0xD9:
14994    case 0xDA:
14995    case 0xDB:
14996    case 0xDC:
14997    case 0xDD:
14998    case 0xDE:
14999    case 0xDF: {
15000       Bool redundantREXWok = False;
15001
15002       if (haveF2orF3(pfx)) 
15003          goto decode_failure;
15004
15005       /* kludge to tolerate redundant rex.w prefixes (should do this
15006          properly one day) */
15007       /* mono 1.1.18.1 produces 48 D9 FA, which is rex.w fsqrt */
15008       if ( (opc == 0xD9 && getUChar(delta+0) == 0xFA)/*fsqrt*/ )
15009          redundantREXWok = True;
15010
15011       if ( (sz == 4
15012            || (sz == 8 && redundantREXWok))
15013            && haveNo66noF2noF3(pfx)) {
15014          Long delta0    = delta;
15015          Bool decode_OK = False;
15016          delta = dis_FPU ( &decode_OK, vbi, pfx, delta );
15017          if (!decode_OK) {
15018             delta = delta0;
15019             goto decode_failure;
15020          }
15021          break;
15022       } else {
15023          goto decode_failure;
15024       }
15025    }
15026
15027    /* ------------------------ INT ------------------------ */
15028
15029    case 0xCC: /* INT 3 */
15030       jmp_lit(Ijk_SigTRAP, guest_RIP_bbstart + delta);
15031       dres.whatNext = Dis_StopHere;
15032       DIP("int $0x3\n");
15033       break;
15034
15035    case 0xCD: { /* INT imm8 */
15036       IRJumpKind jk = Ijk_Boring;
15037       if (have66orF2orF3(pfx)) goto decode_failure;
15038       d64 = getUChar(delta); delta++;
15039       switch (d64) {
15040          case 32: jk = Ijk_Sys_int32; break;
15041          default: goto decode_failure;
15042       }
15043       guest_RIP_next_mustcheck = True;
15044       guest_RIP_next_assumed = guest_RIP_bbstart + delta;
15045       jmp_lit(jk, guest_RIP_next_assumed);
15046       /* It's important that all ArchRegs carry their up-to-date value
15047          at this point.  So we declare an end-of-block here, which
15048          forces any TempRegs caching ArchRegs to be flushed. */
15049       dres.whatNext = Dis_StopHere;
15050       DIP("int $0x%02x\n", (UInt)d64);
15051       break;
15052    }
15053
15054    /* ------------------------ Jcond, byte offset --------- */
15055
15056    case 0xEB: /* Jb (jump, byte offset) */
15057       if (haveF2orF3(pfx)) goto decode_failure;
15058       if (sz != 4) 
15059          goto decode_failure; /* JRS added 2004 July 11 */
15060       d64 = (guest_RIP_bbstart+delta+1) + getSDisp8(delta); 
15061       delta++;
15062       if (resteerOkFn(callback_opaque,d64)) {
15063          dres.whatNext   = Dis_ResteerU;
15064          dres.continueAt = d64;
15065       } else {
15066          jmp_lit(Ijk_Boring,d64);
15067          dres.whatNext = Dis_StopHere;
15068       }
15069       DIP("jmp-8 0x%llx\n", d64);
15070       break;
15071
15072    case 0xE9: /* Jv (jump, 16/32 offset) */
15073       if (haveF2orF3(pfx)) goto decode_failure;
15074       if (sz != 4) 
15075          goto decode_failure; /* JRS added 2004 July 11 */
15076       d64 = (guest_RIP_bbstart+delta+sz) + getSDisp(sz,delta); 
15077       delta += sz;
15078       if (resteerOkFn(callback_opaque,d64)) {
15079          dres.whatNext   = Dis_ResteerU;
15080          dres.continueAt = d64;
15081       } else {
15082          jmp_lit(Ijk_Boring,d64);
15083          dres.whatNext = Dis_StopHere;
15084       }
15085       DIP("jmp 0x%llx\n", d64);
15086       break;
15087
15088    case 0x70:
15089    case 0x71:
15090    case 0x72: /* JBb/JNAEb (jump below) */
15091    case 0x73: /* JNBb/JAEb (jump not below) */
15092    case 0x74: /* JZb/JEb (jump zero) */
15093    case 0x75: /* JNZb/JNEb (jump not zero) */
15094    case 0x76: /* JBEb/JNAb (jump below or equal) */
15095    case 0x77: /* JNBEb/JAb (jump not below or equal) */
15096    case 0x78: /* JSb (jump negative) */
15097    case 0x79: /* JSb (jump not negative) */
15098    case 0x7A: /* JP (jump parity even) */
15099    case 0x7B: /* JNP/JPO (jump parity odd) */
15100    case 0x7C: /* JLb/JNGEb (jump less) */
15101    case 0x7D: /* JGEb/JNLb (jump greater or equal) */
15102    case 0x7E: /* JLEb/JNGb (jump less or equal) */
15103    case 0x7F: /* JGb/JNLEb (jump greater) */
15104     { Long   jmpDelta;
15105       HChar* comment  = "";
15106       if (haveF2orF3(pfx)) goto decode_failure;
15107       jmpDelta = getSDisp8(delta);
15108       vassert(-128 <= jmpDelta && jmpDelta < 128);
15109       d64 = (guest_RIP_bbstart+delta+1) + jmpDelta;
15110       delta++;
15111       if (resteerCisOk
15112           && vex_control.guest_chase_cond
15113           && (Addr64)d64 != (Addr64)guest_RIP_bbstart
15114           && jmpDelta < 0
15115           && resteerOkFn( callback_opaque, d64) ) {
15116          /* Speculation: assume this backward branch is taken.  So we
15117             need to emit a side-exit to the insn following this one,
15118             on the negation of the condition, and continue at the
15119             branch target address (d64).  If we wind up back at the
15120             first instruction of the trace, just stop; it's better to
15121             let the IR loop unroller handle that case. */
15122          stmt( IRStmt_Exit( 
15123                   mk_amd64g_calculate_condition(
15124                      (AMD64Condcode)(1 ^ (opc - 0x70))),
15125                   Ijk_Boring,
15126                   IRConst_U64(guest_RIP_bbstart+delta) ) );
15127          dres.whatNext   = Dis_ResteerC;
15128          dres.continueAt = d64;
15129          comment = "(assumed taken)";
15130       }
15131       else
15132       if (resteerCisOk
15133           && vex_control.guest_chase_cond
15134           && (Addr64)d64 != (Addr64)guest_RIP_bbstart
15135           && jmpDelta >= 0
15136           && resteerOkFn( callback_opaque, guest_RIP_bbstart+delta ) ) {
15137          /* Speculation: assume this forward branch is not taken.  So
15138             we need to emit a side-exit to d64 (the dest) and continue
15139             disassembling at the insn immediately following this
15140             one. */
15141          stmt( IRStmt_Exit( 
15142                   mk_amd64g_calculate_condition((AMD64Condcode)(opc - 0x70)),
15143                   Ijk_Boring,
15144                   IRConst_U64(d64) ) );
15145          dres.whatNext   = Dis_ResteerC;
15146          dres.continueAt = guest_RIP_bbstart+delta;
15147          comment = "(assumed not taken)";
15148       }
15149       else {
15150          /* Conservative default translation - end the block at this
15151             point. */
15152       jcc_01( (AMD64Condcode)(opc - 0x70), 
15153               guest_RIP_bbstart+delta,
15154               d64 );
15155       dres.whatNext = Dis_StopHere;
15156       }
15157       DIP("j%s-8 0x%llx %s\n", name_AMD64Condcode(opc - 0x70), d64, comment);
15158       break;
15159     }
15160
15161    case 0xE3: 
15162       /* JRCXZ or JECXZ, depending address size override. */
15163       if (have66orF2orF3(pfx)) goto decode_failure;
15164       d64 = (guest_RIP_bbstart+delta+1) + getSDisp8(delta); 
15165       delta++;
15166       if (haveASO(pfx)) {
15167          /* 32-bit */
15168          stmt( IRStmt_Exit( binop(Iop_CmpEQ64, 
15169                             unop(Iop_32Uto64, getIReg32(R_RCX)), 
15170                             mkU64(0)),
15171                Ijk_Boring,
15172                IRConst_U64(d64)) 
15173              );
15174          DIP("jecxz 0x%llx\n", d64);
15175       } else {
15176          /* 64-bit */
15177          stmt( IRStmt_Exit( binop(Iop_CmpEQ64, 
15178                                   getIReg64(R_RCX), 
15179                                   mkU64(0)),
15180                Ijk_Boring,
15181                IRConst_U64(d64)) 
15182              );
15183          DIP("jrcxz 0x%llx\n", d64);
15184       }
15185       break;
15186
15187    case 0xE0: /* LOOPNE disp8: decrement count, jump if count != 0 && ZF==0 */
15188    case 0xE1: /* LOOPE  disp8: decrement count, jump if count != 0 && ZF==1 */
15189    case 0xE2: /* LOOP   disp8: decrement count, jump if count != 0 */
15190     { /* The docs say this uses rCX as a count depending on the
15191          address size override, not the operand one.  Since we don't
15192          handle address size overrides, I guess that means RCX. */
15193       IRExpr* zbit  = NULL;
15194       IRExpr* count = NULL;
15195       IRExpr* cond  = NULL;
15196       HChar*  xtra  = NULL;
15197
15198       if (have66orF2orF3(pfx) || haveASO(pfx)) goto decode_failure;
15199       d64 = guest_RIP_bbstart+delta+1 + getSDisp8(delta);
15200       delta++;
15201       putIReg64(R_RCX, binop(Iop_Sub64, getIReg64(R_RCX), mkU64(1)));
15202
15203       count = getIReg64(R_RCX);
15204       cond = binop(Iop_CmpNE64, count, mkU64(0));
15205       switch (opc) {
15206          case 0xE2: 
15207             xtra = ""; 
15208             break;
15209          case 0xE1: 
15210             xtra = "e"; 
15211             zbit = mk_amd64g_calculate_condition( AMD64CondZ );
15212       cond = mkAnd1(cond, zbit);
15213             break;
15214          case 0xE0: 
15215             xtra = "ne";
15216             zbit = mk_amd64g_calculate_condition( AMD64CondNZ );
15217       cond = mkAnd1(cond, zbit);
15218             break;
15219          default:
15220             vassert(0);
15221       }
15222       stmt( IRStmt_Exit(cond, Ijk_Boring, IRConst_U64(d64)) );
15223
15224       DIP("loop%s 0x%llx\n", xtra, d64);
15225       break;
15226     }
15227
15228    /* ------------------------ IMUL ----------------------- */
15229
15230    case 0x69: /* IMUL Iv, Ev, Gv */
15231       if (haveF2orF3(pfx)) goto decode_failure;
15232       delta = dis_imul_I_E_G ( vbi, pfx, sz, delta, sz );
15233       break;
15234    case 0x6B: /* IMUL Ib, Ev, Gv */
15235       delta = dis_imul_I_E_G ( vbi, pfx, sz, delta, 1 );
15236       break;
15237
15238    /* ------------------------ MOV ------------------------ */
15239
15240    case 0x88: /* MOV Gb,Eb */
15241       if (haveF2orF3(pfx)) goto decode_failure;
15242       delta = dis_mov_G_E(vbi, pfx, 1, delta);
15243       break;
15244
15245    case 0x89: /* MOV Gv,Ev */
15246       if (haveF2orF3(pfx)) goto decode_failure;
15247       delta = dis_mov_G_E(vbi, pfx, sz, delta);
15248       break;
15249
15250    case 0x8A: /* MOV Eb,Gb */
15251       if (haveF2orF3(pfx)) goto decode_failure;
15252       delta = dis_mov_E_G(vbi, pfx, 1, delta);
15253       break;
15254  
15255    case 0x8B: /* MOV Ev,Gv */
15256       if (haveF2orF3(pfx)) goto decode_failure;
15257       delta = dis_mov_E_G(vbi, pfx, sz, delta);
15258       break;
15259  
15260    case 0x8D: /* LEA M,Gv */
15261       if (haveF2orF3(pfx)) goto decode_failure;
15262       if (sz != 4 && sz != 8)
15263          goto decode_failure;
15264       modrm = getUChar(delta);
15265       if (epartIsReg(modrm)) 
15266          goto decode_failure;
15267       /* NOTE!  this is the one place where a segment override prefix
15268          has no effect on the address calculation.  Therefore we clear
15269          any segment override bits in pfx. */
15270       addr = disAMode ( &alen, vbi, clearSegBits(pfx), delta, dis_buf, 0 );
15271       delta += alen;
15272       /* This is a hack.  But it isn't clear that really doing the
15273          calculation at 32 bits is really worth it.  Hence for leal,
15274          do the full 64-bit calculation and then truncate it. */
15275       putIRegG( sz, pfx, modrm, 
15276                          sz == 4
15277                             ? unop(Iop_64to32, mkexpr(addr))
15278                             : mkexpr(addr)
15279               );
15280       DIP("lea%c %s, %s\n", nameISize(sz), dis_buf, 
15281                             nameIRegG(sz,pfx,modrm));
15282       break;
15283
15284 //..    case 0x8C: /* MOV Sw,Ew -- MOV from a SEGMENT REGISTER */
15285 //..       delta = dis_mov_Sw_Ew(sorb, sz, delta);
15286 //..       break;
15287 //.. 
15288 //..    case 0x8E: /* MOV Ew,Sw -- MOV to a SEGMENT REGISTER */
15289 //..       delta = dis_mov_Ew_Sw(sorb, delta);
15290 //..       break;
15291  
15292    case 0xA0: /* MOV Ob,AL */
15293       if (have66orF2orF3(pfx)) goto decode_failure;
15294       sz = 1;
15295       /* Fall through ... */
15296    case 0xA1: /* MOV Ov,eAX */
15297       if (sz != 8 && sz != 4 && sz != 2 && sz != 1) 
15298          goto decode_failure;
15299       d64 = getDisp64(delta); 
15300       delta += 8;
15301       ty = szToITy(sz);
15302       addr = newTemp(Ity_I64);
15303       assign( addr, handleAddrOverrides(vbi, pfx, mkU64(d64)) );
15304       putIRegRAX(sz, loadLE( ty, mkexpr(addr) ));
15305       DIP("mov%c %s0x%llx, %s\n", nameISize(sz), 
15306                                   segRegTxt(pfx), d64,
15307                                   nameIRegRAX(sz));
15308       break;
15309
15310    case 0xA2: /* MOV AL,Ob */
15311       if (have66orF2orF3(pfx)) goto decode_failure;
15312       sz = 1;
15313       /* Fall through ... */
15314    case 0xA3: /* MOV eAX,Ov */
15315       if (sz != 8 && sz != 4 && sz != 2 && sz != 1) 
15316          goto decode_failure;
15317       d64 = getDisp64(delta); 
15318       delta += 8;
15319       ty = szToITy(sz);
15320       addr = newTemp(Ity_I64);
15321       assign( addr, handleAddrOverrides(vbi, pfx, mkU64(d64)) );
15322       storeLE( mkexpr(addr), getIRegRAX(sz) );
15323       DIP("mov%c %s, %s0x%llx\n", nameISize(sz), nameIRegRAX(sz),
15324                                   segRegTxt(pfx), d64);
15325       break;
15326
15327    /* XXXX be careful here with moves to AH/BH/CH/DH */
15328    case 0xB0: /* MOV imm,AL */
15329    case 0xB1: /* MOV imm,CL */
15330    case 0xB2: /* MOV imm,DL */
15331    case 0xB3: /* MOV imm,BL */
15332    case 0xB4: /* MOV imm,AH */
15333    case 0xB5: /* MOV imm,CH */
15334    case 0xB6: /* MOV imm,DH */
15335    case 0xB7: /* MOV imm,BH */
15336       if (haveF2orF3(pfx)) goto decode_failure;
15337       d64 = getUChar(delta); 
15338       delta += 1;
15339       putIRegRexB(1, pfx, opc-0xB0, mkU8(d64));
15340       DIP("movb $%lld,%s\n", d64, nameIRegRexB(1,pfx,opc-0xB0));
15341       break;
15342
15343    case 0xB8: /* MOV imm,eAX */
15344    case 0xB9: /* MOV imm,eCX */
15345    case 0xBA: /* MOV imm,eDX */
15346    case 0xBB: /* MOV imm,eBX */
15347    case 0xBC: /* MOV imm,eSP */
15348    case 0xBD: /* MOV imm,eBP */
15349    case 0xBE: /* MOV imm,eSI */
15350    case 0xBF: /* MOV imm,eDI */
15351       /* This is the one-and-only place where 64-bit literals are
15352          allowed in the instruction stream. */
15353       if (haveF2orF3(pfx)) goto decode_failure;
15354       if (sz == 8) {
15355          d64 = getDisp64(delta);
15356          delta += 8;
15357          putIRegRexB(8, pfx, opc-0xB8, mkU64(d64));
15358          DIP("movabsq $%lld,%s\n", (Long)d64, 
15359                                    nameIRegRexB(8,pfx,opc-0xB8));
15360       } else {
15361          d64 = getSDisp(imin(4,sz),delta);
15362          delta += imin(4,sz);
15363          putIRegRexB(sz, pfx, opc-0xB8, 
15364                          mkU(szToITy(sz), d64 & mkSizeMask(sz)));
15365          DIP("mov%c $%lld,%s\n", nameISize(sz), 
15366                                  (Long)d64, 
15367                                  nameIRegRexB(sz,pfx,opc-0xB8));
15368       }
15369       break;
15370
15371    case 0xC6: /* MOV Ib,Eb */
15372       sz = 1;
15373       goto do_Mov_I_E;
15374    case 0xC7: /* MOV Iv,Ev */
15375       goto do_Mov_I_E;
15376
15377    do_Mov_I_E:
15378       if (haveF2orF3(pfx)) goto decode_failure;
15379       modrm = getUChar(delta);
15380       if (epartIsReg(modrm)) {
15381          delta++; /* mod/rm byte */
15382          d64 = getSDisp(imin(4,sz),delta); 
15383          delta += imin(4,sz);
15384          putIRegE(sz, pfx, modrm, 
15385                       mkU(szToITy(sz), d64 & mkSizeMask(sz)));
15386          DIP("mov%c $%lld, %s\n", nameISize(sz), 
15387                                   (Long)d64, 
15388                                   nameIRegE(sz,pfx,modrm));
15389       } else {
15390          addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 
15391                            /*xtra*/imin(4,sz) );
15392          delta += alen;
15393          d64 = getSDisp(imin(4,sz),delta);
15394          delta += imin(4,sz);
15395          storeLE(mkexpr(addr), 
15396                  mkU(szToITy(sz), d64 & mkSizeMask(sz)));
15397          DIP("mov%c $%lld, %s\n", nameISize(sz), (Long)d64, dis_buf);
15398       }
15399       break;
15400
15401    /* ------------------------ MOVx ------------------------ */
15402
15403    case 0x63: /* MOVSX */
15404       if (haveF2orF3(pfx)) goto decode_failure;
15405       if (haveREX(pfx) && 1==getRexW(pfx)) {
15406          vassert(sz == 8);
15407          /* movsx r/m32 to r64 */
15408          modrm = getUChar(delta);
15409          if (epartIsReg(modrm)) {
15410             delta++;
15411             putIRegG(8, pfx, modrm, 
15412                              unop(Iop_32Sto64, 
15413                                   getIRegE(4, pfx, modrm)));
15414             DIP("movslq %s,%s\n",
15415                 nameIRegE(4, pfx, modrm),
15416                 nameIRegG(8, pfx, modrm));
15417             break;
15418          } else {
15419             addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
15420             delta += alen;
15421             putIRegG(8, pfx, modrm, 
15422                              unop(Iop_32Sto64, 
15423                                   loadLE(Ity_I32, mkexpr(addr))));
15424             DIP("movslq %s,%s\n", dis_buf, 
15425                 nameIRegG(8, pfx, modrm));
15426             break;
15427          }
15428       } else {
15429          goto decode_failure;
15430       }
15431
15432    /* ------------------------ opl imm, A ----------------- */
15433
15434    case 0x04: /* ADD Ib, AL */
15435       if (haveF2orF3(pfx)) goto decode_failure;
15436       delta = dis_op_imm_A( 1, False, Iop_Add8, True, delta, "add" );
15437       break;
15438    case 0x05: /* ADD Iv, eAX */
15439       if (haveF2orF3(pfx)) goto decode_failure;
15440       delta = dis_op_imm_A(sz, False, Iop_Add8, True, delta, "add" );
15441       break;
15442
15443    case 0x0C: /* OR Ib, AL */
15444       if (haveF2orF3(pfx)) goto decode_failure;
15445       delta = dis_op_imm_A( 1, False, Iop_Or8, True, delta, "or" );
15446       break;
15447    case 0x0D: /* OR Iv, eAX */
15448       if (haveF2orF3(pfx)) goto decode_failure;
15449       delta = dis_op_imm_A( sz, False, Iop_Or8, True, delta, "or" );
15450       break;
15451
15452    case 0x14: /* ADC Ib, AL */
15453       if (haveF2orF3(pfx)) goto decode_failure;
15454       delta = dis_op_imm_A( 1, True, Iop_Add8, True, delta, "adc" );
15455       break;
15456 //.. //--    case 0x15: /* ADC Iv, eAX */
15457 //.. //--       delta = dis_op_imm_A( sz, ADC, True, delta, "adc" );
15458 //.. //--       break;
15459
15460    case 0x1C: /* SBB Ib, AL */
15461       if (haveF2orF3(pfx)) goto decode_failure;
15462       delta = dis_op_imm_A( 1, True, Iop_Sub8, True, delta, "sbb" );
15463       break;
15464 //.. //--    case 0x1D: /* SBB Iv, eAX */
15465 //.. //--       delta = dis_op_imm_A( sz, SBB, True, delta, "sbb" );
15466 //.. //--       break;
15467 //.. //-- 
15468    case 0x24: /* AND Ib, AL */
15469       if (haveF2orF3(pfx)) goto decode_failure;
15470       delta = dis_op_imm_A( 1, False, Iop_And8, True, delta, "and" );
15471       break;
15472    case 0x25: /* AND Iv, eAX */
15473       if (haveF2orF3(pfx)) goto decode_failure;
15474       delta = dis_op_imm_A( sz, False, Iop_And8, True, delta, "and" );
15475       break;
15476
15477    case 0x2C: /* SUB Ib, AL */
15478       if (haveF2orF3(pfx)) goto decode_failure;
15479       delta = dis_op_imm_A(1, False, Iop_Sub8, True, delta, "sub" );
15480       break;
15481    case 0x2D: /* SUB Iv, eAX */
15482       if (haveF2orF3(pfx)) goto decode_failure;
15483       delta = dis_op_imm_A( sz, False, Iop_Sub8, True, delta, "sub" );
15484       break;
15485
15486    case 0x34: /* XOR Ib, AL */
15487       if (haveF2orF3(pfx)) goto decode_failure;
15488       delta = dis_op_imm_A( 1, False, Iop_Xor8, True, delta, "xor" );
15489       break;
15490    case 0x35: /* XOR Iv, eAX */
15491       if (haveF2orF3(pfx)) goto decode_failure;
15492       delta = dis_op_imm_A( sz, False, Iop_Xor8, True, delta, "xor" );
15493       break;
15494
15495    case 0x3C: /* CMP Ib, AL */
15496       if (haveF2orF3(pfx)) goto decode_failure;
15497       delta = dis_op_imm_A( 1, False, Iop_Sub8, False, delta, "cmp" );
15498       break;
15499    case 0x3D: /* CMP Iv, eAX */
15500       if (haveF2orF3(pfx)) goto decode_failure;
15501       delta = dis_op_imm_A( sz, False, Iop_Sub8, False, delta, "cmp" );
15502       break;
15503
15504    case 0xA8: /* TEST Ib, AL */
15505       if (haveF2orF3(pfx)) goto decode_failure;
15506       delta = dis_op_imm_A( 1, False, Iop_And8, False, delta, "test" );
15507       break;
15508    case 0xA9: /* TEST Iv, eAX */
15509       if (haveF2orF3(pfx)) goto decode_failure;
15510       delta = dis_op_imm_A( sz, False, Iop_And8, False, delta, "test" );
15511       break;
15512
15513    /* ------------------------ opl Ev, Gv ----------------- */
15514  
15515    case 0x02: /* ADD Eb,Gb */
15516       if (haveF2orF3(pfx)) goto decode_failure;
15517       delta = dis_op2_E_G ( vbi, pfx, False, Iop_Add8, True, 1, delta, "add" );
15518       break;
15519    case 0x03: /* ADD Ev,Gv */
15520       if (haveF2orF3(pfx)) goto decode_failure;
15521       delta = dis_op2_E_G ( vbi, pfx, False, Iop_Add8, True, sz, delta, "add" );
15522       break;
15523
15524    case 0x0A: /* OR Eb,Gb */
15525       if (haveF2orF3(pfx)) goto decode_failure;
15526       delta = dis_op2_E_G ( vbi, pfx, False, Iop_Or8, True, 1, delta, "or" );
15527       break;
15528    case 0x0B: /* OR Ev,Gv */
15529       if (haveF2orF3(pfx)) goto decode_failure;
15530       delta = dis_op2_E_G ( vbi, pfx, False, Iop_Or8, True, sz, delta, "or" );
15531       break;
15532
15533    case 0x12: /* ADC Eb,Gb */
15534       if (haveF2orF3(pfx)) goto decode_failure;
15535       delta = dis_op2_E_G ( vbi, pfx, True, Iop_Add8, True, 1, delta, "adc" );
15536       break;
15537    case 0x13: /* ADC Ev,Gv */
15538       if (haveF2orF3(pfx)) goto decode_failure;
15539       delta = dis_op2_E_G ( vbi, pfx, True, Iop_Add8, True, sz, delta, "adc" );
15540       break;
15541
15542    case 0x1A: /* SBB Eb,Gb */
15543       if (haveF2orF3(pfx)) goto decode_failure;
15544       delta = dis_op2_E_G ( vbi, pfx, True, Iop_Sub8, True, 1, delta, "sbb" );
15545       break;
15546    case 0x1B: /* SBB Ev,Gv */
15547       if (haveF2orF3(pfx)) goto decode_failure;
15548       delta = dis_op2_E_G ( vbi, pfx, True, Iop_Sub8, True, sz, delta, "sbb" );
15549       break;
15550
15551    case 0x22: /* AND Eb,Gb */
15552       if (haveF2orF3(pfx)) goto decode_failure;
15553       delta = dis_op2_E_G ( vbi, pfx, False, Iop_And8, True, 1, delta, "and" );
15554       break;
15555    case 0x23: /* AND Ev,Gv */
15556       if (haveF2orF3(pfx)) goto decode_failure;
15557       delta = dis_op2_E_G ( vbi, pfx, False, Iop_And8, True, sz, delta, "and" );
15558       break;
15559
15560    case 0x2A: /* SUB Eb,Gb */
15561       if (haveF2orF3(pfx)) goto decode_failure;
15562       delta = dis_op2_E_G ( vbi, pfx, False, Iop_Sub8, True, 1, delta, "sub" );
15563       break;
15564    case 0x2B: /* SUB Ev,Gv */
15565       if (haveF2orF3(pfx)) goto decode_failure;
15566       delta = dis_op2_E_G ( vbi, pfx, False, Iop_Sub8, True, sz, delta, "sub" );
15567       break;
15568
15569    case 0x32: /* XOR Eb,Gb */
15570       if (haveF2orF3(pfx)) goto decode_failure;
15571       delta = dis_op2_E_G ( vbi, pfx, False, Iop_Xor8, True, 1, delta, "xor" );
15572       break;
15573    case 0x33: /* XOR Ev,Gv */
15574       if (haveF2orF3(pfx)) goto decode_failure;
15575       delta = dis_op2_E_G ( vbi, pfx, False, Iop_Xor8, True, sz, delta, "xor" );
15576       break;
15577
15578    case 0x3A: /* CMP Eb,Gb */
15579       if (haveF2orF3(pfx)) goto decode_failure;
15580       delta = dis_op2_E_G ( vbi, pfx, False, Iop_Sub8, False, 1, delta, "cmp" );
15581       break;
15582    case 0x3B: /* CMP Ev,Gv */
15583       if (haveF2orF3(pfx)) goto decode_failure;
15584       delta = dis_op2_E_G ( vbi, pfx, False, Iop_Sub8, False, sz, delta, "cmp" );
15585       break;
15586
15587    case 0x84: /* TEST Eb,Gb */
15588       if (haveF2orF3(pfx)) goto decode_failure;
15589       delta = dis_op2_E_G ( vbi, pfx, False, Iop_And8, False, 1, delta, "test" );
15590       break;
15591    case 0x85: /* TEST Ev,Gv */
15592       if (haveF2orF3(pfx)) goto decode_failure;
15593       delta = dis_op2_E_G ( vbi, pfx, False, Iop_And8, False, sz, delta, "test" );
15594       break;
15595
15596    /* ------------------------ opl Gv, Ev ----------------- */
15597
15598    case 0x00: /* ADD Gb,Eb */
15599       if (haveF2orF3(pfx)) goto decode_failure;
15600       delta = dis_op2_G_E ( vbi, pfx, False, Iop_Add8, True, 1, delta, "add" );
15601       break;
15602    case 0x01: /* ADD Gv,Ev */
15603       if (haveF2orF3(pfx)) goto decode_failure;
15604       delta = dis_op2_G_E ( vbi, pfx, False, Iop_Add8, True, sz, delta, "add" );
15605       break;
15606
15607    case 0x08: /* OR Gb,Eb */
15608       if (haveF2orF3(pfx)) goto decode_failure;
15609       delta = dis_op2_G_E ( vbi, pfx, False, Iop_Or8, True, 1, delta, "or" );
15610       break;
15611    case 0x09: /* OR Gv,Ev */
15612       if (haveF2orF3(pfx)) goto decode_failure;
15613       delta = dis_op2_G_E ( vbi, pfx, False, Iop_Or8, True, sz, delta, "or" );
15614       break;
15615
15616    case 0x10: /* ADC Gb,Eb */
15617       if (haveF2orF3(pfx)) goto decode_failure;
15618       delta = dis_op2_G_E ( vbi, pfx, True, Iop_Add8, True, 1, delta, "adc" );
15619       break;
15620    case 0x11: /* ADC Gv,Ev */
15621       if (haveF2orF3(pfx)) goto decode_failure;
15622       delta = dis_op2_G_E ( vbi, pfx, True, Iop_Add8, True, sz, delta, "adc" );
15623       break;
15624
15625    case 0x18: /* SBB Gb,Eb */
15626       if (haveF2orF3(pfx)) goto decode_failure;
15627       delta = dis_op2_G_E ( vbi, pfx, True, Iop_Sub8, True, 1, delta, "sbb" );
15628       break;
15629    case 0x19: /* SBB Gv,Ev */
15630       if (haveF2orF3(pfx)) goto decode_failure;
15631       delta = dis_op2_G_E ( vbi, pfx, True, Iop_Sub8, True, sz, delta, "sbb" );
15632       break;
15633
15634    case 0x20: /* AND Gb,Eb */
15635       if (haveF2orF3(pfx)) goto decode_failure;
15636       delta = dis_op2_G_E ( vbi, pfx, False, Iop_And8, True, 1, delta, "and" );
15637       break;
15638    case 0x21: /* AND Gv,Ev */
15639       if (haveF2orF3(pfx)) goto decode_failure;
15640       delta = dis_op2_G_E ( vbi, pfx, False, Iop_And8, True, sz, delta, "and" );
15641       break;
15642
15643    case 0x28: /* SUB Gb,Eb */
15644       if (haveF2orF3(pfx)) goto decode_failure;
15645       delta = dis_op2_G_E ( vbi, pfx, False, Iop_Sub8, True, 1, delta, "sub" );
15646       break;
15647    case 0x29: /* SUB Gv,Ev */
15648       if (haveF2orF3(pfx)) goto decode_failure;
15649       delta = dis_op2_G_E ( vbi, pfx, False, Iop_Sub8, True, sz, delta, "sub" );
15650       break;
15651
15652    case 0x30: /* XOR Gb,Eb */
15653       if (haveF2orF3(pfx)) goto decode_failure;
15654       delta = dis_op2_G_E ( vbi, pfx, False, Iop_Xor8, True, 1, delta, "xor" );
15655       break;
15656    case 0x31: /* XOR Gv,Ev */
15657       if (haveF2orF3(pfx)) goto decode_failure;
15658       delta = dis_op2_G_E ( vbi, pfx, False, Iop_Xor8, True, sz, delta, "xor" );
15659       break;
15660
15661    case 0x38: /* CMP Gb,Eb */
15662       if (haveF2orF3(pfx)) goto decode_failure;
15663       delta = dis_op2_G_E ( vbi, pfx, False, Iop_Sub8, False, 1, delta, "cmp" );
15664       break;
15665    case 0x39: /* CMP Gv,Ev */
15666       if (haveF2orF3(pfx)) goto decode_failure;
15667       delta = dis_op2_G_E ( vbi, pfx, False, Iop_Sub8, False, sz, delta, "cmp" );
15668       break;
15669
15670    /* ------------------------ POP ------------------------ */
15671
15672    case 0x58: /* POP eAX */
15673    case 0x59: /* POP eCX */
15674    case 0x5A: /* POP eDX */
15675    case 0x5B: /* POP eBX */
15676    case 0x5D: /* POP eBP */
15677    case 0x5E: /* POP eSI */
15678    case 0x5F: /* POP eDI */
15679    case 0x5C: /* POP eSP */
15680       if (haveF2orF3(pfx)) goto decode_failure;
15681       vassert(sz == 2 || sz == 4 || sz == 8);
15682       if (sz == 4)
15683          sz = 8; /* there is no encoding for 32-bit pop in 64-bit mode */
15684       t1 = newTemp(szToITy(sz)); 
15685       t2 = newTemp(Ity_I64);
15686       assign(t2, getIReg64(R_RSP));
15687       assign(t1, loadLE(szToITy(sz),mkexpr(t2)));
15688       putIReg64(R_RSP, binop(Iop_Add64, mkexpr(t2), mkU64(sz)));
15689       putIRegRexB(sz, pfx, opc-0x58, mkexpr(t1));
15690       DIP("pop%c %s\n", nameISize(sz), nameIRegRexB(sz,pfx,opc-0x58));
15691       break;
15692
15693    case 0x9D: /* POPF */
15694       /* Note.  There is no encoding for a 32-bit popf in 64-bit mode.
15695          So sz==4 actually means sz==8. */
15696       if (haveF2orF3(pfx)) goto decode_failure;
15697       vassert(sz == 2 || sz == 4);
15698       if (sz == 4) sz = 8;
15699       if (sz != 8) goto decode_failure; // until we know a sz==2 test case exists
15700       t1 = newTemp(Ity_I64); t2 = newTemp(Ity_I64);
15701       assign(t2, getIReg64(R_RSP));
15702       assign(t1, widenUto64(loadLE(szToITy(sz),mkexpr(t2))));
15703       putIReg64(R_RSP, binop(Iop_Add64, mkexpr(t2), mkU64(sz)));
15704       /* t1 is the flag word.  Mask out everything except OSZACP and 
15705          set the flags thunk to AMD64G_CC_OP_COPY. */
15706       stmt( IRStmt_Put( OFFB_CC_OP,   mkU64(AMD64G_CC_OP_COPY) ));
15707       stmt( IRStmt_Put( OFFB_CC_DEP2, mkU64(0) ));
15708       stmt( IRStmt_Put( OFFB_CC_DEP1, 
15709                         binop(Iop_And64,
15710                               mkexpr(t1), 
15711                               mkU64( AMD64G_CC_MASK_C | AMD64G_CC_MASK_P 
15712                                      | AMD64G_CC_MASK_A | AMD64G_CC_MASK_Z 
15713                                      | AMD64G_CC_MASK_S| AMD64G_CC_MASK_O )
15714                              )
15715                        )
15716           );
15717
15718       /* Also need to set the D flag, which is held in bit 10 of t1.
15719          If zero, put 1 in OFFB_DFLAG, else -1 in OFFB_DFLAG. */
15720       stmt( IRStmt_Put( 
15721                OFFB_DFLAG,
15722                IRExpr_Mux0X( 
15723                   unop(Iop_32to8,
15724                   unop(Iop_64to32,
15725                        binop(Iop_And64, 
15726                              binop(Iop_Shr64, mkexpr(t1), mkU8(10)), 
15727                              mkU64(1)))),
15728                   mkU64(1), 
15729                   mkU64(0xFFFFFFFFFFFFFFFFULL))) 
15730           );
15731
15732       /* And set the ID flag */
15733       stmt( IRStmt_Put( 
15734                OFFB_IDFLAG,
15735                IRExpr_Mux0X( 
15736                   unop(Iop_32to8,
15737                   unop(Iop_64to32,
15738                        binop(Iop_And64, 
15739                              binop(Iop_Shr64, mkexpr(t1), mkU8(21)), 
15740                              mkU64(1)))),
15741                   mkU64(0), 
15742                   mkU64(1))) 
15743           );
15744
15745       DIP("popf%c\n", nameISize(sz));
15746       break;
15747
15748 //..    case 0x61: /* POPA */
15749 //..       /* This is almost certainly wrong for sz==2.  So ... */
15750 //..       if (sz != 4) goto decode_failure;
15751 //.. 
15752 //..       /* t5 is the old %ESP value. */
15753 //..       t5 = newTemp(Ity_I32);
15754 //..       assign( t5, getIReg(4, R_ESP) );
15755 //.. 
15756 //..       /* Reload all the registers, except %esp. */
15757 //..       putIReg(4,R_EAX, loadLE(Ity_I32, binop(Iop_Add32,mkexpr(t5),mkU32(28)) ));
15758 //..       putIReg(4,R_ECX, loadLE(Ity_I32, binop(Iop_Add32,mkexpr(t5),mkU32(24)) ));
15759 //..       putIReg(4,R_EDX, loadLE(Ity_I32, binop(Iop_Add32,mkexpr(t5),mkU32(20)) ));
15760 //..       putIReg(4,R_EBX, loadLE(Ity_I32, binop(Iop_Add32,mkexpr(t5),mkU32(16)) ));
15761 //..       /* ignore saved %ESP */
15762 //..       putIReg(4,R_EBP, loadLE(Ity_I32, binop(Iop_Add32,mkexpr(t5),mkU32( 8)) ));
15763 //..       putIReg(4,R_ESI, loadLE(Ity_I32, binop(Iop_Add32,mkexpr(t5),mkU32( 4)) ));
15764 //..       putIReg(4,R_EDI, loadLE(Ity_I32, binop(Iop_Add32,mkexpr(t5),mkU32( 0)) ));
15765 //.. 
15766 //..       /* and move %ESP back up */
15767 //..       putIReg( 4, R_ESP, binop(Iop_Add32, mkexpr(t5), mkU32(8*4)) );
15768 //.. 
15769 //..       DIP("pusha%c\n", nameISize(sz));
15770 //..       break;
15771
15772    case 0x8F: { /* POPQ m64 / POPW m16 */
15773       Int   len;
15774       UChar rm;
15775       /* There is no encoding for 32-bit pop in 64-bit mode.
15776          So sz==4 actually means sz==8. */
15777       if (haveF2orF3(pfx)) goto decode_failure;
15778       vassert(sz == 2 || sz == 4);
15779       if (sz == 4) sz = 8;
15780       if (sz != 8) goto decode_failure; // until we know a sz==2 test case exists
15781
15782       rm = getUChar(delta);
15783
15784       /* make sure this instruction is correct POP */
15785       if (epartIsReg(rm) || gregLO3ofRM(rm) != 0)
15786          goto decode_failure;
15787       /* and has correct size */
15788       vassert(sz == 8);      
15789        
15790       t1 = newTemp(Ity_I64);
15791       t3 = newTemp(Ity_I64);
15792       assign( t1, getIReg64(R_RSP) );
15793       assign( t3, loadLE(Ity_I64, mkexpr(t1)) );
15794        
15795       /* Increase RSP; must be done before the STORE.  Intel manual
15796          says: If the RSP register is used as a base register for
15797          addressing a destination operand in memory, the POP
15798          instruction computes the effective address of the operand
15799          after it increments the RSP register.  */
15800       putIReg64(R_RSP, binop(Iop_Add64, mkexpr(t1), mkU64(sz)) );
15801
15802       addr = disAMode ( &len, vbi, pfx, delta, dis_buf, 0 );
15803       storeLE( mkexpr(addr), mkexpr(t3) );
15804
15805       DIP("popl %s\n", dis_buf);
15806
15807       delta += len;
15808       break;
15809    }
15810
15811 //.. //--    case 0x1F: /* POP %DS */
15812 //.. //--       dis_pop_segreg( cb, R_DS, sz ); break;
15813 //.. //--    case 0x07: /* POP %ES */
15814 //.. //--       dis_pop_segreg( cb, R_ES, sz ); break;
15815 //.. //--    case 0x17: /* POP %SS */
15816 //.. //--       dis_pop_segreg( cb, R_SS, sz ); break;
15817
15818    /* ------------------------ PUSH ----------------------- */
15819
15820    case 0x50: /* PUSH eAX */
15821    case 0x51: /* PUSH eCX */
15822    case 0x52: /* PUSH eDX */
15823    case 0x53: /* PUSH eBX */
15824    case 0x55: /* PUSH eBP */
15825    case 0x56: /* PUSH eSI */
15826    case 0x57: /* PUSH eDI */
15827    case 0x54: /* PUSH eSP */
15828       /* This is the Right Way, in that the value to be pushed is
15829          established before %rsp is changed, so that pushq %rsp
15830          correctly pushes the old value. */
15831       if (haveF2orF3(pfx)) goto decode_failure;
15832       vassert(sz == 2 || sz == 4 || sz == 8);
15833       if (sz == 4)
15834          sz = 8; /* there is no encoding for 32-bit push in 64-bit mode */
15835       ty = sz==2 ? Ity_I16 : Ity_I64;
15836       t1 = newTemp(ty); 
15837       t2 = newTemp(Ity_I64);
15838       assign(t1, getIRegRexB(sz, pfx, opc-0x50));
15839       assign(t2, binop(Iop_Sub64, getIReg64(R_RSP), mkU64(sz)));
15840       putIReg64(R_RSP, mkexpr(t2) );
15841       storeLE(mkexpr(t2),mkexpr(t1));
15842       DIP("push%c %s\n", nameISize(sz), nameIRegRexB(sz,pfx,opc-0x50));
15843       break;
15844
15845    case 0x68: /* PUSH Iv */
15846       if (haveF2orF3(pfx)) goto decode_failure;
15847       /* Note, sz==4 is not possible in 64-bit mode.  Hence ... */
15848       if (sz == 4) sz = 8;
15849       d64 = getSDisp(imin(4,sz),delta); 
15850       delta += imin(4,sz);
15851       goto do_push_I;
15852    case 0x6A: /* PUSH Ib, sign-extended to sz */
15853       if (haveF2orF3(pfx)) goto decode_failure;
15854       /* Note, sz==4 is not possible in 64-bit mode.  Hence ... */
15855       if (sz == 4) sz = 8;
15856       d64 = getSDisp8(delta); delta += 1;
15857       goto do_push_I;
15858    do_push_I:
15859       ty = szToITy(sz);
15860       t1 = newTemp(Ity_I64);
15861       t2 = newTemp(ty);
15862       assign( t1, binop(Iop_Sub64,getIReg64(R_RSP),mkU64(sz)) );
15863       putIReg64(R_RSP, mkexpr(t1) );
15864       /* stop mkU16 asserting if d32 is a negative 16-bit number
15865          (bug #132813) */
15866       if (ty == Ity_I16)
15867          d64 &= 0xFFFF;
15868       storeLE( mkexpr(t1), mkU(ty,d64) );
15869       DIP("push%c $%lld\n", nameISize(sz), (Long)d64);
15870       break;
15871
15872    case 0x9C: /* PUSHF */ {
15873       /* Note.  There is no encoding for a 32-bit pushf in 64-bit
15874          mode.  So sz==4 actually means sz==8. */
15875       /* 24 July 06: has also been seen with a redundant REX prefix,
15876          so must also allow sz==8. */
15877       if (haveF2orF3(pfx)) goto decode_failure;
15878       vassert(sz == 2 || sz == 4 || sz == 8);
15879       if (sz == 4) sz = 8;
15880       if (sz != 8) goto decode_failure; // until we know a sz==2 test case exists
15881
15882       t1 = newTemp(Ity_I64);
15883       assign( t1, binop(Iop_Sub64,getIReg64(R_RSP),mkU64(sz)) );
15884       putIReg64(R_RSP, mkexpr(t1) );
15885
15886       t2 = newTemp(Ity_I64);
15887       assign( t2, mk_amd64g_calculate_rflags_all() );
15888
15889       /* Patch in the D flag.  This can simply be a copy of bit 10 of
15890          baseBlock[OFFB_DFLAG]. */
15891       t3 = newTemp(Ity_I64);
15892       assign( t3, binop(Iop_Or64,
15893                         mkexpr(t2),
15894                         binop(Iop_And64,
15895                               IRExpr_Get(OFFB_DFLAG,Ity_I64),
15896                               mkU64(1<<10))) 
15897             );
15898
15899       /* And patch in the ID flag. */
15900       t4 = newTemp(Ity_I64);
15901       assign( t4, binop(Iop_Or64,
15902                         mkexpr(t3),
15903                         binop(Iop_And64,
15904                               binop(Iop_Shl64, IRExpr_Get(OFFB_IDFLAG,Ity_I64), 
15905                                                mkU8(21)),
15906                               mkU64(1<<21)))
15907             );
15908
15909       /* if sz==2, the stored value needs to be narrowed. */
15910       if (sz == 2)
15911         storeLE( mkexpr(t1), unop(Iop_32to16,
15912                              unop(Iop_64to32,mkexpr(t4))) );
15913       else 
15914         storeLE( mkexpr(t1), mkexpr(t4) );
15915
15916       DIP("pushf%c\n", nameISize(sz));
15917       break;
15918    }
15919
15920 //..    case 0x60: /* PUSHA */
15921 //..       /* This is almost certainly wrong for sz==2.  So ... */
15922 //..       if (sz != 4) goto decode_failure;
15923 //.. 
15924 //..       /* This is the Right Way, in that the value to be pushed is
15925 //..          established before %esp is changed, so that pusha
15926 //..          correctly pushes the old %esp value.  New value of %esp is
15927 //..          pushed at start. */
15928 //..       /* t0 is the %ESP value we're going to push. */
15929 //..       t0 = newTemp(Ity_I32);
15930 //..       assign( t0, getIReg(4, R_ESP) );
15931 //.. 
15932 //..       /* t5 will be the new %ESP value. */
15933 //..       t5 = newTemp(Ity_I32);
15934 //..       assign( t5, binop(Iop_Sub32, mkexpr(t0), mkU32(8*4)) );
15935 //.. 
15936 //..       /* Update guest state before prodding memory. */
15937 //..       putIReg(4, R_ESP, mkexpr(t5));
15938 //.. 
15939 //..       /* Dump all the registers. */
15940 //..       storeLE( binop(Iop_Add32,mkexpr(t5),mkU32(28)), getIReg(4,R_EAX) );
15941 //..       storeLE( binop(Iop_Add32,mkexpr(t5),mkU32(24)), getIReg(4,R_ECX) );
15942 //..       storeLE( binop(Iop_Add32,mkexpr(t5),mkU32(20)), getIReg(4,R_EDX) );
15943 //..       storeLE( binop(Iop_Add32,mkexpr(t5),mkU32(16)), getIReg(4,R_EBX) );
15944 //..       storeLE( binop(Iop_Add32,mkexpr(t5),mkU32(12)), mkexpr(t0) /*esp*/);
15945 //..       storeLE( binop(Iop_Add32,mkexpr(t5),mkU32( 8)), getIReg(4,R_EBP) );
15946 //..       storeLE( binop(Iop_Add32,mkexpr(t5),mkU32( 4)), getIReg(4,R_ESI) );
15947 //..       storeLE( binop(Iop_Add32,mkexpr(t5),mkU32( 0)), getIReg(4,R_EDI) );
15948 //.. 
15949 //..       DIP("pusha%c\n", nameISize(sz));
15950 //..       break;
15951 //.. 
15952 //.. 
15953 //.. //--    case 0x0E: /* PUSH %CS */
15954 //.. //--       dis_push_segreg( cb, R_CS, sz ); break;
15955 //.. //--    case 0x1E: /* PUSH %DS */
15956 //.. //--       dis_push_segreg( cb, R_DS, sz ); break;
15957 //.. //--    case 0x06: /* PUSH %ES */
15958 //.. //--       dis_push_segreg( cb, R_ES, sz ); break;
15959 //.. //--    case 0x16: /* PUSH %SS */
15960 //.. //--       dis_push_segreg( cb, R_SS, sz ); break;
15961 //.. 
15962 //..    /* ------------------------ SCAS et al ----------------- */
15963 //.. 
15964 //..    case 0xA4: /* MOVS, no REP prefix */
15965 //..    case 0xA5: 
15966 //..       dis_string_op( dis_MOVS, ( opc == 0xA4 ? 1 : sz ), "movs", sorb );
15967 //..       break;
15968 //.. 
15969 //..   case 0xA6: /* CMPSb, no REP prefix */
15970 //.. //--    case 0xA7:
15971 //..      dis_string_op( dis_CMPS, ( opc == 0xA6 ? 1 : sz ), "cmps", sorb );
15972 //..      break;
15973 //.. //-- 
15974 //.. //--    
15975     case 0xAC: /* LODS, no REP prefix */
15976     case 0xAD:
15977        dis_string_op( dis_LODS, ( opc == 0xAC ? 1 : sz ), "lods", pfx );
15978        break;
15979 //.. 
15980 //..    case 0xAE: /* SCAS, no REP prefix */
15981 //..    case 0xAF:
15982 //..       dis_string_op( dis_SCAS, ( opc == 0xAE ? 1 : sz ), "scas", sorb );
15983 //..       break;
15984
15985
15986    case 0xFC: /* CLD */
15987       if (haveF2orF3(pfx)) goto decode_failure;
15988       stmt( IRStmt_Put( OFFB_DFLAG, mkU64(1)) );
15989       DIP("cld\n");
15990       break;
15991
15992    case 0xFD: /* STD */
15993       if (haveF2orF3(pfx)) goto decode_failure;
15994       stmt( IRStmt_Put( OFFB_DFLAG, mkU64(-1ULL)) );
15995       DIP("std\n");
15996       break;
15997
15998    case 0xF8: /* CLC */
15999    case 0xF9: /* STC */
16000    case 0xF5: /* CMC */
16001       t0 = newTemp(Ity_I64);
16002       t1 = newTemp(Ity_I64);
16003       assign( t0, mk_amd64g_calculate_rflags_all() );
16004       switch (opc) {
16005          case 0xF8: 
16006             assign( t1, binop(Iop_And64, mkexpr(t0), 
16007                                          mkU64(~AMD64G_CC_MASK_C)));
16008             DIP("clc\n");
16009             break;
16010          case 0xF9: 
16011             assign( t1, binop(Iop_Or64, mkexpr(t0), 
16012                                         mkU64(AMD64G_CC_MASK_C)));
16013             DIP("stc\n");
16014             break;
16015          case 0xF5: 
16016             assign( t1, binop(Iop_Xor64, mkexpr(t0), 
16017                                          mkU64(AMD64G_CC_MASK_C)));
16018             DIP("cmc\n");
16019             break;
16020          default: 
16021             vpanic("disInstr(x64)(clc/stc/cmc)");
16022       }
16023       stmt( IRStmt_Put( OFFB_CC_OP,   mkU64(AMD64G_CC_OP_COPY) ));
16024       stmt( IRStmt_Put( OFFB_CC_DEP2, mkU64(0) ));
16025       stmt( IRStmt_Put( OFFB_CC_DEP1, mkexpr(t1) ));
16026       /* Set NDEP even though it isn't used.  This makes redundant-PUT
16027          elimination of previous stores to this field work better. */
16028       stmt( IRStmt_Put( OFFB_CC_NDEP, mkU64(0) ));
16029       break;
16030
16031 //..    /* REPNE prefix insn */
16032 //..    case 0xF2: { 
16033 //..       Addr32 eip_orig = guest_eip_bbstart + delta - 1;
16034 //..       vassert(sorb == 0);
16035 //..       abyte = getUChar(delta); delta++;
16036 //.. 
16037 //..       if (abyte == 0x66) { sz = 2; abyte = getUChar(delta); delta++; }
16038 //..       whatNext = Dis_StopHere;         
16039 //.. 
16040 //..       switch (abyte) {
16041 //..       /* According to the Intel manual, "repne movs" should never occur, but
16042 //..        * in practice it has happened, so allow for it here... */
16043 //..       case 0xA4: sz = 1;   /* REPNE MOVS<sz> */
16044 //..         goto decode_failure;
16045 //.. //--       case 0xA5: 
16046 //..         //         dis_REP_op ( CondNZ, dis_MOVS, sz, eip_orig,
16047 //..         //                              guest_eip_bbstart+delta, "repne movs" );
16048 //..         //         break;
16049 //.. //-- 
16050 //.. //--       case 0xA6: sz = 1;   /* REPNE CMPS<sz> */
16051 //.. //--       case 0xA7:
16052 //.. //--          dis_REP_op ( cb, CondNZ, dis_CMPS, sz, eip_orig, eip, "repne cmps" );
16053 //.. //--          break;
16054 //.. //-- 
16055 //..       case 0xAE: sz = 1;   /* REPNE SCAS<sz> */
16056 //..       case 0xAF:
16057 //..          dis_REP_op ( X86CondNZ, dis_SCAS, sz, eip_orig,
16058 //..                                  guest_eip_bbstart+delta, "repne scas" );
16059 //..          break;
16060 //.. 
16061 //..       default:
16062 //..          goto decode_failure;
16063 //..       }
16064 //..       break;
16065 //..    }
16066
16067    /* ------ AE: SCAS variants ------ */
16068    case 0xAE:
16069    case 0xAF:
16070       /* F2 AE/AF: repne scasb/repne scas{w,l,q} */
16071       if (haveASO(pfx)) 
16072          goto decode_failure;
16073       if (haveF2(pfx) && !haveF3(pfx)) {
16074          if (opc == 0xAE)
16075             sz = 1;
16076          dis_REP_op ( AMD64CondNZ, dis_SCAS, sz, 
16077                       guest_RIP_curr_instr,
16078                       guest_RIP_bbstart+delta, "repne scas", pfx );
16079          dres.whatNext = Dis_StopHere;
16080          break;
16081       }
16082       /* F3 AE/AF: repe scasb/repe scas{w,l,q} */
16083       if (haveASO(pfx)) 
16084          goto decode_failure;
16085       if (!haveF2(pfx) && haveF3(pfx)) {
16086          if (opc == 0xAE)
16087             sz = 1;
16088          dis_REP_op ( AMD64CondZ, dis_SCAS, sz, 
16089                       guest_RIP_curr_instr,
16090                       guest_RIP_bbstart+delta, "repe scas", pfx );
16091          dres.whatNext = Dis_StopHere;
16092          break;
16093       }
16094       /* AE/AF: scasb/scas{w,l,q} */
16095       if (!haveF2(pfx) && !haveF3(pfx)) {
16096          if (opc == 0xAE)
16097             sz = 1;
16098          dis_string_op( dis_SCAS, sz, "scas", pfx );
16099          break;
16100       }
16101       goto decode_failure;
16102
16103    /* ------ A6, A7: CMPS variants ------ */
16104    case 0xA6:
16105    case 0xA7:
16106       /* F3 A6/A7: repe cmps/rep cmps{w,l,q} */
16107       if (haveASO(pfx)) 
16108          goto decode_failure;
16109       if (haveF3(pfx) && !haveF2(pfx)) {
16110          if (opc == 0xA6)
16111             sz = 1;
16112          dis_REP_op ( AMD64CondZ, dis_CMPS, sz, 
16113                       guest_RIP_curr_instr,
16114                       guest_RIP_bbstart+delta, "repe cmps", pfx );
16115          dres.whatNext = Dis_StopHere;
16116          break;
16117       }
16118       goto decode_failure;
16119
16120    /* ------ AA, AB: STOS variants ------ */
16121    case 0xAA:
16122    case 0xAB:
16123       /* F3 AA/AB: rep stosb/rep stos{w,l,q} */
16124       if (haveASO(pfx)) 
16125          goto decode_failure;
16126       if (haveF3(pfx) && !haveF2(pfx)) {
16127          if (opc == 0xAA)
16128             sz = 1;
16129          dis_REP_op ( AMD64CondAlways, dis_STOS, sz,
16130                       guest_RIP_curr_instr,
16131                       guest_RIP_bbstart+delta, "rep stos", pfx );
16132         dres.whatNext = Dis_StopHere;
16133         break;
16134       }
16135       /* AA/AB: stosb/stos{w,l,q} */
16136       if (!haveF3(pfx) && !haveF2(pfx)) {
16137          if (opc == 0xAA)
16138             sz = 1;
16139          dis_string_op( dis_STOS, sz, "stos", pfx );
16140          break;
16141       }
16142       goto decode_failure;
16143
16144    /* ------ A4, A5: MOVS variants ------ */
16145    case 0xA4:
16146    case 0xA5:
16147       /* F3 A4: rep movsb */
16148       if (haveASO(pfx)) 
16149          goto decode_failure;
16150       if (haveF3(pfx) && !haveF2(pfx)) {
16151          if (opc == 0xA4)
16152             sz = 1;
16153          dis_REP_op ( AMD64CondAlways, dis_MOVS, sz,
16154                       guest_RIP_curr_instr,
16155                       guest_RIP_bbstart+delta, "rep movs", pfx );
16156         dres.whatNext = Dis_StopHere;
16157         break;
16158       }
16159       /* A4: movsb */
16160       if (!haveF3(pfx) && !haveF2(pfx)) {
16161          if (opc == 0xA4)
16162             sz = 1;
16163          dis_string_op( dis_MOVS, sz, "movs", pfx );
16164          break;
16165       }
16166       goto decode_failure;
16167
16168
16169    /* ------------------------ XCHG ----------------------- */
16170
16171    /* XCHG reg,mem automatically asserts LOCK# even without a LOCK
16172       prefix.  Therefore, surround it with a IRStmt_MBE(Imbe_BusLock)
16173       and IRStmt_MBE(Imbe_BusUnlock) pair.  But be careful; if it is
16174       used with an explicit LOCK prefix, we don't want to end up with
16175       two IRStmt_MBE(Imbe_BusLock)s -- one made here and one made by
16176       the generic LOCK logic at the top of disInstr. */
16177    case 0x86: /* XCHG Gb,Eb */
16178       sz = 1;
16179       /* Fall through ... */
16180    case 0x87: /* XCHG Gv,Ev */
16181       if (haveF2orF3(pfx)) goto decode_failure;
16182       modrm = getUChar(delta);
16183       ty = szToITy(sz);
16184       t1 = newTemp(ty); t2 = newTemp(ty);
16185       if (epartIsReg(modrm)) {
16186          assign(t1, getIRegE(sz, pfx, modrm));
16187          assign(t2, getIRegG(sz, pfx, modrm));
16188          putIRegG(sz, pfx, modrm, mkexpr(t1));
16189          putIRegE(sz, pfx, modrm, mkexpr(t2));
16190          delta++;
16191          DIP("xchg%c %s, %s\n", 
16192              nameISize(sz), nameIRegG(sz, pfx, modrm), 
16193                             nameIRegE(sz, pfx, modrm));
16194       } else {
16195          *expect_CAS = True;
16196          addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
16197          assign( t1, loadLE(ty, mkexpr(addr)) );
16198          assign( t2, getIRegG(sz, pfx, modrm) );
16199          casLE( mkexpr(addr),
16200                 mkexpr(t1), mkexpr(t2), guest_RIP_curr_instr );
16201          putIRegG( sz, pfx, modrm, mkexpr(t1) );
16202          delta += alen;
16203          DIP("xchg%c %s, %s\n", nameISize(sz), 
16204                                 nameIRegG(sz, pfx, modrm), dis_buf);
16205       }
16206       break;
16207
16208    case 0x90: /* XCHG eAX,eAX */
16209       /* detect and handle F3 90 (rep nop) specially */
16210       if (!have66(pfx) && !haveF2(pfx) && haveF3(pfx)) {
16211          DIP("rep nop (P4 pause)\n");
16212          /* "observe" the hint.  The Vex client needs to be careful not
16213             to cause very long delays as a result, though. */
16214          jmp_lit(Ijk_Yield, guest_RIP_bbstart+delta);
16215          dres.whatNext = Dis_StopHere;
16216          break;
16217       }
16218       /* detect and handle NOPs specially */
16219       if (/* F2/F3 probably change meaning completely */
16220           !haveF2orF3(pfx)
16221           /* If REX.B is 1, we're not exchanging rAX with itself */
16222           && getRexB(pfx)==0 ) {
16223          DIP("nop\n");
16224          break;
16225       }
16226       /* else fall through to normal case. */
16227    case 0x91: /* XCHG rAX,rCX */
16228    case 0x92: /* XCHG rAX,rDX */
16229    case 0x93: /* XCHG rAX,rBX */
16230    case 0x94: /* XCHG rAX,rSP */
16231    case 0x95: /* XCHG rAX,rBP */
16232    case 0x96: /* XCHG rAX,rSI */
16233    case 0x97: /* XCHG rAX,rDI */
16234
16235       /* guard against mutancy */
16236       if (haveF2orF3(pfx)) goto decode_failure;
16237
16238       /* sz == 2 could legitimately happen, but we don't handle it yet */
16239       if (sz == 2) goto decode_failure; /* awaiting test case */
16240
16241       codegen_xchg_rAX_Reg ( pfx, sz, opc - 0x90 );
16242       break;
16243
16244 //.. //--    /* ------------------------ XLAT ----------------------- */
16245 //.. //-- 
16246 //.. //--    case 0xD7: /* XLAT */
16247 //.. //--       t1 = newTemp(cb); t2 = newTemp(cb);
16248 //.. //--       uInstr2(cb, GET, sz, ArchReg, R_EBX, TempReg, t1); /* get eBX */
16249 //.. //--       handleAddrOverrides( cb, sorb, t1 );               /* make t1 DS:eBX */
16250 //.. //--       uInstr2(cb, GET, 1, ArchReg, R_AL, TempReg, t2); /* get AL */
16251 //.. //--       /* Widen %AL to 32 bits, so it's all defined when we add it. */
16252 //.. //--       uInstr1(cb, WIDEN, 4, TempReg, t2);
16253 //.. //--       uWiden(cb, 1, False);
16254 //.. //--       uInstr2(cb, ADD, sz, TempReg, t2, TempReg, t1);  /* add AL to eBX */
16255 //.. //--       uInstr2(cb, LOAD, 1, TempReg, t1,  TempReg, t2); /* get byte at t1 into t2 */
16256 //.. //--       uInstr2(cb, PUT, 1, TempReg, t2, ArchReg, R_AL); /* put byte into AL */
16257 //.. //-- 
16258 //.. //--       DIP("xlat%c [ebx]\n", nameISize(sz));
16259 //.. //--       break;
16260
16261    /* ------------------------ IN / OUT ----------------------- */
16262  
16263    case 0xE4: /* IN imm8, AL */
16264       sz = 1; 
16265       t1 = newTemp(Ity_I64);
16266       abyte = getUChar(delta); delta++;
16267       assign(t1, mkU64( abyte & 0xFF ));
16268       DIP("in%c $%d,%s\n", nameISize(sz), (Int)abyte, nameIRegRAX(sz));
16269       goto do_IN;
16270    case 0xE5: /* IN imm8, eAX */
16271       if (!(sz == 2 || sz == 4)) goto decode_failure;
16272       t1 = newTemp(Ity_I64);
16273       abyte = getUChar(delta); delta++;
16274       assign(t1, mkU64( abyte & 0xFF ));
16275       DIP("in%c $%d,%s\n", nameISize(sz), (Int)abyte, nameIRegRAX(sz));
16276       goto do_IN;
16277    case 0xEC: /* IN %DX, AL */
16278       sz = 1; 
16279       t1 = newTemp(Ity_I64);
16280       assign(t1, unop(Iop_16Uto64, getIRegRDX(2)));
16281       DIP("in%c %s,%s\n", nameISize(sz), nameIRegRDX(2), 
16282                                          nameIRegRAX(sz));
16283       goto do_IN;
16284    case 0xED: /* IN %DX, eAX */
16285       if (!(sz == 2 || sz == 4)) goto decode_failure;
16286       t1 = newTemp(Ity_I64);
16287       assign(t1, unop(Iop_16Uto64, getIRegRDX(2)));
16288       DIP("in%c %s,%s\n", nameISize(sz), nameIRegRDX(2), 
16289                                          nameIRegRAX(sz));
16290       goto do_IN;
16291    do_IN: {
16292       /* At this point, sz indicates the width, and t1 is a 64-bit
16293          value giving port number. */
16294       IRDirty* d;
16295       if (haveF2orF3(pfx)) goto decode_failure;
16296       vassert(sz == 1 || sz == 2 || sz == 4);
16297       ty = szToITy(sz);
16298       t2 = newTemp(Ity_I64);
16299       d = unsafeIRDirty_1_N( 
16300              t2,
16301              0/*regparms*/, 
16302              "amd64g_dirtyhelper_IN", 
16303              &amd64g_dirtyhelper_IN,
16304              mkIRExprVec_2( mkexpr(t1), mkU64(sz) )
16305           );
16306       /* do the call, dumping the result in t2. */
16307       stmt( IRStmt_Dirty(d) );
16308       putIRegRAX(sz, narrowTo( ty, mkexpr(t2) ) );
16309       break;
16310    }
16311
16312    case 0xE6: /* OUT AL, imm8 */
16313       sz = 1;
16314       t1 = newTemp(Ity_I64);
16315       abyte = getUChar(delta); delta++;
16316       assign( t1, mkU64( abyte & 0xFF ) );
16317       DIP("out%c %s,$%d\n", nameISize(sz), nameIRegRAX(sz), (Int)abyte);
16318       goto do_OUT;
16319    case 0xE7: /* OUT eAX, imm8 */
16320       if (!(sz == 2 || sz == 4)) goto decode_failure;
16321       t1 = newTemp(Ity_I64);
16322       abyte = getUChar(delta); delta++;
16323       assign( t1, mkU64( abyte & 0xFF ) );
16324       DIP("out%c %s,$%d\n", nameISize(sz), nameIRegRAX(sz), (Int)abyte);
16325       goto do_OUT;
16326    case 0xEE: /* OUT AL, %DX */
16327       sz = 1;
16328       t1 = newTemp(Ity_I64);
16329       assign( t1, unop(Iop_16Uto64, getIRegRDX(2)) );
16330       DIP("out%c %s,%s\n", nameISize(sz), nameIRegRAX(sz),
16331                                           nameIRegRDX(2));
16332       goto do_OUT;
16333    case 0xEF: /* OUT eAX, %DX */
16334       if (!(sz == 2 || sz == 4)) goto decode_failure;
16335       t1 = newTemp(Ity_I64);
16336       assign( t1, unop(Iop_16Uto64, getIRegRDX(2)) );
16337       DIP("out%c %s,%s\n", nameISize(sz), nameIRegRAX(sz),
16338                                           nameIRegRDX(2));
16339       goto do_OUT;
16340    do_OUT: {
16341       /* At this point, sz indicates the width, and t1 is a 64-bit
16342          value giving port number. */
16343       IRDirty* d;
16344       if (haveF2orF3(pfx)) goto decode_failure;
16345       vassert(sz == 1 || sz == 2 || sz == 4);
16346       ty = szToITy(sz);
16347       d = unsafeIRDirty_0_N( 
16348              0/*regparms*/, 
16349              "amd64g_dirtyhelper_OUT", 
16350              &amd64g_dirtyhelper_OUT,
16351              mkIRExprVec_3( mkexpr(t1),
16352                             widenUto64( getIRegRAX(sz) ), 
16353                             mkU64(sz) )
16354           );
16355       stmt( IRStmt_Dirty(d) );
16356       break;
16357    }
16358
16359    /* ------------------------ (Grp1 extensions) ---------- */
16360
16361    case 0x80: /* Grp1 Ib,Eb */
16362       if (haveF2orF3(pfx)) goto decode_failure;
16363       modrm = getUChar(delta);
16364       am_sz = lengthAMode(pfx,delta);
16365       sz    = 1;
16366       d_sz  = 1;
16367       d64   = getSDisp8(delta + am_sz);
16368       delta = dis_Grp1 ( vbi, pfx, delta, modrm, am_sz, d_sz, sz, d64 );
16369       break;
16370
16371    case 0x81: /* Grp1 Iv,Ev */
16372       if (haveF2orF3(pfx)) goto decode_failure;
16373       modrm = getUChar(delta);
16374       am_sz = lengthAMode(pfx,delta);
16375       d_sz  = imin(sz,4);
16376       d64   = getSDisp(d_sz, delta + am_sz);
16377       delta = dis_Grp1 ( vbi, pfx, delta, modrm, am_sz, d_sz, sz, d64 );
16378       break;
16379
16380    case 0x83: /* Grp1 Ib,Ev */
16381       if (haveF2orF3(pfx)) goto decode_failure;
16382       modrm = getUChar(delta);
16383       am_sz = lengthAMode(pfx,delta);
16384       d_sz  = 1;
16385       d64   = getSDisp8(delta + am_sz);
16386       delta = dis_Grp1 ( vbi, pfx, delta, modrm, am_sz, d_sz, sz, d64 );
16387       break;
16388
16389    /* ------------------------ (Grp2 extensions) ---------- */
16390
16391    case 0xC0: { /* Grp2 Ib,Eb */
16392       Bool decode_OK = True;
16393       if (haveF2orF3(pfx)) goto decode_failure;
16394       modrm = getUChar(delta);
16395       am_sz = lengthAMode(pfx,delta);
16396       d_sz  = 1;
16397       d64   = getUChar(delta + am_sz);
16398       sz    = 1;
16399       delta = dis_Grp2 ( vbi, pfx, delta, modrm, am_sz, d_sz, sz, 
16400                          mkU8(d64 & 0xFF), NULL, &decode_OK );
16401       if (!decode_OK) goto decode_failure;
16402       break;
16403    }
16404    case 0xC1: { /* Grp2 Ib,Ev */
16405       Bool decode_OK = True;
16406       if (haveF2orF3(pfx)) goto decode_failure;
16407       modrm = getUChar(delta);
16408       am_sz = lengthAMode(pfx,delta);
16409       d_sz  = 1;
16410       d64   = getUChar(delta + am_sz);
16411       delta = dis_Grp2 ( vbi, pfx, delta, modrm, am_sz, d_sz, sz, 
16412                          mkU8(d64 & 0xFF), NULL, &decode_OK );
16413       if (!decode_OK) goto decode_failure;
16414       break;
16415    }
16416    case 0xD0: { /* Grp2 1,Eb */
16417       Bool decode_OK = True;
16418       if (haveF2orF3(pfx)) goto decode_failure;
16419       modrm = getUChar(delta);
16420       am_sz = lengthAMode(pfx,delta);
16421       d_sz  = 0;
16422       d64   = 1;
16423       sz    = 1;
16424       delta = dis_Grp2 ( vbi, pfx, delta, modrm, am_sz, d_sz, sz, 
16425                          mkU8(d64), NULL, &decode_OK );
16426       if (!decode_OK) goto decode_failure;
16427       break;
16428    }
16429    case 0xD1: { /* Grp2 1,Ev */
16430       Bool decode_OK = True;
16431       if (haveF2orF3(pfx)) goto decode_failure;
16432       modrm = getUChar(delta);
16433       am_sz = lengthAMode(pfx,delta);
16434       d_sz  = 0;
16435       d64   = 1;
16436       delta = dis_Grp2 ( vbi, pfx, delta, modrm, am_sz, d_sz, sz, 
16437                          mkU8(d64), NULL, &decode_OK );
16438       if (!decode_OK) goto decode_failure;
16439       break;
16440    }
16441    case 0xD2: { /* Grp2 CL,Eb */
16442       Bool decode_OK = True;
16443       if (haveF2orF3(pfx)) goto decode_failure;
16444       modrm = getUChar(delta);
16445       am_sz = lengthAMode(pfx,delta);
16446       d_sz  = 0;
16447       sz    = 1;
16448       delta = dis_Grp2 ( vbi, pfx, delta, modrm, am_sz, d_sz, sz, 
16449                          getIRegCL(), "%cl", &decode_OK );
16450       if (!decode_OK) goto decode_failure;
16451       break;
16452    }
16453    case 0xD3: { /* Grp2 CL,Ev */
16454       Bool decode_OK = True;
16455       if (haveF2orF3(pfx)) goto decode_failure;
16456       modrm = getUChar(delta);
16457       am_sz = lengthAMode(pfx,delta);
16458       d_sz  = 0;
16459       delta = dis_Grp2 ( vbi, pfx, delta, modrm, am_sz, d_sz, sz, 
16460                          getIRegCL(), "%cl", &decode_OK );
16461       if (!decode_OK) goto decode_failure;
16462       break;
16463    }
16464
16465    /* ------------------------ (Grp3 extensions) ---------- */
16466
16467    case 0xF6: { /* Grp3 Eb */
16468       Bool decode_OK = True;
16469       if (haveF2orF3(pfx)) goto decode_failure;
16470       delta = dis_Grp3 ( vbi, pfx, 1, delta, &decode_OK );
16471       if (!decode_OK) goto decode_failure;
16472       break;
16473    }
16474    case 0xF7: { /* Grp3 Ev */
16475       Bool decode_OK = True;
16476       if (haveF2orF3(pfx)) goto decode_failure;
16477       delta = dis_Grp3 ( vbi, pfx, sz, delta, &decode_OK );
16478       if (!decode_OK) goto decode_failure;
16479       break;
16480    }
16481
16482    /* ------------------------ (Grp4 extensions) ---------- */
16483
16484    case 0xFE: { /* Grp4 Eb */
16485       Bool decode_OK = True;
16486       if (haveF2orF3(pfx)) goto decode_failure;
16487       delta = dis_Grp4 ( vbi, pfx, delta, &decode_OK );
16488       if (!decode_OK) goto decode_failure;
16489       break;
16490    }
16491
16492    /* ------------------------ (Grp5 extensions) ---------- */
16493
16494    case 0xFF: { /* Grp5 Ev */
16495       Bool decode_OK = True;
16496       if (haveF2orF3(pfx)) goto decode_failure;
16497       delta = dis_Grp5 ( vbi, pfx, sz, delta, &dres, &decode_OK );
16498       if (!decode_OK) goto decode_failure;
16499       break;
16500    }
16501
16502    /* ------------------------ Escapes to 2-byte opcodes -- */
16503
16504    case 0x0F: {
16505       opc = getUChar(delta); delta++;
16506       switch (opc) {
16507
16508       /* =-=-=-=-=-=-=-=-=- Grp8 =-=-=-=-=-=-=-=-=-=-=-= */
16509
16510       case 0xBA: { /* Grp8 Ib,Ev */
16511          Bool decode_OK = False;
16512          if (haveF2orF3(pfx)) goto decode_failure;
16513          modrm = getUChar(delta);
16514          am_sz = lengthAMode(pfx,delta);
16515          d64   = getSDisp8(delta + am_sz);
16516          delta = dis_Grp8_Imm ( vbi, pfx, delta, modrm, am_sz, sz, d64,
16517                                 &decode_OK );
16518          if (!decode_OK)
16519             goto decode_failure;
16520          break;
16521       }
16522
16523       /* =-=-=-=-=-=-=-=-=- BSF/BSR -=-=-=-=-=-=-=-=-=-= */
16524
16525       case 0xBC: /* BSF Gv,Ev */
16526          if (haveF2orF3(pfx)) goto decode_failure;
16527          delta = dis_bs_E_G ( vbi, pfx, sz, delta, True );
16528          break;
16529       case 0xBD: /* BSR Gv,Ev */
16530          if (haveF2orF3(pfx)) goto decode_failure;
16531          delta = dis_bs_E_G ( vbi, pfx, sz, delta, False );
16532          break;
16533
16534       /* =-=-=-=-=-=-=-=-=- BSWAP -=-=-=-=-=-=-=-=-=-=-= */
16535
16536       case 0xC8: /* BSWAP %eax */
16537       case 0xC9:
16538       case 0xCA:
16539       case 0xCB:
16540       case 0xCC:
16541       case 0xCD:
16542       case 0xCE:
16543       case 0xCF: /* BSWAP %edi */
16544          if (haveF2orF3(pfx)) goto decode_failure;
16545          /* According to the AMD64 docs, this insn can have size 4 or
16546             8. */
16547          if (sz == 4) {
16548             t1 = newTemp(Ity_I32);
16549             t2 = newTemp(Ity_I32);
16550             assign( t1, getIRegRexB(4, pfx, opc-0xC8) );
16551             assign( t2,
16552                binop(Iop_Or32,
16553                   binop(Iop_Shl32, mkexpr(t1), mkU8(24)),
16554                binop(Iop_Or32,
16555                   binop(Iop_And32, binop(Iop_Shl32, mkexpr(t1), mkU8(8)),
16556                                    mkU32(0x00FF0000)),
16557                binop(Iop_Or32,
16558                   binop(Iop_And32, binop(Iop_Shr32, mkexpr(t1), mkU8(8)),
16559                                    mkU32(0x0000FF00)),
16560                   binop(Iop_And32, binop(Iop_Shr32, mkexpr(t1), mkU8(24)),
16561                                    mkU32(0x000000FF) )
16562                )))
16563             );
16564             putIRegRexB(4, pfx, opc-0xC8, mkexpr(t2));
16565             DIP("bswapl %s\n", nameIRegRexB(4, pfx, opc-0xC8));
16566             break;
16567          }
16568          else if (sz == 8) {
16569             IRTemp m8  = newTemp(Ity_I64);
16570             IRTemp s8  = newTemp(Ity_I64);
16571             IRTemp m16 = newTemp(Ity_I64);
16572             IRTemp s16 = newTemp(Ity_I64);
16573             IRTemp m32 = newTemp(Ity_I64);
16574             t1 = newTemp(Ity_I64);
16575             t2 = newTemp(Ity_I64);
16576             assign( t1, getIRegRexB(8, pfx, opc-0xC8) );
16577
16578             assign( m8, mkU64(0xFF00FF00FF00FF00ULL) );
16579             assign( s8,
16580                     binop(Iop_Or64,
16581                           binop(Iop_Shr64,
16582                                 binop(Iop_And64,mkexpr(t1),mkexpr(m8)),
16583                                 mkU8(8)),
16584                           binop(Iop_And64,
16585                                 binop(Iop_Shl64,mkexpr(t1),mkU8(8)),
16586                                 mkexpr(m8))
16587                          ) 
16588                   );
16589
16590             assign( m16, mkU64(0xFFFF0000FFFF0000ULL) );
16591             assign( s16,
16592                     binop(Iop_Or64,
16593                           binop(Iop_Shr64,
16594                                 binop(Iop_And64,mkexpr(s8),mkexpr(m16)),
16595                                 mkU8(16)),
16596                           binop(Iop_And64,
16597                                 binop(Iop_Shl64,mkexpr(s8),mkU8(16)),
16598                                 mkexpr(m16))
16599                          ) 
16600                   );
16601
16602             assign( m32, mkU64(0xFFFFFFFF00000000ULL) );
16603             assign( t2,
16604                     binop(Iop_Or64,
16605                           binop(Iop_Shr64,
16606                                 binop(Iop_And64,mkexpr(s16),mkexpr(m32)),
16607                                 mkU8(32)),
16608                           binop(Iop_And64,
16609                                 binop(Iop_Shl64,mkexpr(s16),mkU8(32)),
16610                                 mkexpr(m32))
16611                          ) 
16612                   );
16613
16614             putIRegRexB(8, pfx, opc-0xC8, mkexpr(t2));
16615             DIP("bswapq %s\n", nameIRegRexB(8, pfx, opc-0xC8));
16616             break;
16617          } else {
16618             goto decode_failure;
16619          }
16620
16621       /* =-=-=-=-=-=-=-=-=- BT/BTS/BTR/BTC =-=-=-=-=-=-= */
16622
16623       /* All of these are possible at sizes 2, 4 and 8, but until a
16624          size 2 test case shows up, only handle sizes 4 and 8. */
16625
16626       case 0xA3: /* BT Gv,Ev */
16627          if (haveF2orF3(pfx)) goto decode_failure;
16628          if (sz != 8 && sz != 4 && sz != 2) goto decode_failure;
16629          delta = dis_bt_G_E ( vbi, pfx, sz, delta, BtOpNone );
16630          break;
16631       case 0xB3: /* BTR Gv,Ev */
16632          if (haveF2orF3(pfx)) goto decode_failure;
16633          if (sz != 8 && sz != 4 && sz != 2) goto decode_failure;
16634          delta = dis_bt_G_E ( vbi, pfx, sz, delta, BtOpReset );
16635          break;
16636       case 0xAB: /* BTS Gv,Ev */
16637          if (haveF2orF3(pfx)) goto decode_failure;
16638          if (sz != 8 && sz != 4 && sz != 2) goto decode_failure;
16639          delta = dis_bt_G_E ( vbi, pfx, sz, delta, BtOpSet );
16640          break;
16641       case 0xBB: /* BTC Gv,Ev */
16642          if (haveF2orF3(pfx)) goto decode_failure;
16643          if (sz != 8 && sz != 4 && sz != 2) goto decode_failure;
16644          delta = dis_bt_G_E ( vbi, pfx, sz, delta, BtOpComp );
16645          break;
16646
16647       /* =-=-=-=-=-=-=-=-=- CMOV =-=-=-=-=-=-=-=-=-=-=-= */
16648  
16649       case 0x40:
16650       case 0x41:
16651       case 0x42: /* CMOVBb/CMOVNAEb (cmov below) */
16652       case 0x43: /* CMOVNBb/CMOVAEb (cmov not below) */
16653       case 0x44: /* CMOVZb/CMOVEb (cmov zero) */
16654       case 0x45: /* CMOVNZb/CMOVNEb (cmov not zero) */
16655       case 0x46: /* CMOVBEb/CMOVNAb (cmov below or equal) */
16656       case 0x47: /* CMOVNBEb/CMOVAb (cmov not below or equal) */
16657       case 0x48: /* CMOVSb (cmov negative) */
16658       case 0x49: /* CMOVSb (cmov not negative) */
16659       case 0x4A: /* CMOVP (cmov parity even) */
16660       case 0x4B: /* CMOVNP (cmov parity odd) */
16661       case 0x4C: /* CMOVLb/CMOVNGEb (cmov less) */
16662       case 0x4D: /* CMOVGEb/CMOVNLb (cmov greater or equal) */
16663       case 0x4E: /* CMOVLEb/CMOVNGb (cmov less or equal) */
16664       case 0x4F: /* CMOVGb/CMOVNLEb (cmov greater) */
16665          if (haveF2orF3(pfx)) goto decode_failure;
16666          delta = dis_cmov_E_G(vbi, pfx, sz, (AMD64Condcode)(opc - 0x40), delta);
16667          break;
16668
16669       /* =-=-=-=-=-=-=-=-=- CMPXCHG -=-=-=-=-=-=-=-=-=-= */
16670
16671       case 0xB0: { /* CMPXCHG Gb,Eb */
16672          Bool ok = True;
16673          if (haveF2orF3(pfx)) goto decode_failure;
16674          delta = dis_cmpxchg_G_E ( &ok, vbi, pfx, 1, delta );
16675          if (!ok) goto decode_failure;
16676          break;
16677       }
16678       case 0xB1: { /* CMPXCHG Gv,Ev (allowed in 16,32,64 bit) */
16679          Bool ok = True;
16680          if (haveF2orF3(pfx)) goto decode_failure;
16681          if (sz != 2 && sz != 4 && sz != 8) goto decode_failure;
16682          delta = dis_cmpxchg_G_E ( &ok, vbi, pfx, sz, delta );
16683          if (!ok) goto decode_failure;
16684          break;
16685       }
16686
16687       case 0xC7: { /* CMPXCHG8B Ev, CMPXCHG16B Ev */
16688          IRType  elemTy     = sz==4 ? Ity_I32 : Ity_I64;
16689          IRTemp  expdHi     = newTemp(elemTy);
16690          IRTemp  expdLo     = newTemp(elemTy);
16691          IRTemp  dataHi     = newTemp(elemTy);
16692          IRTemp  dataLo     = newTemp(elemTy);
16693          IRTemp  oldHi      = newTemp(elemTy);
16694          IRTemp  oldLo      = newTemp(elemTy);
16695          IRTemp  flags_old  = newTemp(Ity_I64);
16696          IRTemp  flags_new  = newTemp(Ity_I64);
16697          IRTemp  success    = newTemp(Ity_I1);
16698          IROp    opOR       = sz==4 ? Iop_Or32    : Iop_Or64;
16699          IROp    opXOR      = sz==4 ? Iop_Xor32   : Iop_Xor64;
16700          IROp    opCasCmpEQ = sz==4 ? Iop_CasCmpEQ32 : Iop_CasCmpEQ64;
16701          IRExpr* zero       = sz==4 ? mkU32(0)    : mkU64(0);
16702          IRTemp expdHi64    = newTemp(Ity_I64);
16703          IRTemp expdLo64    = newTemp(Ity_I64);
16704
16705          /* Translate this using a DCAS, even if there is no LOCK
16706             prefix.  Life is too short to bother with generating two
16707             different translations for the with/without-LOCK-prefix
16708             cases. */
16709          *expect_CAS = True;
16710
16711          /* Decode, and generate address. */
16712          if (have66orF2orF3(pfx)) goto decode_failure;
16713          if (sz != 4 && sz != 8) goto decode_failure;
16714          if (sz == 8 && !(archinfo->hwcaps & VEX_HWCAPS_AMD64_CX16))
16715             goto decode_failure;
16716          modrm = getUChar(delta);
16717          if (epartIsReg(modrm)) goto decode_failure;
16718          if (gregLO3ofRM(modrm) != 1) goto decode_failure;
16719          addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
16720          delta += alen;
16721
16722          /* cmpxchg16b requires an alignment check. */
16723          if (sz == 8)
16724             gen_SEGV_if_not_16_aligned( addr );
16725
16726          /* Get the expected and new values. */
16727          assign( expdHi64, getIReg64(R_RDX) );
16728          assign( expdLo64, getIReg64(R_RAX) );
16729
16730          /* These are the correctly-sized expected and new values.
16731             However, we also get expdHi64/expdLo64 above as 64-bits
16732             regardless, because we will need them later in the 32-bit
16733             case (paradoxically). */
16734          assign( expdHi, sz==4 ? unop(Iop_64to32, mkexpr(expdHi64))
16735                                : mkexpr(expdHi64) );
16736          assign( expdLo, sz==4 ? unop(Iop_64to32, mkexpr(expdLo64))
16737                                : mkexpr(expdLo64) );
16738          assign( dataHi, sz==4 ? getIReg32(R_RCX) : getIReg64(R_RCX) );
16739          assign( dataLo, sz==4 ? getIReg32(R_RBX) : getIReg64(R_RBX) );
16740
16741          /* Do the DCAS */
16742          stmt( IRStmt_CAS(
16743                   mkIRCAS( oldHi, oldLo, 
16744                            Iend_LE, mkexpr(addr), 
16745                            mkexpr(expdHi), mkexpr(expdLo),
16746                            mkexpr(dataHi), mkexpr(dataLo)
16747                )));
16748
16749          /* success when oldHi:oldLo == expdHi:expdLo */
16750          assign( success,
16751                  binop(opCasCmpEQ,
16752                        binop(opOR,
16753                              binop(opXOR, mkexpr(oldHi), mkexpr(expdHi)),
16754                              binop(opXOR, mkexpr(oldLo), mkexpr(expdLo))
16755                        ),
16756                        zero
16757                  ));
16758
16759          /* If the DCAS is successful, that is to say oldHi:oldLo ==
16760             expdHi:expdLo, then put expdHi:expdLo back in RDX:RAX,
16761             which is where they came from originally.  Both the actual
16762             contents of these two regs, and any shadow values, are
16763             unchanged.  If the DCAS fails then we're putting into
16764             RDX:RAX the value seen in memory. */
16765          /* Now of course there's a complication in the 32-bit case
16766             (bah!): if the DCAS succeeds, we need to leave RDX:RAX
16767             unchanged; but if we use the same scheme as in the 64-bit
16768             case, we get hit by the standard rule that a write to the
16769             bottom 32 bits of an integer register zeros the upper 32
16770             bits.  And so the upper halves of RDX and RAX mysteriously
16771             become zero.  So we have to stuff back in the original
16772             64-bit values which we previously stashed in
16773             expdHi64:expdLo64, even if we're doing a cmpxchg8b. */
16774          /* It's just _so_ much fun ... */
16775          putIRegRDX( 8,
16776                      IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(success)),
16777                                    sz == 4 ? unop(Iop_32Uto64, mkexpr(oldHi))
16778                                            : mkexpr(oldHi),
16779                                    mkexpr(expdHi64)
16780                    ));
16781          putIRegRAX( 8,
16782                      IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(success)),
16783                                    sz == 4 ? unop(Iop_32Uto64, mkexpr(oldLo))
16784                                            : mkexpr(oldLo),
16785                                    mkexpr(expdLo64)
16786                    ));
16787
16788          /* Copy the success bit into the Z flag and leave the others
16789             unchanged */
16790          assign( flags_old, widenUto64(mk_amd64g_calculate_rflags_all()));
16791          assign( 
16792             flags_new,
16793             binop(Iop_Or64,
16794                   binop(Iop_And64, mkexpr(flags_old), 
16795                                    mkU64(~AMD64G_CC_MASK_Z)),
16796                   binop(Iop_Shl64,
16797                         binop(Iop_And64,
16798                               unop(Iop_1Uto64, mkexpr(success)), mkU64(1)), 
16799                         mkU8(AMD64G_CC_SHIFT_Z)) ));
16800
16801          stmt( IRStmt_Put( OFFB_CC_OP,   mkU64(AMD64G_CC_OP_COPY) ));
16802          stmt( IRStmt_Put( OFFB_CC_DEP1, mkexpr(flags_new) ));
16803          stmt( IRStmt_Put( OFFB_CC_DEP2, mkU64(0) ));
16804          /* Set NDEP even though it isn't used.  This makes
16805             redundant-PUT elimination of previous stores to this field
16806             work better. */
16807          stmt( IRStmt_Put( OFFB_CC_NDEP, mkU64(0) ));
16808
16809          /* Sheesh.  Aren't you glad it was me and not you that had to
16810             write and validate all this grunge? */
16811
16812          DIP("cmpxchg8b %s\n", dis_buf);
16813          break;
16814
16815       }
16816
16817       /* =-=-=-=-=-=-=-=-=- CPUID -=-=-=-=-=-=-=-=-=-=-= */
16818
16819       case 0xA2: { /* CPUID */
16820          /* Uses dirty helper: 
16821                void amd64g_dirtyhelper_CPUID ( VexGuestAMD64State* )
16822             declared to mod rax, wr rbx, rcx, rdx
16823          */
16824          IRDirty* d     = NULL;
16825          HChar*   fName = NULL;
16826          void*    fAddr = NULL;
16827          if (haveF2orF3(pfx)) goto decode_failure;
16828          if (archinfo->hwcaps == (VEX_HWCAPS_AMD64_SSE3
16829                                   |VEX_HWCAPS_AMD64_CX16)) {
16830             fName = "amd64g_dirtyhelper_CPUID_sse3_and_cx16";
16831             fAddr = &amd64g_dirtyhelper_CPUID_sse3_and_cx16; 
16832             /* This is a Core-2-like machine */
16833          }
16834          else {
16835             /* Give a CPUID for at least a baseline machine, no SSE2
16836                and no CX16 */
16837             fName = "amd64g_dirtyhelper_CPUID_baseline";
16838             fAddr = &amd64g_dirtyhelper_CPUID_baseline;
16839          }
16840
16841          vassert(fName); vassert(fAddr);
16842          d = unsafeIRDirty_0_N ( 0/*regparms*/, 
16843                                  fName, fAddr, mkIRExprVec_0() );
16844          /* declare guest state effects */
16845          d->needsBBP = True;
16846          d->nFxState = 4;
16847          d->fxState[0].fx     = Ifx_Modify;
16848          d->fxState[0].offset = OFFB_RAX;
16849          d->fxState[0].size   = 8;
16850          d->fxState[1].fx     = Ifx_Write;
16851          d->fxState[1].offset = OFFB_RBX;
16852          d->fxState[1].size   = 8;
16853          d->fxState[2].fx     = Ifx_Modify;
16854          d->fxState[2].offset = OFFB_RCX;
16855          d->fxState[2].size   = 8;
16856          d->fxState[3].fx     = Ifx_Write;
16857          d->fxState[3].offset = OFFB_RDX;
16858          d->fxState[3].size   = 8;
16859          /* execute the dirty call, side-effecting guest state */
16860          stmt( IRStmt_Dirty(d) );
16861          /* CPUID is a serialising insn.  So, just in case someone is
16862             using it as a memory fence ... */
16863          stmt( IRStmt_MBE(Imbe_Fence) );
16864          DIP("cpuid\n");
16865          break;
16866       }
16867
16868       /* =-=-=-=-=-=-=-=-=- MOVZX, MOVSX =-=-=-=-=-=-=-= */
16869
16870       case 0xB6: /* MOVZXb Eb,Gv */
16871          if (haveF2orF3(pfx)) goto decode_failure;
16872          if (sz != 2 && sz != 4 && sz != 8)
16873             goto decode_failure;
16874          delta = dis_movx_E_G ( vbi, pfx, delta, 1, sz, False );
16875          break;
16876       case 0xB7: /* MOVZXw Ew,Gv */
16877          if (haveF2orF3(pfx)) goto decode_failure;
16878          if (sz != 4 && sz != 8)
16879             goto decode_failure;
16880          delta = dis_movx_E_G ( vbi, pfx, delta, 2, sz, False );
16881          break;
16882
16883       case 0xBE: /* MOVSXb Eb,Gv */
16884          if (haveF2orF3(pfx)) goto decode_failure;
16885          if (sz != 2 && sz != 4 && sz != 8)
16886             goto decode_failure;
16887          delta = dis_movx_E_G ( vbi, pfx, delta, 1, sz, True );
16888          break;
16889       case 0xBF: /* MOVSXw Ew,Gv */
16890          if (haveF2orF3(pfx)) goto decode_failure;
16891          if (sz != 4 && sz != 8)
16892             goto decode_failure;
16893          delta = dis_movx_E_G ( vbi, pfx, delta, 2, sz, True );
16894          break;
16895
16896 //.. //--       /* =-=-=-=-=-=-=-=-=-=-= MOVNTI -=-=-=-=-=-=-=-=-= */
16897 //.. //-- 
16898 //.. //--       case 0xC3: /* MOVNTI Gv,Ev */
16899 //.. //--          vg_assert(sz == 4);
16900 //.. //--          modrm = getUChar(eip);
16901 //.. //--          vg_assert(!epartIsReg(modrm));
16902 //.. //--          t1 = newTemp(cb);
16903 //.. //--          uInstr2(cb, GET, 4, ArchReg, gregOfRM(modrm), TempReg, t1);
16904 //.. //--          pair = disAMode ( cb, sorb, eip, dis_buf );
16905 //.. //--          t2 = LOW24(pair);
16906 //.. //--          eip += HI8(pair);
16907 //.. //--          uInstr2(cb, STORE, 4, TempReg, t1, TempReg, t2);
16908 //.. //--          DIP("movnti %s,%s\n", nameIReg(4,gregOfRM(modrm)), dis_buf);
16909 //.. //--          break;
16910
16911       /* =-=-=-=-=-=-=-=-=- MUL/IMUL =-=-=-=-=-=-=-=-=-= */
16912
16913       case 0xAF: /* IMUL Ev, Gv */
16914          if (haveF2orF3(pfx)) goto decode_failure;
16915          delta = dis_mul_E_G ( vbi, pfx, sz, delta );
16916          break;
16917
16918       /* =-=-=-=-=-=-=-=-=- NOPs =-=-=-=-=-=-=-=-=-=-=-= */
16919
16920       case 0x1F:
16921          if (haveF2orF3(pfx)) goto decode_failure;
16922          modrm = getUChar(delta);
16923          if (epartIsReg(modrm)) goto decode_failure;
16924          addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
16925          delta += alen;
16926          DIP("nop%c %s\n", nameISize(sz), dis_buf);
16927          break;
16928
16929       /* =-=-=-=-=-=-=-=-=- Jcond d32 -=-=-=-=-=-=-=-=-= */
16930       case 0x80:
16931       case 0x81:
16932       case 0x82: /* JBb/JNAEb (jump below) */
16933       case 0x83: /* JNBb/JAEb (jump not below) */
16934       case 0x84: /* JZb/JEb (jump zero) */
16935       case 0x85: /* JNZb/JNEb (jump not zero) */
16936       case 0x86: /* JBEb/JNAb (jump below or equal) */
16937       case 0x87: /* JNBEb/JAb (jump not below or equal) */
16938       case 0x88: /* JSb (jump negative) */
16939       case 0x89: /* JSb (jump not negative) */
16940       case 0x8A: /* JP (jump parity even) */
16941       case 0x8B: /* JNP/JPO (jump parity odd) */
16942       case 0x8C: /* JLb/JNGEb (jump less) */
16943       case 0x8D: /* JGEb/JNLb (jump greater or equal) */
16944       case 0x8E: /* JLEb/JNGb (jump less or equal) */
16945       case 0x8F: /* JGb/JNLEb (jump greater) */
16946        { Long   jmpDelta;
16947          HChar* comment  = "";
16948          if (haveF2orF3(pfx)) goto decode_failure;
16949          jmpDelta = getSDisp32(delta);
16950          d64 = (guest_RIP_bbstart+delta+4) + jmpDelta;
16951          delta += 4;
16952          if (resteerCisOk
16953              && vex_control.guest_chase_cond
16954              && (Addr64)d64 != (Addr64)guest_RIP_bbstart
16955              && jmpDelta < 0
16956              && resteerOkFn( callback_opaque, d64) ) {
16957             /* Speculation: assume this backward branch is taken.  So
16958                we need to emit a side-exit to the insn following this
16959                one, on the negation of the condition, and continue at
16960                the branch target address (d64).  If we wind up back at
16961                the first instruction of the trace, just stop; it's
16962                better to let the IR loop unroller handle that case. */
16963             stmt( IRStmt_Exit( 
16964                      mk_amd64g_calculate_condition(
16965                         (AMD64Condcode)(1 ^ (opc - 0x80))),
16966                      Ijk_Boring,
16967                      IRConst_U64(guest_RIP_bbstart+delta) ) );
16968             dres.whatNext   = Dis_ResteerC;
16969             dres.continueAt = d64;
16970             comment = "(assumed taken)";
16971          }
16972          else
16973          if (resteerCisOk
16974              && vex_control.guest_chase_cond
16975              && (Addr64)d64 != (Addr64)guest_RIP_bbstart
16976              && jmpDelta >= 0
16977              && resteerOkFn( callback_opaque, guest_RIP_bbstart+delta ) ) {
16978             /* Speculation: assume this forward branch is not taken.
16979                So we need to emit a side-exit to d64 (the dest) and
16980                continue disassembling at the insn immediately
16981                following this one. */
16982             stmt( IRStmt_Exit( 
16983                      mk_amd64g_calculate_condition((AMD64Condcode)
16984                                                    (opc - 0x80)),
16985                      Ijk_Boring,
16986                      IRConst_U64(d64) ) );
16987             dres.whatNext   = Dis_ResteerC;
16988             dres.continueAt = guest_RIP_bbstart+delta;
16989             comment = "(assumed not taken)";
16990          }
16991          else {
16992             /* Conservative default translation - end the block at
16993                this point. */
16994          jcc_01( (AMD64Condcode)(opc - 0x80), 
16995                  guest_RIP_bbstart+delta, 
16996                  d64 );
16997          dres.whatNext = Dis_StopHere;
16998          }
16999          DIP("j%s-32 0x%llx %s\n", name_AMD64Condcode(opc - 0x80), d64, comment);
17000          break;
17001        }
17002
17003       /* =-=-=-=-=-=-=-=-=- PREFETCH =-=-=-=-=-=-=-=-=-= */
17004       case 0x0D: /* 0F 0D /0 -- prefetch mem8 */
17005                  /* 0F 0D /1 -- prefetchw mem8 */
17006          if (have66orF2orF3(pfx)) goto decode_failure;
17007          modrm = getUChar(delta);
17008          if (epartIsReg(modrm)) goto decode_failure;
17009          if (gregLO3ofRM(modrm) != 0 && gregLO3ofRM(modrm) != 1)
17010             goto decode_failure;
17011
17012          addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
17013          delta += alen;
17014
17015          switch (gregLO3ofRM(modrm)) {
17016             case 0: DIP("prefetch %s\n", dis_buf); break;
17017             case 1: DIP("prefetchw %s\n", dis_buf); break;
17018             default: vassert(0); /*NOTREACHED*/
17019          }
17020          break;
17021
17022       /* =-=-=-=-=-=-=-=-=- RDTSC -=-=-=-=-=-=-=-=-=-=-= */
17023       case 0x31: { /* RDTSC */
17024          IRTemp   val  = newTemp(Ity_I64);
17025          IRExpr** args = mkIRExprVec_0();
17026          IRDirty* d    = unsafeIRDirty_1_N ( 
17027                             val, 
17028                             0/*regparms*/, 
17029                             "amd64g_dirtyhelper_RDTSC", 
17030                             &amd64g_dirtyhelper_RDTSC, 
17031                             args 
17032                          );
17033          if (have66orF2orF3(pfx)) goto decode_failure;
17034          /* execute the dirty call, dumping the result in val. */
17035          stmt( IRStmt_Dirty(d) );
17036          putIRegRDX(4, unop(Iop_64HIto32, mkexpr(val)));
17037          putIRegRAX(4, unop(Iop_64to32, mkexpr(val)));
17038          DIP("rdtsc\n");
17039          break;
17040       }
17041
17042 //..       /* =-=-=-=-=-=-=-=-=- PUSH/POP Sreg =-=-=-=-=-=-=-=-=-= */
17043 //.. 
17044 //..       case 0xA1: /* POP %FS */
17045 //..          dis_pop_segreg( R_FS, sz ); break;
17046 //..       case 0xA9: /* POP %GS */
17047 //..          dis_pop_segreg( R_GS, sz ); break;
17048 //.. 
17049 //..       case 0xA0: /* PUSH %FS */
17050 //..          dis_push_segreg( R_FS, sz ); break;
17051 //..       case 0xA8: /* PUSH %GS */
17052 //..          dis_push_segreg( R_GS, sz ); break;
17053
17054       /* =-=-=-=-=-=-=-=-=- SETcc Eb =-=-=-=-=-=-=-=-=-= */
17055       case 0x90:
17056       case 0x91:
17057       case 0x92: /* set-Bb/set-NAEb (set if below) */
17058       case 0x93: /* set-NBb/set-AEb (set if not below) */
17059       case 0x94: /* set-Zb/set-Eb (set if zero) */
17060       case 0x95: /* set-NZb/set-NEb (set if not zero) */
17061       case 0x96: /* set-BEb/set-NAb (set if below or equal) */
17062       case 0x97: /* set-NBEb/set-Ab (set if not below or equal) */
17063       case 0x98: /* set-Sb (set if negative) */
17064       case 0x99: /* set-Sb (set if not negative) */
17065       case 0x9A: /* set-P (set if parity even) */
17066       case 0x9B: /* set-NP (set if parity odd) */
17067       case 0x9C: /* set-Lb/set-NGEb (set if less) */
17068       case 0x9D: /* set-GEb/set-NLb (set if greater or equal) */
17069       case 0x9E: /* set-LEb/set-NGb (set if less or equal) */
17070       case 0x9F: /* set-Gb/set-NLEb (set if greater) */
17071          if (haveF2orF3(pfx)) goto decode_failure;
17072          t1 = newTemp(Ity_I8);
17073          assign( t1, unop(Iop_1Uto8,mk_amd64g_calculate_condition(opc-0x90)) );
17074          modrm = getUChar(delta);
17075          if (epartIsReg(modrm)) {
17076             delta++;
17077             putIRegE(1, pfx, modrm, mkexpr(t1));
17078             DIP("set%s %s\n", name_AMD64Condcode(opc-0x90), 
17079                               nameIRegE(1,pfx,modrm));
17080          } else {
17081             addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
17082             delta += alen;
17083             storeLE( mkexpr(addr), mkexpr(t1) );
17084             DIP("set%s %s\n", name_AMD64Condcode(opc-0x90), dis_buf);
17085          }
17086          break;
17087
17088       /* =-=-=-=-=-=-=-=-=- SHLD/SHRD -=-=-=-=-=-=-=-=-= */
17089
17090       case 0xA4: /* SHLDv imm8,Gv,Ev */
17091          modrm = getUChar(delta);
17092          d64   = delta + lengthAMode(pfx, delta);
17093          vex_sprintf(dis_buf, "$%d", (Int)getUChar(d64));
17094          delta = dis_SHLRD_Gv_Ev ( 
17095                     vbi, pfx, delta, modrm, sz, 
17096                     mkU8(getUChar(d64)), True, /* literal */
17097                     dis_buf, True /* left */ );
17098          break;
17099       case 0xA5: /* SHLDv %cl,Gv,Ev */
17100          modrm = getUChar(delta);
17101          delta = dis_SHLRD_Gv_Ev ( 
17102                     vbi, pfx, delta, modrm, sz,
17103                     getIRegCL(), False, /* not literal */
17104                     "%cl", True /* left */ );
17105          break;
17106
17107       case 0xAC: /* SHRDv imm8,Gv,Ev */
17108          modrm = getUChar(delta);
17109          d64   = delta + lengthAMode(pfx, delta);
17110          vex_sprintf(dis_buf, "$%d", (Int)getUChar(d64));
17111          delta = dis_SHLRD_Gv_Ev ( 
17112                     vbi, pfx, delta, modrm, sz, 
17113                     mkU8(getUChar(d64)), True, /* literal */
17114                     dis_buf, False /* right */ );
17115          break;
17116       case 0xAD: /* SHRDv %cl,Gv,Ev */
17117          modrm = getUChar(delta);
17118          delta = dis_SHLRD_Gv_Ev ( 
17119                     vbi, pfx, delta, modrm, sz, 
17120                     getIRegCL(), False, /* not literal */
17121                     "%cl", False /* right */);
17122          break;
17123
17124       /* =-=-=-=-=-=-=-=-=- SYSCALL -=-=-=-=-=-=-=-=-=-= */
17125       case 0x05: /* SYSCALL */
17126          guest_RIP_next_mustcheck = True;
17127          guest_RIP_next_assumed = guest_RIP_bbstart + delta;
17128          putIReg64( R_RCX, mkU64(guest_RIP_next_assumed) );
17129          /* It's important that all guest state is up-to-date
17130             at this point.  So we declare an end-of-block here, which
17131             forces any cached guest state to be flushed. */
17132          jmp_lit(Ijk_Sys_syscall, guest_RIP_next_assumed);
17133          dres.whatNext = Dis_StopHere;
17134          DIP("syscall\n");
17135          break;
17136
17137       /* =-=-=-=-=-=-=-=-=- XADD -=-=-=-=-=-=-=-=-=-= */
17138
17139       case 0xC0: { /* XADD Gb,Eb */ 
17140          Bool decode_OK = False;
17141          delta = dis_xadd_G_E ( &decode_OK, vbi, pfx, 1, delta );
17142          if (!decode_OK)
17143             goto decode_failure;
17144          break;
17145       }
17146       case 0xC1: { /* XADD Gv,Ev */ 
17147          Bool decode_OK = False;
17148          delta = dis_xadd_G_E ( &decode_OK, vbi, pfx, sz, delta );
17149          if (!decode_OK)
17150             goto decode_failure;
17151          break;
17152       }
17153
17154       /* =-=-=-=-=-=-=-=-=- MMXery =-=-=-=-=-=-=-=-=-=-= */
17155
17156       case 0x71: 
17157       case 0x72: 
17158       case 0x73: /* PSLLgg/PSRAgg/PSRLgg mmxreg by imm8 */
17159
17160       case 0x6E: /* MOVD (src)ireg-or-mem, (dst)mmxreg */
17161       case 0x7E: /* MOVD (src)mmxreg, (dst)ireg-or-mem */
17162       case 0x7F: /* MOVQ (src)mmxreg, (dst)mmxreg-or-mem */
17163       case 0x6F: /* MOVQ (src)mmxreg-or-mem, (dst)mmxreg */
17164
17165       case 0xFC: 
17166       case 0xFD: 
17167       case 0xFE: /* PADDgg (src)mmxreg-or-mem, (dst)mmxreg */
17168
17169       case 0xEC: 
17170       case 0xED: /* PADDSgg (src)mmxreg-or-mem, (dst)mmxreg */
17171
17172       case 0xDC:
17173       case 0xDD: /* PADDUSgg (src)mmxreg-or-mem, (dst)mmxreg */
17174
17175       case 0xF8: 
17176       case 0xF9: 
17177       case 0xFA: /* PSUBgg (src)mmxreg-or-mem, (dst)mmxreg */
17178
17179       case 0xE8: 
17180       case 0xE9: /* PSUBSgg (src)mmxreg-or-mem, (dst)mmxreg */
17181
17182       case 0xD8: 
17183       case 0xD9: /* PSUBUSgg (src)mmxreg-or-mem, (dst)mmxreg */
17184
17185       case 0xE5: /* PMULHW (src)mmxreg-or-mem, (dst)mmxreg */
17186       case 0xD5: /* PMULLW (src)mmxreg-or-mem, (dst)mmxreg */
17187
17188       case 0xF5: /* PMADDWD (src)mmxreg-or-mem, (dst)mmxreg */
17189
17190       case 0x74: 
17191       case 0x75: 
17192       case 0x76: /* PCMPEQgg (src)mmxreg-or-mem, (dst)mmxreg */
17193
17194       case 0x64: 
17195       case 0x65: 
17196       case 0x66: /* PCMPGTgg (src)mmxreg-or-mem, (dst)mmxreg */
17197
17198       case 0x6B: /* PACKSSDW (src)mmxreg-or-mem, (dst)mmxreg */
17199       case 0x63: /* PACKSSWB (src)mmxreg-or-mem, (dst)mmxreg */
17200       case 0x67: /* PACKUSWB (src)mmxreg-or-mem, (dst)mmxreg */
17201
17202       case 0x68: 
17203       case 0x69: 
17204       case 0x6A: /* PUNPCKHgg (src)mmxreg-or-mem, (dst)mmxreg */
17205
17206       case 0x60: 
17207       case 0x61: 
17208       case 0x62: /* PUNPCKLgg (src)mmxreg-or-mem, (dst)mmxreg */
17209
17210       case 0xDB: /* PAND (src)mmxreg-or-mem, (dst)mmxreg */
17211       case 0xDF: /* PANDN (src)mmxreg-or-mem, (dst)mmxreg */
17212       case 0xEB: /* POR (src)mmxreg-or-mem, (dst)mmxreg */
17213       case 0xEF: /* PXOR (src)mmxreg-or-mem, (dst)mmxreg */
17214
17215       case 0xF1: /* PSLLgg (src)mmxreg-or-mem, (dst)mmxreg */
17216       case 0xF2: 
17217       case 0xF3: 
17218
17219       case 0xD1: /* PSRLgg (src)mmxreg-or-mem, (dst)mmxreg */
17220       case 0xD2: 
17221       case 0xD3: 
17222
17223       case 0xE1: /* PSRAgg (src)mmxreg-or-mem, (dst)mmxreg */
17224       case 0xE2: 
17225       {
17226          Long delta0    = delta-1;
17227          Bool decode_OK = False;
17228
17229          /* If sz==2 this is SSE, and we assume sse idec has
17230             already spotted those cases by now. */
17231          if (sz != 4 && sz != 8)
17232             goto decode_failure;
17233          if (have66orF2orF3(pfx))
17234             goto decode_failure;
17235
17236          delta = dis_MMX ( &decode_OK, vbi, pfx, sz, delta-1 );
17237          if (!decode_OK) {
17238             delta = delta0;
17239             goto decode_failure;
17240          }
17241          break;
17242       }
17243
17244       case 0x0E: /* FEMMS */
17245       case 0x77: /* EMMS */
17246          if (sz != 4)
17247             goto decode_failure;
17248          do_EMMS_preamble();
17249          DIP("{f}emms\n");
17250          break;
17251
17252       /* =-=-=-=-=-=-=-=-=- unimp2 =-=-=-=-=-=-=-=-=-=-= */
17253
17254       default:
17255          goto decode_failure;
17256    } /* switch (opc) for the 2-byte opcodes */
17257    goto decode_success;
17258    } /* case 0x0F: of primary opcode */
17259
17260    /* ------------------------ ??? ------------------------ */
17261   
17262   default:
17263   decode_failure:
17264    /* All decode failures end up here. */
17265    vex_printf("vex amd64->IR: unhandled instruction bytes: "
17266               "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
17267               (Int)getUChar(delta_start+0),
17268               (Int)getUChar(delta_start+1),
17269               (Int)getUChar(delta_start+2),
17270               (Int)getUChar(delta_start+3),
17271               (Int)getUChar(delta_start+4),
17272               (Int)getUChar(delta_start+5) );
17273
17274    /* Tell the dispatcher that this insn cannot be decoded, and so has
17275       not been executed, and (is currently) the next to be executed.
17276       RIP should be up-to-date since it made so at the start of each
17277       insn, but nevertheless be paranoid and update it again right
17278       now. */
17279    stmt( IRStmt_Put( OFFB_RIP, mkU64(guest_RIP_curr_instr) ) );
17280    jmp_lit(Ijk_NoDecode, guest_RIP_curr_instr);
17281    dres.whatNext = Dis_StopHere;
17282    dres.len      = 0;
17283    /* We also need to say that a CAS is not expected now, regardless
17284       of what it might have been set to at the start of the function,
17285       since the IR that we've emitted just above (to synthesis a
17286       SIGILL) does not involve any CAS, and presumably no other IR has
17287       been emitted for this (non-decoded) insn. */
17288    *expect_CAS = False;
17289    return dres;
17290
17291    } /* switch (opc) for the main (primary) opcode switch. */
17292
17293   decode_success:
17294    /* All decode successes end up here. */
17295    DIP("\n");
17296    dres.len = (Int)toUInt(delta - delta_start);
17297    return dres;
17298 }
17299
17300 #undef DIP
17301 #undef DIS
17302
17303
17304 /*------------------------------------------------------------*/
17305 /*--- Top-level fn                                         ---*/
17306 /*------------------------------------------------------------*/
17307
17308 /* Disassemble a single instruction into IR.  The instruction
17309    is located in host memory at &guest_code[delta]. */
17310
17311 DisResult disInstr_AMD64 ( IRSB*        irsb_IN,
17312                            Bool         put_IP,
17313                            Bool         (*resteerOkFn) ( void*, Addr64 ),
17314                            Bool         resteerCisOk,
17315                            void*        callback_opaque,
17316                            UChar*       guest_code_IN,
17317                            Long         delta,
17318                            Addr64       guest_IP,
17319                            VexArch      guest_arch,
17320                            VexArchInfo* archinfo,
17321                            VexAbiInfo*  abiinfo,
17322                            Bool         host_bigendian_IN )
17323 {
17324    Int       i, x1, x2;
17325    Bool      expect_CAS, has_CAS;
17326    DisResult dres;
17327
17328    /* Set globals (see top of this file) */
17329    vassert(guest_arch == VexArchAMD64);
17330    guest_code           = guest_code_IN;
17331    irsb                 = irsb_IN;
17332    host_is_bigendian    = host_bigendian_IN;
17333    guest_RIP_curr_instr = guest_IP;
17334    guest_RIP_bbstart    = guest_IP - delta;
17335
17336    /* We'll consult these after doing disInstr_AMD64_WRK. */
17337    guest_RIP_next_assumed   = 0;
17338    guest_RIP_next_mustcheck = False;
17339
17340    x1 = irsb_IN->stmts_used;
17341    expect_CAS = False;
17342    dres = disInstr_AMD64_WRK ( &expect_CAS, put_IP, resteerOkFn,
17343                                resteerCisOk,
17344                                callback_opaque,
17345                                delta, archinfo, abiinfo );
17346    x2 = irsb_IN->stmts_used;
17347    vassert(x2 >= x1);
17348
17349    /* If disInstr_AMD64_WRK tried to figure out the next rip, check it
17350       got it right.  Failure of this assertion is serious and denotes
17351       a bug in disInstr. */
17352    if (guest_RIP_next_mustcheck 
17353        && guest_RIP_next_assumed != guest_RIP_curr_instr + dres.len) {
17354       vex_printf("\n");
17355       vex_printf("assumed next %%rip = 0x%llx\n", 
17356                  guest_RIP_next_assumed );
17357       vex_printf(" actual next %%rip = 0x%llx\n", 
17358                  guest_RIP_curr_instr + dres.len );
17359       vpanic("disInstr_AMD64: disInstr miscalculated next %rip");
17360    }
17361
17362    /* See comment at the top of disInstr_AMD64_WRK for meaning of
17363       expect_CAS.  Here, we (sanity-)check for the presence/absence of
17364       IRCAS as directed by the returned expect_CAS value. */
17365    has_CAS = False;
17366    for (i = x1; i < x2; i++) {
17367       if (irsb_IN->stmts[i]->tag == Ist_CAS)
17368          has_CAS = True;
17369    }
17370
17371    if (expect_CAS != has_CAS) {
17372       /* inconsistency detected.  re-disassemble the instruction so as
17373          to generate a useful error message; then assert. */
17374       vex_traceflags |= VEX_TRACE_FE;
17375       dres = disInstr_AMD64_WRK ( &expect_CAS, put_IP, resteerOkFn,
17376                                   resteerCisOk,
17377                                   callback_opaque,
17378                                   delta, archinfo, abiinfo );
17379       for (i = x1; i < x2; i++) {
17380          vex_printf("\t\t");
17381          ppIRStmt(irsb_IN->stmts[i]);
17382          vex_printf("\n");
17383       }
17384       /* Failure of this assertion is serious and denotes a bug in
17385          disInstr. */
17386       vpanic("disInstr_AMD64: inconsistency in LOCK prefix handling");
17387    }
17388
17389    return dres;
17390 }
17391
17392
17393
17394 /*--------------------------------------------------------------------*/
17395 /*--- end                                       guest_amd64_toIR.c ---*/
17396 /*--------------------------------------------------------------------*/