]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/valgrind/src/valgrind-3.6.0-svn/VEX/priv/guest_x86_toIR.c
update
[l4.git] / l4 / pkg / valgrind / src / valgrind-3.6.0-svn / VEX / priv / guest_x86_toIR.c
1
2 /*--------------------------------------------------------------------*/
3 /*--- begin                                       guest_x86_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 x86 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 32-bit value is being written.
42
43    FUCOMI(P): what happens to A and S flags?  Currently are forced
44       to zero.
45
46    x87 FP Limitations:
47
48    * all arithmetic done at 64 bits
49
50    * no FP exceptions, except for handling stack over/underflow
51
52    * FP rounding mode observed only for float->int conversions
53      and int->float conversions which could lose accuracy, and
54      for float-to-float rounding.  For all other operations, 
55      round-to-nearest is used, regardless.
56
57    * FP sin/cos/tan/sincos: C2 flag is always cleared.  IOW the
58      simulation claims the argument is in-range (-2^63 <= arg <= 2^63)
59      even when it isn't.
60
61    * some of the FCOM cases could do with testing -- not convinced
62      that the args are the right way round.
63
64    * FSAVE does not re-initialise the FPU; it should do
65
66    * FINIT not only initialises the FPU environment, it also
67      zeroes all the FP registers.  It should leave the registers
68      unchanged.
69
70    SAHF should cause eflags[1] == 1, and in fact it produces 0.  As
71    per Intel docs this bit has no meaning anyway.  Since PUSHF is the
72    only way to observe eflags[1], a proper fix would be to make that
73    bit be set by PUSHF.
74
75    The state of %eflags.AC (alignment check, bit 18) is recorded by
76    the simulation (viz, if you set it with popf then a pushf produces
77    the value you set it to), but it is otherwise ignored.  In
78    particular, setting it to 1 does NOT cause alignment checking to
79    happen.  Programs that set it to 1 and then rely on the resulting
80    SIGBUSs to inform them of misaligned accesses will not work.
81
82    Implementation of sysenter is necessarily partial.  sysenter is a
83    kind of system call entry.  When doing a sysenter, the return
84    address is not known -- that is something that is beyond Vex's
85    knowledge.  So the generated IR forces a return to the scheduler,
86    which can do what it likes to simulate the systenter, but it MUST
87    set this thread's guest_EIP field with the continuation address
88    before resuming execution.  If that doesn't happen, the thread will
89    jump to address zero, which is probably fatal.
90
91    This module uses global variables and so is not MT-safe (if that
92    should ever become relevant).
93
94    The delta values are 32-bit ints, not 64-bit ints.  That means
95    this module may not work right if run on a 64-bit host.  That should
96    be fixed properly, really -- if anyone ever wants to use Vex to
97    translate x86 code for execution on a 64-bit host.
98
99    casLE (implementation of lock-prefixed insns) and rep-prefixed
100    insns: the side-exit back to the start of the insn is done with
101    Ijk_Boring.  This is quite wrong, it should be done with
102    Ijk_NoRedir, since otherwise the side exit, which is intended to
103    restart the instruction for whatever reason, could go somewhere
104    entirely else.  Doing it right (with Ijk_NoRedir jumps) would make
105    no-redir jumps performance critical, at least for rep-prefixed
106    instructions, since all iterations thereof would involve such a
107    jump.  It's not such a big deal with casLE since the side exit is
108    only taken if the CAS fails, that is, the location is contended,
109    which is relatively unlikely.
110
111    XXXX: Nov 2009: handling of SWP on ARM suffers from the same
112    problem.
113
114    Note also, the test for CAS success vs failure is done using
115    Iop_CasCmp{EQ,NE}{8,16,32,64} rather than the ordinary
116    Iop_Cmp{EQ,NE} equivalents.  This is so as to tell Memcheck that it
117    shouldn't definedness-check these comparisons.  See
118    COMMENT_ON_CasCmpEQ in memcheck/mc_translate.c for
119    background/rationale.
120 */
121
122 /* Performance holes:
123
124    - fcom ; fstsw %ax ; sahf
125      sahf does not update the O flag (sigh) and so O needs to
126      be computed.  This is done expensively; it would be better
127      to have a calculate_eflags_o helper.
128
129    - emwarns; some FP codes can generate huge numbers of these
130      if the fpucw is changed in an inner loop.  It would be
131      better for the guest state to have an emwarn-enable reg
132      which can be set zero or nonzero.  If it is zero, emwarns
133      are not flagged, and instead control just flows all the
134      way through bbs as usual.
135 */
136
137 /* "Special" instructions.
138
139    This instruction decoder can decode three special instructions
140    which mean nothing natively (are no-ops as far as regs/mem are
141    concerned) but have meaning for supporting Valgrind.  A special
142    instruction is flagged by the 12-byte preamble C1C703 C1C70D C1C71D
143    C1C713 (in the standard interpretation, that means: roll $3, %edi;
144    roll $13, %edi; roll $29, %edi; roll $19, %edi).  Following that,
145    one of the following 3 are allowed (standard interpretation in
146    parentheses):
147
148       87DB (xchgl %ebx,%ebx)   %EDX = client_request ( %EAX )
149       87C9 (xchgl %ecx,%ecx)   %EAX = guest_NRADDR
150       87D2 (xchgl %edx,%edx)   call-noredir *%EAX
151
152    Any other bytes following the 12-byte preamble are illegal and
153    constitute a failure in instruction decoding.  This all assumes
154    that the preamble will never occur except in specific code
155    fragments designed for Valgrind to catch.
156
157    No prefixes may precede a "Special" instruction.
158 */
159
160 /* LOCK prefixed instructions.  These are translated using IR-level
161    CAS statements (IRCAS) and are believed to preserve atomicity, even
162    from the point of view of some other process racing against a
163    simulated one (presumably they communicate via a shared memory
164    segment).
165
166    Handlers which are aware of LOCK prefixes are:
167       dis_op2_G_E      (add, or, adc, sbb, and, sub, xor)
168       dis_cmpxchg_G_E  (cmpxchg)
169       dis_Grp1         (add, or, adc, sbb, and, sub, xor)
170       dis_Grp3         (not, neg)
171       dis_Grp4         (inc, dec)
172       dis_Grp5         (inc, dec)
173       dis_Grp8_Imm     (bts, btc, btr)
174       dis_bt_G_E       (bts, btc, btr)
175       dis_xadd_G_E     (xadd)
176 */
177
178
179 #include "libvex_basictypes.h"
180 #include "libvex_ir.h"
181 #include "libvex.h"
182 #include "libvex_guest_x86.h"
183
184 #include "main_util.h"
185 #include "main_globals.h"
186 #include "guest_generic_bb_to_IR.h"
187 #include "guest_generic_x87.h"
188 #include "guest_x86_defs.h"
189
190
191 /*------------------------------------------------------------*/
192 /*--- Globals                                              ---*/
193 /*------------------------------------------------------------*/
194
195 /* These are set at the start of the translation of an insn, right
196    down in disInstr_X86, so that we don't have to pass them around
197    endlessly.  They are all constant during the translation of any
198    given insn. */
199
200 /* We need to know this to do sub-register accesses correctly. */
201 static Bool host_is_bigendian;
202
203 /* Pointer to the guest code area (points to start of BB, not to the
204    insn being processed). */
205 static UChar* guest_code;
206
207 /* The guest address corresponding to guest_code[0]. */
208 static Addr32 guest_EIP_bbstart;
209
210 /* The guest address for the instruction currently being
211    translated. */
212 static Addr32 guest_EIP_curr_instr;
213
214 /* The IRSB* into which we're generating code. */
215 static IRSB* irsb;
216
217
218 /*------------------------------------------------------------*/
219 /*--- Debugging output                                     ---*/
220 /*------------------------------------------------------------*/
221
222 #define DIP(format, args...)           \
223    if (vex_traceflags & VEX_TRACE_FE)  \
224       vex_printf(format, ## args)
225
226 #define DIS(buf, format, args...)      \
227    if (vex_traceflags & VEX_TRACE_FE)  \
228       vex_sprintf(buf, format, ## args)
229
230
231 /*------------------------------------------------------------*/
232 /*--- Offsets of various parts of the x86 guest state.     ---*/
233 /*------------------------------------------------------------*/
234
235 #define OFFB_EAX       offsetof(VexGuestX86State,guest_EAX)
236 #define OFFB_EBX       offsetof(VexGuestX86State,guest_EBX)
237 #define OFFB_ECX       offsetof(VexGuestX86State,guest_ECX)
238 #define OFFB_EDX       offsetof(VexGuestX86State,guest_EDX)
239 #define OFFB_ESP       offsetof(VexGuestX86State,guest_ESP)
240 #define OFFB_EBP       offsetof(VexGuestX86State,guest_EBP)
241 #define OFFB_ESI       offsetof(VexGuestX86State,guest_ESI)
242 #define OFFB_EDI       offsetof(VexGuestX86State,guest_EDI)
243
244 #define OFFB_EIP       offsetof(VexGuestX86State,guest_EIP)
245
246 #define OFFB_CC_OP     offsetof(VexGuestX86State,guest_CC_OP)
247 #define OFFB_CC_DEP1   offsetof(VexGuestX86State,guest_CC_DEP1)
248 #define OFFB_CC_DEP2   offsetof(VexGuestX86State,guest_CC_DEP2)
249 #define OFFB_CC_NDEP   offsetof(VexGuestX86State,guest_CC_NDEP)
250
251 #define OFFB_FPREGS    offsetof(VexGuestX86State,guest_FPREG[0])
252 #define OFFB_FPTAGS    offsetof(VexGuestX86State,guest_FPTAG[0])
253 #define OFFB_DFLAG     offsetof(VexGuestX86State,guest_DFLAG)
254 #define OFFB_IDFLAG    offsetof(VexGuestX86State,guest_IDFLAG)
255 #define OFFB_ACFLAG    offsetof(VexGuestX86State,guest_ACFLAG)
256 #define OFFB_FTOP      offsetof(VexGuestX86State,guest_FTOP)
257 #define OFFB_FC3210    offsetof(VexGuestX86State,guest_FC3210)
258 #define OFFB_FPROUND   offsetof(VexGuestX86State,guest_FPROUND)
259
260 #define OFFB_CS        offsetof(VexGuestX86State,guest_CS)
261 #define OFFB_DS        offsetof(VexGuestX86State,guest_DS)
262 #define OFFB_ES        offsetof(VexGuestX86State,guest_ES)
263 #define OFFB_FS        offsetof(VexGuestX86State,guest_FS)
264 #define OFFB_GS        offsetof(VexGuestX86State,guest_GS)
265 #define OFFB_SS        offsetof(VexGuestX86State,guest_SS)
266 #define OFFB_LDT       offsetof(VexGuestX86State,guest_LDT)
267 #define OFFB_GDT       offsetof(VexGuestX86State,guest_GDT)
268
269 #define OFFB_SSEROUND  offsetof(VexGuestX86State,guest_SSEROUND)
270 #define OFFB_XMM0      offsetof(VexGuestX86State,guest_XMM0)
271 #define OFFB_XMM1      offsetof(VexGuestX86State,guest_XMM1)
272 #define OFFB_XMM2      offsetof(VexGuestX86State,guest_XMM2)
273 #define OFFB_XMM3      offsetof(VexGuestX86State,guest_XMM3)
274 #define OFFB_XMM4      offsetof(VexGuestX86State,guest_XMM4)
275 #define OFFB_XMM5      offsetof(VexGuestX86State,guest_XMM5)
276 #define OFFB_XMM6      offsetof(VexGuestX86State,guest_XMM6)
277 #define OFFB_XMM7      offsetof(VexGuestX86State,guest_XMM7)
278
279 #define OFFB_EMWARN    offsetof(VexGuestX86State,guest_EMWARN)
280
281 #define OFFB_TISTART   offsetof(VexGuestX86State,guest_TISTART)
282 #define OFFB_TILEN     offsetof(VexGuestX86State,guest_TILEN)
283 #define OFFB_NRADDR    offsetof(VexGuestX86State,guest_NRADDR)
284
285 #define OFFB_IP_AT_SYSCALL offsetof(VexGuestX86State,guest_IP_AT_SYSCALL)
286
287
288 /*------------------------------------------------------------*/
289 /*--- Helper bits and pieces for deconstructing the        ---*/
290 /*--- x86 insn stream.                                     ---*/
291 /*------------------------------------------------------------*/
292
293 /* This is the Intel register encoding -- integer regs. */
294 #define R_EAX 0
295 #define R_ECX 1
296 #define R_EDX 2
297 #define R_EBX 3
298 #define R_ESP 4
299 #define R_EBP 5
300 #define R_ESI 6
301 #define R_EDI 7
302
303 #define R_AL (0+R_EAX)
304 #define R_AH (4+R_EAX)
305
306 /* This is the Intel register encoding -- segment regs. */
307 #define R_ES 0
308 #define R_CS 1
309 #define R_SS 2
310 #define R_DS 3
311 #define R_FS 4
312 #define R_GS 5
313
314
315 /* Add a statement to the list held by "irbb". */
316 static void stmt ( IRStmt* st )
317 {
318    addStmtToIRSB( irsb, st );
319 }
320
321 /* Generate a new temporary of the given type. */
322 static IRTemp newTemp ( IRType ty )
323 {
324    vassert(isPlausibleIRType(ty));
325    return newIRTemp( irsb->tyenv, ty );
326 }
327
328 /* Various simple conversions */
329
330 static UInt extend_s_8to32( UInt x )
331 {
332    return (UInt)((((Int)x) << 24) >> 24);
333 }
334
335 static UInt extend_s_16to32 ( UInt x )
336 {
337    return (UInt)((((Int)x) << 16) >> 16);
338 }
339
340 /* Fetch a byte from the guest insn stream. */
341 static UChar getIByte ( Int delta )
342 {
343    return guest_code[delta];
344 }
345
346 /* Extract the reg field from a modRM byte. */
347 static Int gregOfRM ( UChar mod_reg_rm )
348 {
349    return (Int)( (mod_reg_rm >> 3) & 7 );
350 }
351
352 /* Figure out whether the mod and rm parts of a modRM byte refer to a
353    register or memory.  If so, the byte will have the form 11XXXYYY,
354    where YYY is the register number. */
355 static Bool epartIsReg ( UChar mod_reg_rm )
356 {
357    return toBool(0xC0 == (mod_reg_rm & 0xC0));
358 }
359
360 /* ... and extract the register number ... */
361 static Int eregOfRM ( UChar mod_reg_rm )
362 {
363    return (Int)(mod_reg_rm & 0x7);
364 }
365
366 /* Get a 8/16/32-bit unsigned value out of the insn stream. */
367
368 static UChar getUChar ( Int delta )
369 {
370    UChar v = guest_code[delta+0];
371    return toUChar(v);
372 }
373
374 static UInt getUDisp16 ( Int delta )
375 {
376    UInt v = guest_code[delta+1]; v <<= 8;
377    v |= guest_code[delta+0];
378    return v & 0xFFFF;
379 }
380
381 static UInt getUDisp32 ( Int delta )
382 {
383    UInt v = guest_code[delta+3]; v <<= 8;
384    v |= guest_code[delta+2]; v <<= 8;
385    v |= guest_code[delta+1]; v <<= 8;
386    v |= guest_code[delta+0];
387    return v;
388 }
389
390 static UInt getUDisp ( Int size, Int delta )
391 {
392    switch (size) {
393       case 4: return getUDisp32(delta);
394       case 2: return getUDisp16(delta);
395       case 1: return (UInt)getUChar(delta);
396       default: vpanic("getUDisp(x86)");
397    }
398    return 0; /*notreached*/
399 }
400
401
402 /* Get a byte value out of the insn stream and sign-extend to 32
403    bits. */
404 static UInt getSDisp8 ( Int delta )
405 {
406    return extend_s_8to32( (UInt) (guest_code[delta]) );
407 }
408
409 static UInt getSDisp16 ( Int delta0 )
410 {
411    UChar* eip = (UChar*)(&guest_code[delta0]);
412    UInt d = *eip++;
413    d |= ((*eip++) << 8);
414    return extend_s_16to32(d);
415 }
416
417 static UInt getSDisp ( Int size, Int delta )
418 {
419    switch (size) {
420       case 4: return getUDisp32(delta);
421       case 2: return getSDisp16(delta);
422       case 1: return getSDisp8(delta);
423       default: vpanic("getSDisp(x86)");
424   }
425   return 0; /*notreached*/
426 }
427
428
429 /*------------------------------------------------------------*/
430 /*--- Helpers for constructing IR.                         ---*/
431 /*------------------------------------------------------------*/
432
433 /* Create a 1/2/4 byte read of an x86 integer registers.  For 16/8 bit
434    register references, we need to take the host endianness into
435    account.  Supplied value is 0 .. 7 and in the Intel instruction
436    encoding. */
437
438 static IRType szToITy ( Int n )
439 {
440    switch (n) {
441       case 1: return Ity_I8;
442       case 2: return Ity_I16;
443       case 4: return Ity_I32;
444       default: vpanic("szToITy(x86)");
445    }
446 }
447
448 /* On a little-endian host, less significant bits of the guest
449    registers are at lower addresses.  Therefore, if a reference to a
450    register low half has the safe guest state offset as a reference to
451    the full register.
452 */
453 static Int integerGuestRegOffset ( Int sz, UInt archreg )
454 {
455    vassert(archreg < 8);
456
457    /* Correct for little-endian host only. */
458    vassert(!host_is_bigendian);
459
460    if (sz == 4 || sz == 2 || (sz == 1 && archreg < 4)) {
461       switch (archreg) {
462          case R_EAX: return OFFB_EAX;
463          case R_EBX: return OFFB_EBX;
464          case R_ECX: return OFFB_ECX;
465          case R_EDX: return OFFB_EDX;
466          case R_ESI: return OFFB_ESI;
467          case R_EDI: return OFFB_EDI;
468          case R_ESP: return OFFB_ESP;
469          case R_EBP: return OFFB_EBP;
470          default: vpanic("integerGuestRegOffset(x86,le)(4,2)");
471       }
472    }
473
474    vassert(archreg >= 4 && archreg < 8 && sz == 1);
475    switch (archreg-4) {
476       case R_EAX: return 1+ OFFB_EAX;
477       case R_EBX: return 1+ OFFB_EBX;
478       case R_ECX: return 1+ OFFB_ECX;
479       case R_EDX: return 1+ OFFB_EDX;
480       default: vpanic("integerGuestRegOffset(x86,le)(1h)");
481    }
482
483    /* NOTREACHED */
484    vpanic("integerGuestRegOffset(x86,le)");
485 }
486
487 static Int segmentGuestRegOffset ( UInt sreg )
488 {
489    switch (sreg) {
490       case R_ES: return OFFB_ES;
491       case R_CS: return OFFB_CS;
492       case R_SS: return OFFB_SS;
493       case R_DS: return OFFB_DS;
494       case R_FS: return OFFB_FS;
495       case R_GS: return OFFB_GS;
496       default: vpanic("segmentGuestRegOffset(x86)");
497    }
498 }
499
500 static Int xmmGuestRegOffset ( UInt xmmreg )
501 {
502    switch (xmmreg) {
503       case 0: return OFFB_XMM0;
504       case 1: return OFFB_XMM1;
505       case 2: return OFFB_XMM2;
506       case 3: return OFFB_XMM3;
507       case 4: return OFFB_XMM4;
508       case 5: return OFFB_XMM5;
509       case 6: return OFFB_XMM6;
510       case 7: return OFFB_XMM7;
511       default: vpanic("xmmGuestRegOffset");
512    }
513 }
514
515 /* Lanes of vector registers are always numbered from zero being the
516    least significant lane (rightmost in the register).  */
517
518 static Int xmmGuestRegLane16offset ( UInt xmmreg, Int laneno )
519 {
520    /* Correct for little-endian host only. */
521    vassert(!host_is_bigendian);
522    vassert(laneno >= 0 && laneno < 8);
523    return xmmGuestRegOffset( xmmreg ) + 2 * laneno;
524 }
525
526 static Int xmmGuestRegLane32offset ( UInt xmmreg, Int laneno )
527 {
528    /* Correct for little-endian host only. */
529    vassert(!host_is_bigendian);
530    vassert(laneno >= 0 && laneno < 4);
531    return xmmGuestRegOffset( xmmreg ) + 4 * laneno;
532 }
533
534 static Int xmmGuestRegLane64offset ( UInt xmmreg, Int laneno )
535 {
536    /* Correct for little-endian host only. */
537    vassert(!host_is_bigendian);
538    vassert(laneno >= 0 && laneno < 2);
539    return xmmGuestRegOffset( xmmreg ) + 8 * laneno;
540 }
541
542 static IRExpr* getIReg ( Int sz, UInt archreg )
543 {
544    vassert(sz == 1 || sz == 2 || sz == 4);
545    vassert(archreg < 8);
546    return IRExpr_Get( integerGuestRegOffset(sz,archreg),
547                       szToITy(sz) );
548 }
549
550 /* Ditto, but write to a reg instead. */
551 static void putIReg ( Int sz, UInt archreg, IRExpr* e )
552 {
553    IRType ty = typeOfIRExpr(irsb->tyenv, e);
554    switch (sz) {
555       case 1: vassert(ty == Ity_I8); break;
556       case 2: vassert(ty == Ity_I16); break;
557       case 4: vassert(ty == Ity_I32); break;
558       default: vpanic("putIReg(x86)");
559    }
560    vassert(archreg < 8);
561    stmt( IRStmt_Put(integerGuestRegOffset(sz,archreg), e) );
562 }
563
564 static IRExpr* getSReg ( UInt sreg )
565 {
566    return IRExpr_Get( segmentGuestRegOffset(sreg), Ity_I16 );
567 }
568
569 static void putSReg ( UInt sreg, IRExpr* e )
570 {
571    vassert(typeOfIRExpr(irsb->tyenv,e) == Ity_I16);
572    stmt( IRStmt_Put( segmentGuestRegOffset(sreg), e ) );
573 }
574
575 static IRExpr* getXMMReg ( UInt xmmreg )
576 {
577    return IRExpr_Get( xmmGuestRegOffset(xmmreg), Ity_V128 );
578 }
579
580 static IRExpr* getXMMRegLane64 ( UInt xmmreg, Int laneno )
581 {
582    return IRExpr_Get( xmmGuestRegLane64offset(xmmreg,laneno), Ity_I64 );
583 }
584
585 static IRExpr* getXMMRegLane64F ( UInt xmmreg, Int laneno )
586 {
587    return IRExpr_Get( xmmGuestRegLane64offset(xmmreg,laneno), Ity_F64 );
588 }
589
590 static IRExpr* getXMMRegLane32 ( UInt xmmreg, Int laneno )
591 {
592    return IRExpr_Get( xmmGuestRegLane32offset(xmmreg,laneno), Ity_I32 );
593 }
594
595 static IRExpr* getXMMRegLane32F ( UInt xmmreg, Int laneno )
596 {
597    return IRExpr_Get( xmmGuestRegLane32offset(xmmreg,laneno), Ity_F32 );
598 }
599
600 static void putXMMReg ( UInt xmmreg, IRExpr* e )
601 {
602    vassert(typeOfIRExpr(irsb->tyenv,e) == Ity_V128);
603    stmt( IRStmt_Put( xmmGuestRegOffset(xmmreg), e ) );
604 }
605
606 static void putXMMRegLane64 ( UInt xmmreg, Int laneno, IRExpr* e )
607 {
608    vassert(typeOfIRExpr(irsb->tyenv,e) == Ity_I64);
609    stmt( IRStmt_Put( xmmGuestRegLane64offset(xmmreg,laneno), e ) );
610 }
611
612 static void putXMMRegLane64F ( UInt xmmreg, Int laneno, IRExpr* e )
613 {
614    vassert(typeOfIRExpr(irsb->tyenv,e) == Ity_F64);
615    stmt( IRStmt_Put( xmmGuestRegLane64offset(xmmreg,laneno), e ) );
616 }
617
618 static void putXMMRegLane32F ( UInt xmmreg, Int laneno, IRExpr* e )
619 {
620    vassert(typeOfIRExpr(irsb->tyenv,e) == Ity_F32);
621    stmt( IRStmt_Put( xmmGuestRegLane32offset(xmmreg,laneno), e ) );
622 }
623
624 static void putXMMRegLane32 ( UInt xmmreg, Int laneno, IRExpr* e )
625 {
626    vassert(typeOfIRExpr(irsb->tyenv,e) == Ity_I32);
627    stmt( IRStmt_Put( xmmGuestRegLane32offset(xmmreg,laneno), e ) );
628 }
629
630 static void putXMMRegLane16 ( UInt xmmreg, Int laneno, IRExpr* e )
631 {
632    vassert(typeOfIRExpr(irsb->tyenv,e) == Ity_I16);
633    stmt( IRStmt_Put( xmmGuestRegLane16offset(xmmreg,laneno), e ) );
634 }
635
636 static void assign ( IRTemp dst, IRExpr* e )
637 {
638    stmt( IRStmt_WrTmp(dst, e) );
639 }
640
641 static void storeLE ( IRExpr* addr, IRExpr* data )
642 {
643    stmt( IRStmt_Store(Iend_LE, addr, data) );
644 }
645
646 static IRExpr* unop ( IROp op, IRExpr* a )
647 {
648    return IRExpr_Unop(op, a);
649 }
650
651 static IRExpr* binop ( IROp op, IRExpr* a1, IRExpr* a2 )
652 {
653    return IRExpr_Binop(op, a1, a2);
654 }
655
656 static IRExpr* triop ( IROp op, IRExpr* a1, IRExpr* a2, IRExpr* a3 )
657 {
658    return IRExpr_Triop(op, a1, a2, a3);
659 }
660
661 static IRExpr* mkexpr ( IRTemp tmp )
662 {
663    return IRExpr_RdTmp(tmp);
664 }
665
666 static IRExpr* mkU8 ( UInt i )
667 {
668    vassert(i < 256);
669    return IRExpr_Const(IRConst_U8( (UChar)i ));
670 }
671
672 static IRExpr* mkU16 ( UInt i )
673 {
674    vassert(i < 65536);
675    return IRExpr_Const(IRConst_U16( (UShort)i ));
676 }
677
678 static IRExpr* mkU32 ( UInt i )
679 {
680    return IRExpr_Const(IRConst_U32(i));
681 }
682
683 static IRExpr* mkU64 ( ULong i )
684 {
685    return IRExpr_Const(IRConst_U64(i));
686 }
687
688 static IRExpr* mkU ( IRType ty, UInt i )
689 {
690    if (ty == Ity_I8)  return mkU8(i);
691    if (ty == Ity_I16) return mkU16(i);
692    if (ty == Ity_I32) return mkU32(i);
693    /* If this panics, it usually means you passed a size (1,2,4)
694       value as the IRType, rather than a real IRType. */
695    vpanic("mkU(x86)");
696 }
697
698 static IRExpr* mkV128 ( UShort mask )
699 {
700    return IRExpr_Const(IRConst_V128(mask));
701 }
702
703 static IRExpr* loadLE ( IRType ty, IRExpr* addr )
704 {
705    return IRExpr_Load(Iend_LE, ty, addr);
706 }
707
708 static IROp mkSizedOp ( IRType ty, IROp op8 )
709 {
710    Int adj;
711    vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32);
712    vassert(op8 == Iop_Add8 || op8 == Iop_Sub8 
713            || op8 == Iop_Mul8 
714            || op8 == Iop_Or8 || op8 == Iop_And8 || op8 == Iop_Xor8
715            || op8 == Iop_Shl8 || op8 == Iop_Shr8 || op8 == Iop_Sar8
716            || op8 == Iop_CmpEQ8 || op8 == Iop_CmpNE8
717            || op8 == Iop_CasCmpNE8
718            || op8 == Iop_Not8);
719    adj = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : 2);
720    return adj + op8;
721 }
722
723 static IROp mkWidenOp ( Int szSmall, Int szBig, Bool signd )
724 {
725    if (szSmall == 1 && szBig == 4) {
726       return signd ? Iop_8Sto32 : Iop_8Uto32;
727    }
728    if (szSmall == 1 && szBig == 2) {
729       return signd ? Iop_8Sto16 : Iop_8Uto16;
730    }
731    if (szSmall == 2 && szBig == 4) {
732       return signd ? Iop_16Sto32 : Iop_16Uto32;
733    }
734    vpanic("mkWidenOp(x86,guest)");
735 }
736
737 static IRExpr* mkAnd1 ( IRExpr* x, IRExpr* y )
738 {
739    vassert(typeOfIRExpr(irsb->tyenv,x) == Ity_I1);
740    vassert(typeOfIRExpr(irsb->tyenv,y) == Ity_I1);
741    return unop(Iop_32to1, 
742                binop(Iop_And32, 
743                      unop(Iop_1Uto32,x), 
744                      unop(Iop_1Uto32,y)));
745 }
746
747 /* Generate a compare-and-swap operation, operating on memory at
748    'addr'.  The expected value is 'expVal' and the new value is
749    'newVal'.  If the operation fails, then transfer control (with a
750    no-redir jump (XXX no -- see comment at top of this file)) to
751    'restart_point', which is presumably the address of the guest
752    instruction again -- retrying, essentially. */
753 static void casLE ( IRExpr* addr, IRExpr* expVal, IRExpr* newVal,
754                     Addr32 restart_point )
755 {
756    IRCAS* cas;
757    IRType tyE    = typeOfIRExpr(irsb->tyenv, expVal);
758    IRType tyN    = typeOfIRExpr(irsb->tyenv, newVal);
759    IRTemp oldTmp = newTemp(tyE);
760    IRTemp expTmp = newTemp(tyE);
761    vassert(tyE == tyN);
762    vassert(tyE == Ity_I32 || tyE == Ity_I16 || tyE == Ity_I8);
763    assign(expTmp, expVal);
764    cas = mkIRCAS( IRTemp_INVALID, oldTmp, Iend_LE, addr, 
765                   NULL, mkexpr(expTmp), NULL, newVal );
766    stmt( IRStmt_CAS(cas) );
767    stmt( IRStmt_Exit(
768             binop( mkSizedOp(tyE,Iop_CasCmpNE8),
769                    mkexpr(oldTmp), mkexpr(expTmp) ),
770             Ijk_Boring, /*Ijk_NoRedir*/
771             IRConst_U32( restart_point ) 
772          ));
773 }
774
775
776 /*------------------------------------------------------------*/
777 /*--- Helpers for %eflags.                                 ---*/
778 /*------------------------------------------------------------*/
779
780 /* -------------- Evaluating the flags-thunk. -------------- */
781
782 /* Build IR to calculate all the eflags from stored
783    CC_OP/CC_DEP1/CC_DEP2/CC_NDEP.  Returns an expression ::
784    Ity_I32. */
785 static IRExpr* mk_x86g_calculate_eflags_all ( void )
786 {
787    IRExpr** args
788       = mkIRExprVec_4( IRExpr_Get(OFFB_CC_OP,   Ity_I32),
789                        IRExpr_Get(OFFB_CC_DEP1, Ity_I32),
790                        IRExpr_Get(OFFB_CC_DEP2, Ity_I32),
791                        IRExpr_Get(OFFB_CC_NDEP, Ity_I32) );
792    IRExpr* call
793       = mkIRExprCCall(
794            Ity_I32,
795            0/*regparm*/, 
796            "x86g_calculate_eflags_all", &x86g_calculate_eflags_all,
797            args
798         );
799    /* Exclude OP and NDEP from definedness checking.  We're only
800       interested in DEP1 and DEP2. */
801    call->Iex.CCall.cee->mcx_mask = (1<<0) | (1<<3);
802    return call;
803 }
804
805 /* Build IR to calculate some particular condition from stored
806    CC_OP/CC_DEP1/CC_DEP2/CC_NDEP.  Returns an expression ::
807    Ity_Bit. */
808 static IRExpr* mk_x86g_calculate_condition ( X86Condcode cond )
809 {
810    IRExpr** args
811       = mkIRExprVec_5( mkU32(cond),
812                        IRExpr_Get(OFFB_CC_OP,  Ity_I32),
813                        IRExpr_Get(OFFB_CC_DEP1, Ity_I32),
814                        IRExpr_Get(OFFB_CC_DEP2, Ity_I32),
815                        IRExpr_Get(OFFB_CC_NDEP, Ity_I32) );
816    IRExpr* call
817       = mkIRExprCCall(
818            Ity_I32,
819            0/*regparm*/, 
820            "x86g_calculate_condition", &x86g_calculate_condition,
821            args
822         );
823    /* Exclude the requested condition, OP and NDEP from definedness
824       checking.  We're only interested in DEP1 and DEP2. */
825    call->Iex.CCall.cee->mcx_mask = (1<<0) | (1<<1) | (1<<4);
826    return unop(Iop_32to1, call);
827 }
828
829 /* Build IR to calculate just the carry flag from stored
830    CC_OP/CC_DEP1/CC_DEP2/CC_NDEP.  Returns an expression :: Ity_I32. */
831 static IRExpr* mk_x86g_calculate_eflags_c ( void )
832 {
833    IRExpr** args
834       = mkIRExprVec_4( IRExpr_Get(OFFB_CC_OP,   Ity_I32),
835                        IRExpr_Get(OFFB_CC_DEP1, Ity_I32),
836                        IRExpr_Get(OFFB_CC_DEP2, Ity_I32),
837                        IRExpr_Get(OFFB_CC_NDEP, Ity_I32) );
838    IRExpr* call
839       = mkIRExprCCall(
840            Ity_I32,
841            3/*regparm*/, 
842            "x86g_calculate_eflags_c", &x86g_calculate_eflags_c,
843            args
844         );
845    /* Exclude OP and NDEP from definedness checking.  We're only
846       interested in DEP1 and DEP2. */
847    call->Iex.CCall.cee->mcx_mask = (1<<0) | (1<<3);
848    return call;
849 }
850
851
852 /* -------------- Building the flags-thunk. -------------- */
853
854 /* The machinery in this section builds the flag-thunk following a
855    flag-setting operation.  Hence the various setFlags_* functions.
856 */
857
858 static Bool isAddSub ( IROp op8 )
859 {
860    return toBool(op8 == Iop_Add8 || op8 == Iop_Sub8);
861 }
862
863 static Bool isLogic ( IROp op8 )
864 {
865    return toBool(op8 == Iop_And8 || op8 == Iop_Or8 || op8 == Iop_Xor8);
866 }
867
868 /* U-widen 8/16/32 bit int expr to 32. */
869 static IRExpr* widenUto32 ( IRExpr* e )
870 {
871    switch (typeOfIRExpr(irsb->tyenv,e)) {
872       case Ity_I32: return e;
873       case Ity_I16: return unop(Iop_16Uto32,e);
874       case Ity_I8:  return unop(Iop_8Uto32,e);
875       default: vpanic("widenUto32");
876    }
877 }
878
879 /* S-widen 8/16/32 bit int expr to 32. */
880 static IRExpr* widenSto32 ( IRExpr* e )
881 {
882    switch (typeOfIRExpr(irsb->tyenv,e)) {
883       case Ity_I32: return e;
884       case Ity_I16: return unop(Iop_16Sto32,e);
885       case Ity_I8:  return unop(Iop_8Sto32,e);
886       default: vpanic("widenSto32");
887    }
888 }
889
890 /* Narrow 8/16/32 bit int expr to 8/16/32.  Clearly only some
891    of these combinations make sense. */
892 static IRExpr* narrowTo ( IRType dst_ty, IRExpr* e )
893 {
894    IRType src_ty = typeOfIRExpr(irsb->tyenv,e);
895    if (src_ty == dst_ty)
896       return e;
897    if (src_ty == Ity_I32 && dst_ty == Ity_I16)
898       return unop(Iop_32to16, e);
899    if (src_ty == Ity_I32 && dst_ty == Ity_I8)
900       return unop(Iop_32to8, e);
901
902    vex_printf("\nsrc, dst tys are: ");
903    ppIRType(src_ty);
904    vex_printf(", ");
905    ppIRType(dst_ty);
906    vex_printf("\n");
907    vpanic("narrowTo(x86)");
908 }
909
910
911 /* Set the flags thunk OP, DEP1 and DEP2 fields.  The supplied op is
912    auto-sized up to the real op. */
913
914 static 
915 void setFlags_DEP1_DEP2 ( IROp op8, IRTemp dep1, IRTemp dep2, IRType ty )
916 {
917    Int ccOp = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : 2);
918
919    vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32);
920
921    switch (op8) {
922       case Iop_Add8: ccOp += X86G_CC_OP_ADDB;   break;
923       case Iop_Sub8: ccOp += X86G_CC_OP_SUBB;   break;
924       default:       ppIROp(op8);
925                      vpanic("setFlags_DEP1_DEP2(x86)");
926    }
927    stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(ccOp)) );
928    stmt( IRStmt_Put( OFFB_CC_DEP1, widenUto32(mkexpr(dep1))) );
929    stmt( IRStmt_Put( OFFB_CC_DEP2, widenUto32(mkexpr(dep2))) );
930    /* Set NDEP even though it isn't used.  This makes redundant-PUT
931       elimination of previous stores to this field work better. */
932    stmt( IRStmt_Put( OFFB_CC_NDEP, mkU32(0) ));
933 }
934
935
936 /* Set the OP and DEP1 fields only, and write zero to DEP2. */
937
938 static 
939 void setFlags_DEP1 ( IROp op8, IRTemp dep1, IRType ty )
940 {
941    Int ccOp = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : 2);
942
943    vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32);
944
945    switch (op8) {
946       case Iop_Or8:
947       case Iop_And8:
948       case Iop_Xor8: ccOp += X86G_CC_OP_LOGICB; break;
949       default:       ppIROp(op8);
950                      vpanic("setFlags_DEP1(x86)");
951    }
952    stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(ccOp)) );
953    stmt( IRStmt_Put( OFFB_CC_DEP1, widenUto32(mkexpr(dep1))) );
954    stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0)) );
955    /* Set NDEP even though it isn't used.  This makes redundant-PUT
956       elimination of previous stores to this field work better. */
957    stmt( IRStmt_Put( OFFB_CC_NDEP, mkU32(0) ));
958 }
959
960
961 /* For shift operations, we put in the result and the undershifted
962    result.  Except if the shift amount is zero, the thunk is left
963    unchanged. */
964
965 static void setFlags_DEP1_DEP2_shift ( IROp    op32,
966                                        IRTemp  res,
967                                        IRTemp  resUS,
968                                        IRType  ty,
969                                        IRTemp  guard )
970 {
971    Int ccOp = ty==Ity_I8 ? 2 : (ty==Ity_I16 ? 1 : 0);
972
973    vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32);
974    vassert(guard);
975
976    /* Both kinds of right shifts are handled by the same thunk
977       operation. */
978    switch (op32) {
979       case Iop_Shr32:
980       case Iop_Sar32: ccOp = X86G_CC_OP_SHRL - ccOp; break;
981       case Iop_Shl32: ccOp = X86G_CC_OP_SHLL - ccOp; break;
982       default:        ppIROp(op32);
983                       vpanic("setFlags_DEP1_DEP2_shift(x86)");
984    }
985
986    /* DEP1 contains the result, DEP2 contains the undershifted value. */
987    stmt( IRStmt_Put( OFFB_CC_OP,
988                      IRExpr_Mux0X( mkexpr(guard),
989                                    IRExpr_Get(OFFB_CC_OP,Ity_I32),
990                                    mkU32(ccOp))) );
991    stmt( IRStmt_Put( OFFB_CC_DEP1,
992                      IRExpr_Mux0X( mkexpr(guard),
993                                    IRExpr_Get(OFFB_CC_DEP1,Ity_I32),
994                                    widenUto32(mkexpr(res)))) );
995    stmt( IRStmt_Put( OFFB_CC_DEP2, 
996                      IRExpr_Mux0X( mkexpr(guard),
997                                    IRExpr_Get(OFFB_CC_DEP2,Ity_I32),
998                                    widenUto32(mkexpr(resUS)))) );
999    /* Set NDEP even though it isn't used.  This makes redundant-PUT
1000       elimination of previous stores to this field work better. */
1001    stmt( IRStmt_Put( OFFB_CC_NDEP,
1002                      IRExpr_Mux0X( mkexpr(guard),
1003                                    IRExpr_Get(OFFB_CC_NDEP,Ity_I32),
1004                                    mkU32(0) )));
1005 }
1006
1007
1008 /* For the inc/dec case, we store in DEP1 the result value and in NDEP
1009    the former value of the carry flag, which unfortunately we have to
1010    compute. */
1011
1012 static void setFlags_INC_DEC ( Bool inc, IRTemp res, IRType ty )
1013 {
1014    Int ccOp = inc ? X86G_CC_OP_INCB : X86G_CC_OP_DECB;
1015    
1016    ccOp += ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : 2);
1017    vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32);
1018
1019    /* This has to come first, because calculating the C flag 
1020       may require reading all four thunk fields. */
1021    stmt( IRStmt_Put( OFFB_CC_NDEP, mk_x86g_calculate_eflags_c()) );
1022    stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(ccOp)) );
1023    stmt( IRStmt_Put( OFFB_CC_DEP1, widenUto32(mkexpr(res))) );
1024    stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0)) );
1025 }
1026
1027
1028 /* Multiplies are pretty much like add and sub: DEP1 and DEP2 hold the
1029    two arguments. */
1030
1031 static
1032 void setFlags_MUL ( IRType ty, IRTemp arg1, IRTemp arg2, UInt base_op )
1033 {
1034    switch (ty) {
1035       case Ity_I8:
1036          stmt( IRStmt_Put( OFFB_CC_OP, mkU32(base_op+0) ) );
1037          break;
1038       case Ity_I16:
1039          stmt( IRStmt_Put( OFFB_CC_OP, mkU32(base_op+1) ) );
1040          break;
1041       case Ity_I32:
1042          stmt( IRStmt_Put( OFFB_CC_OP, mkU32(base_op+2) ) );
1043          break;
1044       default:
1045          vpanic("setFlags_MUL(x86)");
1046    }
1047    stmt( IRStmt_Put( OFFB_CC_DEP1, widenUto32(mkexpr(arg1)) ));
1048    stmt( IRStmt_Put( OFFB_CC_DEP2, widenUto32(mkexpr(arg2)) ));
1049    /* Set NDEP even though it isn't used.  This makes redundant-PUT
1050       elimination of previous stores to this field work better. */
1051    stmt( IRStmt_Put( OFFB_CC_NDEP, mkU32(0) ));
1052 }
1053
1054
1055 /* -------------- Condition codes. -------------- */
1056
1057 /* Condition codes, using the Intel encoding.  */
1058
1059 static HChar* name_X86Condcode ( X86Condcode cond )
1060 {
1061    switch (cond) {
1062       case X86CondO:      return "o";
1063       case X86CondNO:     return "no";
1064       case X86CondB:      return "b";
1065       case X86CondNB:     return "nb";
1066       case X86CondZ:      return "z";
1067       case X86CondNZ:     return "nz";
1068       case X86CondBE:     return "be";
1069       case X86CondNBE:    return "nbe";
1070       case X86CondS:      return "s";
1071       case X86CondNS:     return "ns";
1072       case X86CondP:      return "p";
1073       case X86CondNP:     return "np";
1074       case X86CondL:      return "l";
1075       case X86CondNL:     return "nl";
1076       case X86CondLE:     return "le";
1077       case X86CondNLE:    return "nle";
1078       case X86CondAlways: return "ALWAYS";
1079       default: vpanic("name_X86Condcode");
1080    }
1081 }
1082
1083 static 
1084 X86Condcode positiveIse_X86Condcode ( X86Condcode  cond,
1085                                       Bool*        needInvert )
1086 {
1087    vassert(cond >= X86CondO && cond <= X86CondNLE);
1088    if (cond & 1) {
1089       *needInvert = True;
1090       return cond-1;
1091    } else {
1092       *needInvert = False;
1093       return cond;
1094    }
1095 }
1096
1097
1098 /* -------------- Helpers for ADD/SUB with carry. -------------- */
1099
1100 /* Given ta1, ta2 and tres, compute tres = ADC(ta1,ta2) and set flags
1101    appropriately.
1102
1103    Optionally, generate a store for the 'tres' value.  This can either
1104    be a normal store, or it can be a cas-with-possible-failure style
1105    store:
1106
1107    if taddr is IRTemp_INVALID, then no store is generated.
1108
1109    if taddr is not IRTemp_INVALID, then a store (using taddr as
1110    the address) is generated:
1111
1112      if texpVal is IRTemp_INVALID then a normal store is
1113      generated, and restart_point must be zero (it is irrelevant).
1114
1115      if texpVal is not IRTemp_INVALID then a cas-style store is
1116      generated.  texpVal is the expected value, restart_point
1117      is the restart point if the store fails, and texpVal must
1118      have the same type as tres.   
1119 */
1120 static void helper_ADC ( Int sz,
1121                          IRTemp tres, IRTemp ta1, IRTemp ta2,
1122                          /* info about optional store: */
1123                          IRTemp taddr, IRTemp texpVal, Addr32 restart_point )
1124 {
1125    UInt    thunkOp;
1126    IRType  ty    = szToITy(sz);
1127    IRTemp  oldc  = newTemp(Ity_I32);
1128    IRTemp  oldcn = newTemp(ty);
1129    IROp    plus  = mkSizedOp(ty, Iop_Add8);
1130    IROp    xor   = mkSizedOp(ty, Iop_Xor8);
1131
1132    vassert(typeOfIRTemp(irsb->tyenv, tres) == ty);
1133    vassert(sz == 1 || sz == 2 || sz == 4);
1134    thunkOp = sz==4 ? X86G_CC_OP_ADCL 
1135                    : (sz==2 ? X86G_CC_OP_ADCW : X86G_CC_OP_ADCB);
1136
1137    /* oldc = old carry flag, 0 or 1 */
1138    assign( oldc,  binop(Iop_And32,
1139                         mk_x86g_calculate_eflags_c(),
1140                         mkU32(1)) );
1141
1142    assign( oldcn, narrowTo(ty, mkexpr(oldc)) );
1143
1144    assign( tres, binop(plus,
1145                        binop(plus,mkexpr(ta1),mkexpr(ta2)),
1146                        mkexpr(oldcn)) );
1147
1148    /* Possibly generate a store of 'tres' to 'taddr'.  See comment at
1149       start of this function. */
1150    if (taddr != IRTemp_INVALID) {
1151       if (texpVal == IRTemp_INVALID) {
1152          vassert(restart_point == 0);
1153          storeLE( mkexpr(taddr), mkexpr(tres) );
1154       } else {
1155          vassert(typeOfIRTemp(irsb->tyenv, texpVal) == ty);
1156          /* .. and hence 'texpVal' has the same type as 'tres'. */
1157          casLE( mkexpr(taddr),
1158                 mkexpr(texpVal), mkexpr(tres), restart_point );
1159       }
1160    }
1161
1162    stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(thunkOp) ) );
1163    stmt( IRStmt_Put( OFFB_CC_DEP1, widenUto32(mkexpr(ta1)) ));
1164    stmt( IRStmt_Put( OFFB_CC_DEP2, widenUto32(binop(xor, mkexpr(ta2), 
1165                                                          mkexpr(oldcn)) )) );
1166    stmt( IRStmt_Put( OFFB_CC_NDEP, mkexpr(oldc) ) );
1167 }
1168
1169
1170 /* Given ta1, ta2 and tres, compute tres = SBB(ta1,ta2) and set flags
1171    appropriately.  As with helper_ADC, possibly generate a store of
1172    the result -- see comments on helper_ADC for details.
1173 */
1174 static void helper_SBB ( Int sz,
1175                          IRTemp tres, IRTemp ta1, IRTemp ta2,
1176                          /* info about optional store: */
1177                          IRTemp taddr, IRTemp texpVal, Addr32 restart_point )
1178 {
1179    UInt    thunkOp;
1180    IRType  ty    = szToITy(sz);
1181    IRTemp  oldc  = newTemp(Ity_I32);
1182    IRTemp  oldcn = newTemp(ty);
1183    IROp    minus = mkSizedOp(ty, Iop_Sub8);
1184    IROp    xor   = mkSizedOp(ty, Iop_Xor8);
1185
1186    vassert(typeOfIRTemp(irsb->tyenv, tres) == ty);
1187    vassert(sz == 1 || sz == 2 || sz == 4);
1188    thunkOp = sz==4 ? X86G_CC_OP_SBBL 
1189                    : (sz==2 ? X86G_CC_OP_SBBW : X86G_CC_OP_SBBB);
1190
1191    /* oldc = old carry flag, 0 or 1 */
1192    assign( oldc, binop(Iop_And32,
1193                        mk_x86g_calculate_eflags_c(),
1194                        mkU32(1)) );
1195
1196    assign( oldcn, narrowTo(ty, mkexpr(oldc)) );
1197
1198    assign( tres, binop(minus,
1199                        binop(minus,mkexpr(ta1),mkexpr(ta2)),
1200                        mkexpr(oldcn)) );
1201
1202    /* Possibly generate a store of 'tres' to 'taddr'.  See comment at
1203       start of this function. */
1204    if (taddr != IRTemp_INVALID) {
1205       if (texpVal == IRTemp_INVALID) {
1206          vassert(restart_point == 0);
1207          storeLE( mkexpr(taddr), mkexpr(tres) );
1208       } else {
1209          vassert(typeOfIRTemp(irsb->tyenv, texpVal) == ty);
1210          /* .. and hence 'texpVal' has the same type as 'tres'. */
1211          casLE( mkexpr(taddr),
1212                 mkexpr(texpVal), mkexpr(tres), restart_point );
1213       }
1214    }
1215
1216    stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(thunkOp) ) );
1217    stmt( IRStmt_Put( OFFB_CC_DEP1, widenUto32(mkexpr(ta1) )) );
1218    stmt( IRStmt_Put( OFFB_CC_DEP2, widenUto32(binop(xor, mkexpr(ta2), 
1219                                                          mkexpr(oldcn)) )) );
1220    stmt( IRStmt_Put( OFFB_CC_NDEP, mkexpr(oldc) ) );
1221 }
1222
1223
1224 /* -------------- Helpers for disassembly printing. -------------- */
1225
1226 static HChar* nameGrp1 ( Int opc_aux )
1227 {
1228    static HChar* grp1_names[8] 
1229      = { "add", "or", "adc", "sbb", "and", "sub", "xor", "cmp" };
1230    if (opc_aux < 0 || opc_aux > 7) vpanic("nameGrp1(x86)");
1231    return grp1_names[opc_aux];
1232 }
1233
1234 static HChar* nameGrp2 ( Int opc_aux )
1235 {
1236    static HChar* grp2_names[8] 
1237      = { "rol", "ror", "rcl", "rcr", "shl", "shr", "shl", "sar" };
1238    if (opc_aux < 0 || opc_aux > 7) vpanic("nameGrp2(x86)");
1239    return grp2_names[opc_aux];
1240 }
1241
1242 static HChar* nameGrp4 ( Int opc_aux )
1243 {
1244    static HChar* grp4_names[8] 
1245      = { "inc", "dec", "???", "???", "???", "???", "???", "???" };
1246    if (opc_aux < 0 || opc_aux > 1) vpanic("nameGrp4(x86)");
1247    return grp4_names[opc_aux];
1248 }
1249
1250 static HChar* nameGrp5 ( Int opc_aux )
1251 {
1252    static HChar* grp5_names[8] 
1253      = { "inc", "dec", "call*", "call*", "jmp*", "jmp*", "push", "???" };
1254    if (opc_aux < 0 || opc_aux > 6) vpanic("nameGrp5(x86)");
1255    return grp5_names[opc_aux];
1256 }
1257
1258 static HChar* nameGrp8 ( Int opc_aux )
1259 {
1260    static HChar* grp8_names[8] 
1261      = { "???", "???", "???", "???", "bt", "bts", "btr", "btc" };
1262    if (opc_aux < 4 || opc_aux > 7) vpanic("nameGrp8(x86)");
1263    return grp8_names[opc_aux];
1264 }
1265
1266 static HChar* nameIReg ( Int size, Int reg )
1267 {
1268    static HChar* ireg32_names[8] 
1269      = { "%eax", "%ecx", "%edx", "%ebx", 
1270          "%esp", "%ebp", "%esi", "%edi" };
1271    static HChar* ireg16_names[8] 
1272      = { "%ax", "%cx", "%dx", "%bx", "%sp", "%bp", "%si", "%di" };
1273    static HChar* ireg8_names[8] 
1274      = { "%al", "%cl", "%dl", "%bl", 
1275          "%ah{sp}", "%ch{bp}", "%dh{si}", "%bh{di}" };
1276    if (reg < 0 || reg > 7) goto bad;
1277    switch (size) {
1278       case 4: return ireg32_names[reg];
1279       case 2: return ireg16_names[reg];
1280       case 1: return ireg8_names[reg];
1281    }
1282   bad:
1283    vpanic("nameIReg(X86)");
1284    return NULL; /*notreached*/
1285 }
1286
1287 static HChar* nameSReg ( UInt sreg )
1288 {
1289    switch (sreg) {
1290       case R_ES: return "%es";
1291       case R_CS: return "%cs";
1292       case R_SS: return "%ss";
1293       case R_DS: return "%ds";
1294       case R_FS: return "%fs";
1295       case R_GS: return "%gs";
1296       default: vpanic("nameSReg(x86)");
1297    }
1298 }
1299
1300 static HChar* nameMMXReg ( Int mmxreg )
1301 {
1302    static HChar* mmx_names[8] 
1303      = { "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7" };
1304    if (mmxreg < 0 || mmxreg > 7) vpanic("nameMMXReg(x86,guest)");
1305    return mmx_names[mmxreg];
1306 }
1307
1308 static HChar* nameXMMReg ( Int xmmreg )
1309 {
1310    static HChar* xmm_names[8] 
1311      = { "%xmm0", "%xmm1", "%xmm2", "%xmm3", 
1312          "%xmm4", "%xmm5", "%xmm6", "%xmm7" };
1313    if (xmmreg < 0 || xmmreg > 7) vpanic("name_of_xmm_reg");
1314    return xmm_names[xmmreg];
1315 }
1316  
1317 static HChar* nameMMXGran ( Int gran )
1318 {
1319    switch (gran) {
1320       case 0: return "b";
1321       case 1: return "w";
1322       case 2: return "d";
1323       case 3: return "q";
1324       default: vpanic("nameMMXGran(x86,guest)");
1325    }
1326 }
1327
1328 static HChar nameISize ( Int size )
1329 {
1330    switch (size) {
1331       case 4: return 'l';
1332       case 2: return 'w';
1333       case 1: return 'b';
1334       default: vpanic("nameISize(x86)");
1335    }
1336 }
1337
1338
1339 /*------------------------------------------------------------*/
1340 /*--- JMP helpers                                          ---*/
1341 /*------------------------------------------------------------*/
1342
1343 static void jmp_lit( IRJumpKind kind, Addr32 d32 )
1344 {
1345    irsb->next     = mkU32(d32);
1346    irsb->jumpkind = kind;
1347 }
1348
1349 static void jmp_treg( IRJumpKind kind, IRTemp t )
1350 {
1351    irsb->next = mkexpr(t);
1352    irsb->jumpkind = kind;
1353 }
1354
1355 static 
1356 void jcc_01( X86Condcode cond, Addr32 d32_false, Addr32 d32_true )
1357 {
1358    Bool        invert;
1359    X86Condcode condPos;
1360    condPos = positiveIse_X86Condcode ( cond, &invert );
1361    if (invert) {
1362       stmt( IRStmt_Exit( mk_x86g_calculate_condition(condPos),
1363                          Ijk_Boring,
1364                          IRConst_U32(d32_false) ) );
1365       irsb->next     = mkU32(d32_true);
1366       irsb->jumpkind = Ijk_Boring;
1367    } else {
1368       stmt( IRStmt_Exit( mk_x86g_calculate_condition(condPos),
1369                          Ijk_Boring,
1370                          IRConst_U32(d32_true) ) );
1371       irsb->next     = mkU32(d32_false);
1372       irsb->jumpkind = Ijk_Boring;
1373    }
1374 }
1375
1376
1377 /*------------------------------------------------------------*/
1378 /*--- Disassembling addressing modes                       ---*/
1379 /*------------------------------------------------------------*/
1380
1381 static 
1382 HChar* sorbTxt ( UChar sorb )
1383 {
1384    switch (sorb) {
1385       case 0:    return ""; /* no override */
1386       case 0x3E: return "%ds";
1387       case 0x26: return "%es:";
1388       case 0x64: return "%fs:";
1389       case 0x65: return "%gs:";
1390       default: vpanic("sorbTxt(x86,guest)");
1391    }
1392 }
1393
1394
1395 /* 'virtual' is an IRExpr* holding a virtual address.  Convert it to a
1396    linear address by adding any required segment override as indicated
1397    by sorb. */
1398 static
1399 IRExpr* handleSegOverride ( UChar sorb, IRExpr* virtual )
1400 {
1401    Int    sreg;
1402    IRType hWordTy;
1403    IRTemp ldt_ptr, gdt_ptr, seg_selector, r64;
1404
1405    if (sorb == 0)
1406       /* the common case - no override */
1407       return virtual;
1408
1409    switch (sorb) {
1410       case 0x3E: sreg = R_DS; break;
1411       case 0x26: sreg = R_ES; break;
1412       case 0x64: sreg = R_FS; break;
1413       case 0x65: sreg = R_GS; break;
1414       default: vpanic("handleSegOverride(x86,guest)");
1415    }
1416
1417    hWordTy = sizeof(HWord)==4 ? Ity_I32 : Ity_I64;
1418
1419    seg_selector = newTemp(Ity_I32);
1420    ldt_ptr      = newTemp(hWordTy);
1421    gdt_ptr      = newTemp(hWordTy);
1422    r64          = newTemp(Ity_I64);
1423
1424    assign( seg_selector, unop(Iop_16Uto32, getSReg(sreg)) );
1425    assign( ldt_ptr, IRExpr_Get( OFFB_LDT, hWordTy ));
1426    assign( gdt_ptr, IRExpr_Get( OFFB_GDT, hWordTy ));
1427
1428    /*
1429    Call this to do the translation and limit checks: 
1430    ULong x86g_use_seg_selector ( HWord ldt, HWord gdt,
1431                                  UInt seg_selector, UInt virtual_addr )
1432    */
1433    assign( 
1434       r64, 
1435       mkIRExprCCall( 
1436          Ity_I64, 
1437          0/*regparms*/, 
1438          "x86g_use_seg_selector", 
1439          &x86g_use_seg_selector, 
1440          mkIRExprVec_4( mkexpr(ldt_ptr), mkexpr(gdt_ptr), 
1441                         mkexpr(seg_selector), virtual)
1442       )
1443    );
1444
1445    /* If the high 32 of the result are non-zero, there was a 
1446       failure in address translation.  In which case, make a
1447       quick exit.
1448    */
1449    stmt( 
1450       IRStmt_Exit(
1451          binop(Iop_CmpNE32, unop(Iop_64HIto32, mkexpr(r64)), mkU32(0)),
1452          Ijk_MapFail,
1453          IRConst_U32( guest_EIP_curr_instr )
1454       )
1455    );
1456
1457    /* otherwise, here's the translated result. */
1458    return unop(Iop_64to32, mkexpr(r64));
1459 }
1460
1461
1462 /* Generate IR to calculate an address indicated by a ModRM and
1463    following SIB bytes.  The expression, and the number of bytes in
1464    the address mode, are returned.  Note that this fn should not be
1465    called if the R/M part of the address denotes a register instead of
1466    memory.  If print_codegen is true, text of the addressing mode is
1467    placed in buf. 
1468
1469    The computed address is stored in a new tempreg, and the
1470    identity of the tempreg is returned.  */
1471
1472 static IRTemp disAMode_copy2tmp ( IRExpr* addr32 )
1473 {
1474    IRTemp tmp = newTemp(Ity_I32);
1475    assign( tmp, addr32 );
1476    return tmp;
1477 }
1478
1479 static 
1480 IRTemp disAMode ( Int* len, UChar sorb, Int delta, HChar* buf )
1481 {
1482    UChar mod_reg_rm = getIByte(delta);
1483    delta++;
1484
1485    buf[0] = (UChar)0;
1486
1487    /* squeeze out the reg field from mod_reg_rm, since a 256-entry
1488       jump table seems a bit excessive. 
1489    */
1490    mod_reg_rm &= 0xC7;                      /* is now XX000YYY */
1491    mod_reg_rm  = toUChar(mod_reg_rm | (mod_reg_rm >> 3));  
1492                                             /* is now XX0XXYYY */
1493    mod_reg_rm &= 0x1F;                      /* is now 000XXYYY */
1494    switch (mod_reg_rm) {
1495
1496       /* (%eax) .. (%edi), not including (%esp) or (%ebp).
1497          --> GET %reg, t 
1498       */
1499       case 0x00: case 0x01: case 0x02: case 0x03: 
1500       /* ! 04 */ /* ! 05 */ case 0x06: case 0x07:
1501          { UChar rm = mod_reg_rm;
1502            DIS(buf, "%s(%s)", sorbTxt(sorb), nameIReg(4,rm));
1503            *len = 1;
1504            return disAMode_copy2tmp(
1505                   handleSegOverride(sorb, getIReg(4,rm)));
1506          }
1507
1508       /* d8(%eax) ... d8(%edi), not including d8(%esp) 
1509          --> GET %reg, t ; ADDL d8, t
1510       */
1511       case 0x08: case 0x09: case 0x0A: case 0x0B: 
1512       /* ! 0C */ case 0x0D: case 0x0E: case 0x0F:
1513          { UChar rm = toUChar(mod_reg_rm & 7);
1514            UInt  d  = getSDisp8(delta);
1515            DIS(buf, "%s%d(%s)", sorbTxt(sorb), (Int)d, nameIReg(4,rm));
1516            *len = 2;
1517            return disAMode_copy2tmp(
1518                   handleSegOverride(sorb,
1519                      binop(Iop_Add32,getIReg(4,rm),mkU32(d))));
1520          }
1521
1522       /* d32(%eax) ... d32(%edi), not including d32(%esp)
1523          --> GET %reg, t ; ADDL d8, t
1524       */
1525       case 0x10: case 0x11: case 0x12: case 0x13: 
1526       /* ! 14 */ case 0x15: case 0x16: case 0x17:
1527          { UChar rm = toUChar(mod_reg_rm & 7);
1528            UInt  d  = getUDisp32(delta);
1529            DIS(buf, "%s0x%x(%s)", sorbTxt(sorb), (Int)d, nameIReg(4,rm));
1530            *len = 5;
1531            return disAMode_copy2tmp(
1532                   handleSegOverride(sorb,
1533                      binop(Iop_Add32,getIReg(4,rm),mkU32(d))));
1534          }
1535
1536       /* a register, %eax .. %edi.  This shouldn't happen. */
1537       case 0x18: case 0x19: case 0x1A: case 0x1B:
1538       case 0x1C: case 0x1D: case 0x1E: case 0x1F:
1539          vpanic("disAMode(x86): not an addr!");
1540
1541       /* a 32-bit literal address
1542          --> MOV d32, tmp 
1543       */
1544       case 0x05: 
1545          { UInt d = getUDisp32(delta);
1546            *len = 5;
1547            DIS(buf, "%s(0x%x)", sorbTxt(sorb), d);
1548            return disAMode_copy2tmp( 
1549                      handleSegOverride(sorb, mkU32(d)));
1550          }
1551
1552       case 0x04: {
1553          /* SIB, with no displacement.  Special cases:
1554             -- %esp cannot act as an index value.  
1555                If index_r indicates %esp, zero is used for the index.
1556             -- when mod is zero and base indicates EBP, base is instead
1557                a 32-bit literal.
1558             It's all madness, I tell you.  Extract %index, %base and 
1559             scale from the SIB byte.  The value denoted is then:
1560                | %index == %ESP && %base == %EBP
1561                = d32 following SIB byte
1562                | %index == %ESP && %base != %EBP
1563                = %base
1564                | %index != %ESP && %base == %EBP
1565                = d32 following SIB byte + (%index << scale)
1566                | %index != %ESP && %base != %ESP
1567                = %base + (%index << scale)
1568
1569             What happens to the souls of CPU architects who dream up such
1570             horrendous schemes, do you suppose?  
1571          */
1572          UChar sib     = getIByte(delta);
1573          UChar scale   = toUChar((sib >> 6) & 3);
1574          UChar index_r = toUChar((sib >> 3) & 7);
1575          UChar base_r  = toUChar(sib & 7);
1576          delta++;
1577
1578          if (index_r != R_ESP && base_r != R_EBP) {
1579             DIS(buf, "%s(%s,%s,%d)", sorbTxt(sorb), 
1580                       nameIReg(4,base_r), nameIReg(4,index_r), 1<<scale);
1581             *len = 2;
1582             return
1583                disAMode_copy2tmp( 
1584                handleSegOverride(sorb,
1585                   binop(Iop_Add32, 
1586                         getIReg(4,base_r),
1587                         binop(Iop_Shl32, getIReg(4,index_r),
1588                               mkU8(scale)))));
1589          }
1590
1591          if (index_r != R_ESP && base_r == R_EBP) {
1592             UInt d = getUDisp32(delta);
1593             DIS(buf, "%s0x%x(,%s,%d)", sorbTxt(sorb), d, 
1594                       nameIReg(4,index_r), 1<<scale);
1595             *len = 6;
1596             return
1597                disAMode_copy2tmp(
1598                handleSegOverride(sorb, 
1599                   binop(Iop_Add32,
1600                         binop(Iop_Shl32, getIReg(4,index_r), mkU8(scale)),
1601                         mkU32(d))));
1602          }
1603
1604          if (index_r == R_ESP && base_r != R_EBP) {
1605             DIS(buf, "%s(%s,,)", sorbTxt(sorb), nameIReg(4,base_r));
1606             *len = 2;
1607             return disAMode_copy2tmp(
1608                    handleSegOverride(sorb, getIReg(4,base_r)));
1609          }
1610
1611          if (index_r == R_ESP && base_r == R_EBP) {
1612             UInt d = getUDisp32(delta);
1613             DIS(buf, "%s0x%x(,,)", sorbTxt(sorb), d);
1614             *len = 6;
1615             return disAMode_copy2tmp(
1616                    handleSegOverride(sorb, mkU32(d)));
1617          }
1618          /*NOTREACHED*/
1619          vassert(0);
1620       }
1621
1622       /* SIB, with 8-bit displacement.  Special cases:
1623          -- %esp cannot act as an index value.  
1624             If index_r indicates %esp, zero is used for the index.
1625          Denoted value is:
1626             | %index == %ESP
1627             = d8 + %base
1628             | %index != %ESP
1629             = d8 + %base + (%index << scale)
1630       */
1631       case 0x0C: {
1632          UChar sib     = getIByte(delta);
1633          UChar scale   = toUChar((sib >> 6) & 3);
1634          UChar index_r = toUChar((sib >> 3) & 7);
1635          UChar base_r  = toUChar(sib & 7);
1636          UInt  d       = getSDisp8(delta+1);
1637
1638          if (index_r == R_ESP) {
1639             DIS(buf, "%s%d(%s,,)", sorbTxt(sorb), 
1640                                    (Int)d, nameIReg(4,base_r));
1641             *len = 3;
1642             return disAMode_copy2tmp(
1643                    handleSegOverride(sorb, 
1644                       binop(Iop_Add32, getIReg(4,base_r), mkU32(d)) ));
1645          } else {
1646             DIS(buf, "%s%d(%s,%s,%d)", sorbTxt(sorb), (Int)d, 
1647                      nameIReg(4,base_r), nameIReg(4,index_r), 1<<scale);
1648             *len = 3;
1649             return 
1650                 disAMode_copy2tmp(
1651                 handleSegOverride(sorb,
1652                   binop(Iop_Add32,
1653                         binop(Iop_Add32, 
1654                               getIReg(4,base_r), 
1655                               binop(Iop_Shl32, 
1656                                     getIReg(4,index_r), mkU8(scale))),
1657                         mkU32(d))));
1658          }
1659          /*NOTREACHED*/
1660          vassert(0);
1661       }
1662
1663       /* SIB, with 32-bit displacement.  Special cases:
1664          -- %esp cannot act as an index value.  
1665             If index_r indicates %esp, zero is used for the index.
1666          Denoted value is:
1667             | %index == %ESP
1668             = d32 + %base
1669             | %index != %ESP
1670             = d32 + %base + (%index << scale)
1671       */
1672       case 0x14: {
1673          UChar sib     = getIByte(delta);
1674          UChar scale   = toUChar((sib >> 6) & 3);
1675          UChar index_r = toUChar((sib >> 3) & 7);
1676          UChar base_r  = toUChar(sib & 7);
1677          UInt d        = getUDisp32(delta+1);
1678
1679          if (index_r == R_ESP) {
1680             DIS(buf, "%s%d(%s,,)", sorbTxt(sorb), 
1681                                    (Int)d, nameIReg(4,base_r));
1682             *len = 6;
1683             return disAMode_copy2tmp(
1684                    handleSegOverride(sorb, 
1685                       binop(Iop_Add32, getIReg(4,base_r), mkU32(d)) ));
1686          } else {
1687             DIS(buf, "%s%d(%s,%s,%d)", sorbTxt(sorb), (Int)d, 
1688                      nameIReg(4,base_r), nameIReg(4,index_r), 1<<scale);
1689             *len = 6;
1690             return 
1691                 disAMode_copy2tmp(
1692                 handleSegOverride(sorb,
1693                   binop(Iop_Add32,
1694                         binop(Iop_Add32, 
1695                               getIReg(4,base_r), 
1696                               binop(Iop_Shl32, 
1697                                     getIReg(4,index_r), mkU8(scale))),
1698                         mkU32(d))));
1699          }
1700          /*NOTREACHED*/
1701          vassert(0);
1702       }
1703
1704       default:
1705          vpanic("disAMode(x86)");
1706          return 0; /*notreached*/
1707    }
1708 }
1709
1710
1711 /* Figure out the number of (insn-stream) bytes constituting the amode
1712    beginning at delta.  Is useful for getting hold of literals beyond
1713    the end of the amode before it has been disassembled.  */
1714
1715 static UInt lengthAMode ( Int delta )
1716 {
1717    UChar mod_reg_rm = getIByte(delta); delta++;
1718
1719    /* squeeze out the reg field from mod_reg_rm, since a 256-entry
1720       jump table seems a bit excessive. 
1721    */
1722    mod_reg_rm &= 0xC7;               /* is now XX000YYY */
1723    mod_reg_rm  = toUChar(mod_reg_rm | (mod_reg_rm >> 3));  
1724                                      /* is now XX0XXYYY */
1725    mod_reg_rm &= 0x1F;               /* is now 000XXYYY */
1726    switch (mod_reg_rm) {
1727
1728       /* (%eax) .. (%edi), not including (%esp) or (%ebp). */
1729       case 0x00: case 0x01: case 0x02: case 0x03: 
1730       /* ! 04 */ /* ! 05 */ case 0x06: case 0x07:
1731          return 1;
1732
1733       /* d8(%eax) ... d8(%edi), not including d8(%esp). */ 
1734       case 0x08: case 0x09: case 0x0A: case 0x0B: 
1735       /* ! 0C */ case 0x0D: case 0x0E: case 0x0F:
1736          return 2;
1737
1738       /* d32(%eax) ... d32(%edi), not including d32(%esp). */
1739       case 0x10: case 0x11: case 0x12: case 0x13: 
1740       /* ! 14 */ case 0x15: case 0x16: case 0x17:
1741          return 5;
1742
1743       /* a register, %eax .. %edi.  (Not an addr, but still handled.) */
1744       case 0x18: case 0x19: case 0x1A: case 0x1B:
1745       case 0x1C: case 0x1D: case 0x1E: case 0x1F:
1746          return 1;
1747
1748       /* a 32-bit literal address. */
1749       case 0x05: return 5;
1750
1751       /* SIB, no displacement.  */
1752       case 0x04: {
1753          UChar sib    = getIByte(delta);
1754          UChar base_r = toUChar(sib & 7);
1755          if (base_r == R_EBP) return 6; else return 2;
1756       }
1757       /* SIB, with 8-bit displacement.  */
1758       case 0x0C: return 3;
1759
1760       /* SIB, with 32-bit displacement.  */
1761       case 0x14: return 6;
1762
1763       default:
1764          vpanic("lengthAMode");
1765          return 0; /*notreached*/
1766    }
1767 }
1768
1769 /*------------------------------------------------------------*/
1770 /*--- Disassembling common idioms                          ---*/
1771 /*------------------------------------------------------------*/
1772
1773 /* Handle binary integer instructions of the form
1774       op E, G  meaning
1775       op reg-or-mem, reg
1776    Is passed the a ptr to the modRM byte, the actual operation, and the
1777    data size.  Returns the address advanced completely over this
1778    instruction.
1779
1780    E(src) is reg-or-mem
1781    G(dst) is reg.
1782
1783    If E is reg, -->    GET %G,  tmp
1784                        OP %E,   tmp
1785                        PUT tmp, %G
1786  
1787    If E is mem and OP is not reversible, 
1788                 -->    (getAddr E) -> tmpa
1789                        LD (tmpa), tmpa
1790                        GET %G, tmp2
1791                        OP tmpa, tmp2
1792                        PUT tmp2, %G
1793
1794    If E is mem and OP is reversible
1795                 -->    (getAddr E) -> tmpa
1796                        LD (tmpa), tmpa
1797                        OP %G, tmpa
1798                        PUT tmpa, %G
1799 */
1800 static
1801 UInt dis_op2_E_G ( UChar       sorb,
1802                    Bool        addSubCarry,
1803                    IROp        op8, 
1804                    Bool        keep,
1805                    Int         size, 
1806                    Int         delta0,
1807                    HChar*      t_x86opc )
1808 {
1809    HChar   dis_buf[50];
1810    Int     len;
1811    IRType  ty   = szToITy(size);
1812    IRTemp  dst1 = newTemp(ty);
1813    IRTemp  src  = newTemp(ty);
1814    IRTemp  dst0 = newTemp(ty);
1815    UChar   rm   = getUChar(delta0);
1816    IRTemp  addr = IRTemp_INVALID;
1817
1818    /* addSubCarry == True indicates the intended operation is
1819       add-with-carry or subtract-with-borrow. */
1820    if (addSubCarry) {
1821       vassert(op8 == Iop_Add8 || op8 == Iop_Sub8);
1822       vassert(keep);
1823    }
1824
1825    if (epartIsReg(rm)) {
1826       /* Specially handle XOR reg,reg, because that doesn't really
1827          depend on reg, and doing the obvious thing potentially
1828          generates a spurious value check failure due to the bogus
1829          dependency.  Ditto SBB reg,reg. */
1830       if ((op8 == Iop_Xor8 || (op8 == Iop_Sub8 && addSubCarry))
1831           && gregOfRM(rm) == eregOfRM(rm)) {
1832          putIReg(size, gregOfRM(rm), mkU(ty,0));
1833       }
1834       assign( dst0, getIReg(size,gregOfRM(rm)) );
1835       assign( src,  getIReg(size,eregOfRM(rm)) );
1836
1837       if (addSubCarry && op8 == Iop_Add8) {
1838          helper_ADC( size, dst1, dst0, src,
1839                      /*no store*/IRTemp_INVALID, IRTemp_INVALID, 0 );
1840          putIReg(size, gregOfRM(rm), mkexpr(dst1));
1841       } else
1842       if (addSubCarry && op8 == Iop_Sub8) {
1843          helper_SBB( size, dst1, dst0, src,
1844                      /*no store*/IRTemp_INVALID, IRTemp_INVALID, 0 );
1845          putIReg(size, gregOfRM(rm), mkexpr(dst1));
1846       } else {
1847          assign( dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)) );
1848          if (isAddSub(op8))
1849             setFlags_DEP1_DEP2(op8, dst0, src, ty);
1850          else
1851             setFlags_DEP1(op8, dst1, ty);
1852          if (keep)
1853             putIReg(size, gregOfRM(rm), mkexpr(dst1));
1854       }
1855
1856       DIP("%s%c %s,%s\n", t_x86opc, nameISize(size), 
1857                           nameIReg(size,eregOfRM(rm)),
1858                           nameIReg(size,gregOfRM(rm)));
1859       return 1+delta0;
1860    } else {
1861       /* E refers to memory */
1862       addr = disAMode ( &len, sorb, delta0, dis_buf);
1863       assign( dst0, getIReg(size,gregOfRM(rm)) );
1864       assign( src,  loadLE(szToITy(size), mkexpr(addr)) );
1865
1866       if (addSubCarry && op8 == Iop_Add8) {
1867          helper_ADC( size, dst1, dst0, src,
1868                      /*no store*/IRTemp_INVALID, IRTemp_INVALID, 0 );
1869          putIReg(size, gregOfRM(rm), mkexpr(dst1));
1870       } else
1871       if (addSubCarry && op8 == Iop_Sub8) {
1872          helper_SBB( size, dst1, dst0, src,
1873                      /*no store*/IRTemp_INVALID, IRTemp_INVALID, 0 );
1874          putIReg(size, gregOfRM(rm), mkexpr(dst1));
1875       } else {
1876          assign( dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)) );
1877          if (isAddSub(op8))
1878             setFlags_DEP1_DEP2(op8, dst0, src, ty);
1879          else
1880             setFlags_DEP1(op8, dst1, ty);
1881          if (keep)
1882             putIReg(size, gregOfRM(rm), mkexpr(dst1));
1883       }
1884
1885       DIP("%s%c %s,%s\n", t_x86opc, nameISize(size), 
1886                           dis_buf,nameIReg(size,gregOfRM(rm)));
1887       return len+delta0;
1888    }
1889 }
1890
1891
1892
1893 /* Handle binary integer instructions of the form
1894       op G, E  meaning
1895       op reg, reg-or-mem
1896    Is passed the a ptr to the modRM byte, the actual operation, and the
1897    data size.  Returns the address advanced completely over this
1898    instruction.
1899
1900    G(src) is reg.
1901    E(dst) is reg-or-mem
1902
1903    If E is reg, -->    GET %E,  tmp
1904                        OP %G,   tmp
1905                        PUT tmp, %E
1906  
1907    If E is mem, -->    (getAddr E) -> tmpa
1908                        LD (tmpa), tmpv
1909                        OP %G, tmpv
1910                        ST tmpv, (tmpa)
1911 */
1912 static
1913 UInt dis_op2_G_E ( UChar       sorb,
1914                    Bool        locked,
1915                    Bool        addSubCarry,
1916                    IROp        op8, 
1917                    Bool        keep,
1918                    Int         size, 
1919                    Int         delta0,
1920                    HChar*      t_x86opc )
1921 {
1922    HChar   dis_buf[50];
1923    Int     len;
1924    IRType  ty   = szToITy(size);
1925    IRTemp  dst1 = newTemp(ty);
1926    IRTemp  src  = newTemp(ty);
1927    IRTemp  dst0 = newTemp(ty);
1928    UChar   rm   = getIByte(delta0);
1929    IRTemp  addr = IRTemp_INVALID;
1930
1931    /* addSubCarry == True indicates the intended operation is
1932       add-with-carry or subtract-with-borrow. */
1933    if (addSubCarry) {
1934       vassert(op8 == Iop_Add8 || op8 == Iop_Sub8);
1935       vassert(keep);
1936    }
1937
1938    if (epartIsReg(rm)) {
1939       /* Specially handle XOR reg,reg, because that doesn't really
1940          depend on reg, and doing the obvious thing potentially
1941          generates a spurious value check failure due to the bogus
1942          dependency.  Ditto SBB reg,reg.*/
1943       if ((op8 == Iop_Xor8 || (op8 == Iop_Sub8 && addSubCarry))
1944           && gregOfRM(rm) == eregOfRM(rm)) {
1945          putIReg(size, eregOfRM(rm), mkU(ty,0));
1946       }
1947       assign(dst0, getIReg(size,eregOfRM(rm)));
1948       assign(src,  getIReg(size,gregOfRM(rm)));
1949
1950       if (addSubCarry && op8 == Iop_Add8) {
1951          helper_ADC( size, dst1, dst0, src,
1952                      /*no store*/IRTemp_INVALID, IRTemp_INVALID, 0 );
1953          putIReg(size, eregOfRM(rm), mkexpr(dst1));
1954       } else
1955       if (addSubCarry && op8 == Iop_Sub8) {
1956          helper_SBB( size, dst1, dst0, src,
1957                      /*no store*/IRTemp_INVALID, IRTemp_INVALID, 0 );
1958          putIReg(size, eregOfRM(rm), mkexpr(dst1));
1959       } else {
1960          assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)));
1961          if (isAddSub(op8))
1962             setFlags_DEP1_DEP2(op8, dst0, src, ty);
1963          else
1964             setFlags_DEP1(op8, dst1, ty);
1965          if (keep)
1966             putIReg(size, eregOfRM(rm), mkexpr(dst1));
1967       }
1968
1969       DIP("%s%c %s,%s\n", t_x86opc, nameISize(size), 
1970                           nameIReg(size,gregOfRM(rm)),
1971                           nameIReg(size,eregOfRM(rm)));
1972       return 1+delta0;
1973    }
1974
1975    /* E refers to memory */    
1976    {
1977       addr = disAMode ( &len, sorb, delta0, dis_buf);
1978       assign(dst0, loadLE(ty,mkexpr(addr)));
1979       assign(src,  getIReg(size,gregOfRM(rm)));
1980
1981       if (addSubCarry && op8 == Iop_Add8) {
1982          if (locked) {
1983             /* cas-style store */
1984             helper_ADC( size, dst1, dst0, src,
1985                         /*store*/addr, dst0/*expVal*/, guest_EIP_curr_instr );
1986          } else {
1987             /* normal store */
1988             helper_ADC( size, dst1, dst0, src,
1989                         /*store*/addr, IRTemp_INVALID, 0 );
1990          }
1991       } else
1992       if (addSubCarry && op8 == Iop_Sub8) {
1993          if (locked) {
1994             /* cas-style store */
1995             helper_SBB( size, dst1, dst0, src,
1996                         /*store*/addr, dst0/*expVal*/, guest_EIP_curr_instr );
1997          } else {
1998             /* normal store */
1999             helper_SBB( size, dst1, dst0, src,
2000                         /*store*/addr, IRTemp_INVALID, 0 );
2001          }
2002       } else {
2003          assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)));
2004          if (keep) {
2005             if (locked) {
2006                if (0) vex_printf("locked case\n" );
2007                casLE( mkexpr(addr),
2008                       mkexpr(dst0)/*expval*/, 
2009                       mkexpr(dst1)/*newval*/, guest_EIP_curr_instr );
2010             } else {
2011                if (0) vex_printf("nonlocked case\n");
2012                storeLE(mkexpr(addr), mkexpr(dst1));
2013             }
2014          }
2015          if (isAddSub(op8))
2016             setFlags_DEP1_DEP2(op8, dst0, src, ty);
2017          else
2018             setFlags_DEP1(op8, dst1, ty);
2019       }
2020
2021       DIP("%s%c %s,%s\n", t_x86opc, nameISize(size), 
2022                           nameIReg(size,gregOfRM(rm)), dis_buf);
2023       return len+delta0;
2024    }
2025 }
2026
2027
2028 /* Handle move instructions of the form
2029       mov E, G  meaning
2030       mov reg-or-mem, reg
2031    Is passed the a ptr to the modRM byte, and the data size.  Returns
2032    the address advanced completely over this instruction.
2033
2034    E(src) is reg-or-mem
2035    G(dst) is reg.
2036
2037    If E is reg, -->    GET %E,  tmpv
2038                        PUT tmpv, %G
2039  
2040    If E is mem  -->    (getAddr E) -> tmpa
2041                        LD (tmpa), tmpb
2042                        PUT tmpb, %G
2043 */
2044 static
2045 UInt dis_mov_E_G ( UChar       sorb,
2046                    Int         size, 
2047                    Int         delta0 )
2048 {
2049    Int len;
2050    UChar rm = getIByte(delta0);
2051    HChar dis_buf[50];
2052
2053    if (epartIsReg(rm)) {
2054       putIReg(size, gregOfRM(rm), getIReg(size, eregOfRM(rm)));
2055       DIP("mov%c %s,%s\n", nameISize(size), 
2056                            nameIReg(size,eregOfRM(rm)),
2057                            nameIReg(size,gregOfRM(rm)));
2058       return 1+delta0;
2059    }
2060
2061    /* E refers to memory */    
2062    {
2063       IRTemp addr = disAMode ( &len, sorb, delta0, dis_buf );
2064       putIReg(size, gregOfRM(rm), loadLE(szToITy(size), mkexpr(addr)));
2065       DIP("mov%c %s,%s\n", nameISize(size), 
2066                            dis_buf,nameIReg(size,gregOfRM(rm)));
2067       return delta0+len;
2068    }
2069 }
2070
2071
2072 /* Handle move instructions of the form
2073       mov G, E  meaning
2074       mov reg, reg-or-mem
2075    Is passed the a ptr to the modRM byte, and the data size.  Returns
2076    the address advanced completely over this instruction.
2077
2078    G(src) is reg.
2079    E(dst) is reg-or-mem
2080
2081    If E is reg, -->    GET %G,  tmp
2082                        PUT tmp, %E
2083  
2084    If E is mem, -->    (getAddr E) -> tmpa
2085                        GET %G, tmpv
2086                        ST tmpv, (tmpa) 
2087 */
2088 static
2089 UInt dis_mov_G_E ( UChar       sorb,
2090                    Int         size, 
2091                    Int         delta0 )
2092 {
2093    Int len;
2094    UChar rm = getIByte(delta0);
2095    HChar dis_buf[50];
2096
2097    if (epartIsReg(rm)) {
2098       putIReg(size, eregOfRM(rm), getIReg(size, gregOfRM(rm)));
2099       DIP("mov%c %s,%s\n", nameISize(size), 
2100                            nameIReg(size,gregOfRM(rm)),
2101                            nameIReg(size,eregOfRM(rm)));
2102       return 1+delta0;
2103    }
2104
2105    /* E refers to memory */    
2106    {
2107       IRTemp addr = disAMode ( &len, sorb, delta0, dis_buf);
2108       storeLE( mkexpr(addr), getIReg(size, gregOfRM(rm)) );
2109       DIP("mov%c %s,%s\n", nameISize(size), 
2110                            nameIReg(size,gregOfRM(rm)), dis_buf);
2111       return len+delta0;
2112    }
2113 }
2114
2115
2116 /* op $immediate, AL/AX/EAX. */
2117 static
2118 UInt dis_op_imm_A ( Int    size,
2119                     Bool   carrying,
2120                     IROp   op8,
2121                     Bool   keep,
2122                     Int    delta,
2123                     HChar* t_x86opc )
2124 {
2125    IRType ty   = szToITy(size);
2126    IRTemp dst0 = newTemp(ty);
2127    IRTemp src  = newTemp(ty);
2128    IRTemp dst1 = newTemp(ty);
2129    UInt lit    = getUDisp(size,delta);
2130    assign(dst0, getIReg(size,R_EAX));
2131    assign(src,  mkU(ty,lit));
2132
2133    if (isAddSub(op8) && !carrying) {
2134       assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)) );
2135       setFlags_DEP1_DEP2(op8, dst0, src, ty);
2136    } 
2137    else
2138    if (isLogic(op8)) {
2139       vassert(!carrying);
2140       assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)) );
2141       setFlags_DEP1(op8, dst1, ty);
2142    } 
2143    else
2144    if (op8 == Iop_Add8 && carrying) {
2145       helper_ADC( size, dst1, dst0, src,
2146                   /*no store*/IRTemp_INVALID, IRTemp_INVALID, 0 );
2147    }
2148    else
2149    if (op8 == Iop_Sub8 && carrying) {
2150       helper_SBB( size, dst1, dst0, src,
2151                   /*no store*/IRTemp_INVALID, IRTemp_INVALID, 0 );
2152    }
2153    else
2154       vpanic("dis_op_imm_A(x86,guest)");
2155
2156    if (keep)
2157       putIReg(size, R_EAX, mkexpr(dst1));
2158
2159    DIP("%s%c $0x%x, %s\n", t_x86opc, nameISize(size), 
2160                            lit, nameIReg(size,R_EAX));
2161    return delta+size;
2162 }
2163
2164
2165 /* Sign- and Zero-extending moves. */
2166 static
2167 UInt dis_movx_E_G ( UChar      sorb,
2168                     Int delta, Int szs, Int szd, Bool sign_extend )
2169 {
2170    UChar rm = getIByte(delta);
2171    if (epartIsReg(rm)) {
2172       if (szd == szs) {
2173          // mutant case.  See #250799
2174          putIReg(szd, gregOfRM(rm),
2175                            getIReg(szs,eregOfRM(rm)));
2176       } else {
2177          // normal case
2178          putIReg(szd, gregOfRM(rm),
2179                       unop(mkWidenOp(szs,szd,sign_extend), 
2180                            getIReg(szs,eregOfRM(rm))));
2181       }
2182       DIP("mov%c%c%c %s,%s\n", sign_extend ? 's' : 'z',
2183                                nameISize(szs), nameISize(szd),
2184                                nameIReg(szs,eregOfRM(rm)),
2185                                nameIReg(szd,gregOfRM(rm)));
2186       return 1+delta;
2187    }
2188
2189    /* E refers to memory */    
2190    {
2191       Int    len;
2192       HChar  dis_buf[50];
2193       IRTemp addr = disAMode ( &len, sorb, delta, dis_buf );
2194       if (szd == szs) {
2195          // mutant case.  See #250799
2196          putIReg(szd, gregOfRM(rm),
2197                            loadLE(szToITy(szs),mkexpr(addr)));
2198       } else {
2199          // normal case
2200          putIReg(szd, gregOfRM(rm),
2201                       unop(mkWidenOp(szs,szd,sign_extend), 
2202                            loadLE(szToITy(szs),mkexpr(addr))));
2203       }
2204       DIP("mov%c%c%c %s,%s\n", sign_extend ? 's' : 'z',
2205                                nameISize(szs), nameISize(szd),
2206                                dis_buf, nameIReg(szd,gregOfRM(rm)));
2207       return len+delta;
2208    }
2209 }
2210
2211
2212 /* Generate code to divide ArchRegs EDX:EAX / DX:AX / AX by the 32 /
2213    16 / 8 bit quantity in the given IRTemp.  */
2214 static
2215 void codegen_div ( Int sz, IRTemp t, Bool signed_divide )
2216 {
2217    IROp   op    = signed_divide ? Iop_DivModS64to32 : Iop_DivModU64to32;
2218    IRTemp src64 = newTemp(Ity_I64);
2219    IRTemp dst64 = newTemp(Ity_I64);
2220    switch (sz) {
2221       case 4:
2222          assign( src64, binop(Iop_32HLto64, 
2223                               getIReg(4,R_EDX), getIReg(4,R_EAX)) );
2224          assign( dst64, binop(op, mkexpr(src64), mkexpr(t)) );
2225          putIReg( 4, R_EAX, unop(Iop_64to32,mkexpr(dst64)) );
2226          putIReg( 4, R_EDX, unop(Iop_64HIto32,mkexpr(dst64)) );
2227          break;
2228       case 2: {
2229          IROp widen3264 = signed_divide ? Iop_32Sto64 : Iop_32Uto64;
2230          IROp widen1632 = signed_divide ? Iop_16Sto32 : Iop_16Uto32;
2231          assign( src64, unop(widen3264,
2232                              binop(Iop_16HLto32, 
2233                                    getIReg(2,R_EDX), getIReg(2,R_EAX))) );
2234          assign( dst64, binop(op, mkexpr(src64), unop(widen1632,mkexpr(t))) );
2235          putIReg( 2, R_EAX, unop(Iop_32to16,unop(Iop_64to32,mkexpr(dst64))) );
2236          putIReg( 2, R_EDX, unop(Iop_32to16,unop(Iop_64HIto32,mkexpr(dst64))) );
2237          break;
2238       }
2239       case 1: {
2240          IROp widen3264 = signed_divide ? Iop_32Sto64 : Iop_32Uto64;
2241          IROp widen1632 = signed_divide ? Iop_16Sto32 : Iop_16Uto32;
2242          IROp widen816  = signed_divide ? Iop_8Sto16  : Iop_8Uto16;
2243          assign( src64, unop(widen3264, unop(widen1632, getIReg(2,R_EAX))) );
2244          assign( dst64, 
2245                  binop(op, mkexpr(src64), 
2246                            unop(widen1632, unop(widen816, mkexpr(t)))) );
2247          putIReg( 1, R_AL, unop(Iop_16to8, unop(Iop_32to16,
2248                            unop(Iop_64to32,mkexpr(dst64)))) );
2249          putIReg( 1, R_AH, unop(Iop_16to8, unop(Iop_32to16,
2250                            unop(Iop_64HIto32,mkexpr(dst64)))) );
2251          break;
2252       }
2253       default: vpanic("codegen_div(x86)");
2254    }
2255 }
2256
2257
2258 static 
2259 UInt dis_Grp1 ( UChar sorb, Bool locked,
2260                 Int delta, UChar modrm, 
2261                 Int am_sz, Int d_sz, Int sz, UInt d32 )
2262 {
2263    Int     len;
2264    HChar   dis_buf[50];
2265    IRType  ty   = szToITy(sz);
2266    IRTemp  dst1 = newTemp(ty);
2267    IRTemp  src  = newTemp(ty);
2268    IRTemp  dst0 = newTemp(ty);
2269    IRTemp  addr = IRTemp_INVALID;
2270    IROp    op8  = Iop_INVALID;
2271    UInt    mask = sz==1 ? 0xFF : (sz==2 ? 0xFFFF : 0xFFFFFFFF);
2272
2273    switch (gregOfRM(modrm)) {
2274       case 0: op8 = Iop_Add8; break;  case 1: op8 = Iop_Or8;  break;
2275       case 2: break;  // ADC
2276       case 3: break;  // SBB
2277       case 4: op8 = Iop_And8; break;  case 5: op8 = Iop_Sub8; break;
2278       case 6: op8 = Iop_Xor8; break;  case 7: op8 = Iop_Sub8; break;
2279       /*NOTREACHED*/
2280       default: vpanic("dis_Grp1: unhandled case");
2281    }
2282
2283    if (epartIsReg(modrm)) {
2284       vassert(am_sz == 1);
2285
2286       assign(dst0, getIReg(sz,eregOfRM(modrm)));
2287       assign(src,  mkU(ty,d32 & mask));
2288
2289       if (gregOfRM(modrm) == 2 /* ADC */) {
2290          helper_ADC( sz, dst1, dst0, src,
2291                      /*no store*/IRTemp_INVALID, IRTemp_INVALID, 0 );
2292       } else 
2293       if (gregOfRM(modrm) == 3 /* SBB */) {
2294          helper_SBB( sz, dst1, dst0, src,
2295                      /*no store*/IRTemp_INVALID, IRTemp_INVALID, 0 );
2296       } else {
2297          assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)));
2298          if (isAddSub(op8))
2299             setFlags_DEP1_DEP2(op8, dst0, src, ty);
2300          else
2301             setFlags_DEP1(op8, dst1, ty);
2302       }
2303
2304       if (gregOfRM(modrm) < 7)
2305          putIReg(sz, eregOfRM(modrm), mkexpr(dst1));
2306
2307       delta += (am_sz + d_sz);
2308       DIP("%s%c $0x%x, %s\n", nameGrp1(gregOfRM(modrm)), nameISize(sz), d32, 
2309                               nameIReg(sz,eregOfRM(modrm)));
2310    } else {
2311       addr = disAMode ( &len, sorb, delta, dis_buf);
2312
2313       assign(dst0, loadLE(ty,mkexpr(addr)));
2314       assign(src, mkU(ty,d32 & mask));
2315
2316       if (gregOfRM(modrm) == 2 /* ADC */) {
2317          if (locked) {
2318             /* cas-style store */
2319             helper_ADC( sz, dst1, dst0, src,
2320                        /*store*/addr, dst0/*expVal*/, guest_EIP_curr_instr );
2321          } else {
2322             /* normal store */
2323             helper_ADC( sz, dst1, dst0, src,
2324                         /*store*/addr, IRTemp_INVALID, 0 );
2325          }
2326       } else 
2327       if (gregOfRM(modrm) == 3 /* SBB */) {
2328          if (locked) {
2329             /* cas-style store */
2330             helper_SBB( sz, dst1, dst0, src,
2331                        /*store*/addr, dst0/*expVal*/, guest_EIP_curr_instr );
2332          } else {
2333             /* normal store */
2334             helper_SBB( sz, dst1, dst0, src,
2335                         /*store*/addr, IRTemp_INVALID, 0 );
2336          }
2337       } else {
2338          assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)));
2339          if (gregOfRM(modrm) < 7) {
2340             if (locked) {
2341                casLE( mkexpr(addr), mkexpr(dst0)/*expVal*/, 
2342                                     mkexpr(dst1)/*newVal*/,
2343                                     guest_EIP_curr_instr );
2344             } else {
2345                storeLE(mkexpr(addr), mkexpr(dst1));
2346             }
2347          }
2348          if (isAddSub(op8))
2349             setFlags_DEP1_DEP2(op8, dst0, src, ty);
2350          else
2351             setFlags_DEP1(op8, dst1, ty);
2352       }
2353
2354       delta += (len+d_sz);
2355       DIP("%s%c $0x%x, %s\n", nameGrp1(gregOfRM(modrm)), nameISize(sz),
2356                               d32, dis_buf);
2357    }
2358    return delta;
2359 }
2360
2361
2362 /* Group 2 extended opcodes.  shift_expr must be an 8-bit typed
2363    expression. */
2364
2365 static
2366 UInt dis_Grp2 ( UChar sorb,
2367                 Int delta, UChar modrm,
2368                 Int am_sz, Int d_sz, Int sz, IRExpr* shift_expr,
2369                 HChar* shift_expr_txt, Bool* decode_OK )
2370 {
2371    /* delta on entry points at the modrm byte. */
2372    HChar  dis_buf[50];
2373    Int    len;
2374    Bool   isShift, isRotate, isRotateC;
2375    IRType ty    = szToITy(sz);
2376    IRTemp dst0  = newTemp(ty);
2377    IRTemp dst1  = newTemp(ty);
2378    IRTemp addr  = IRTemp_INVALID;
2379
2380    *decode_OK = True;
2381
2382    vassert(sz == 1 || sz == 2 || sz == 4);
2383
2384    /* Put value to shift/rotate in dst0. */
2385    if (epartIsReg(modrm)) {
2386       assign(dst0, getIReg(sz, eregOfRM(modrm)));
2387       delta += (am_sz + d_sz);
2388    } else {
2389       addr = disAMode ( &len, sorb, delta, dis_buf);
2390       assign(dst0, loadLE(ty,mkexpr(addr)));
2391       delta += len + d_sz;
2392    }
2393
2394    isShift = False;
2395    switch (gregOfRM(modrm)) { case 4: case 5: case 7: isShift = True; }
2396
2397    isRotate = False;
2398    switch (gregOfRM(modrm)) { case 0: case 1: isRotate = True; }
2399
2400    isRotateC = False;
2401    switch (gregOfRM(modrm)) { case 2: case 3: isRotateC = True; }
2402
2403    if (gregOfRM(modrm) == 6) {
2404       *decode_OK = False;
2405       return delta;
2406    }
2407
2408    if (!isShift && !isRotate && !isRotateC) {
2409       /*NOTREACHED*/
2410       vpanic("dis_Grp2(Reg): unhandled case(x86)");
2411    }
2412
2413    if (isRotateC) {
2414       /* call a helper; these insns are so ridiculous they do not
2415          deserve better */
2416       Bool     left = toBool(gregOfRM(modrm) == 2);
2417       IRTemp   r64  = newTemp(Ity_I64);
2418       IRExpr** args 
2419          = mkIRExprVec_4( widenUto32(mkexpr(dst0)), /* thing to rotate */
2420                           widenUto32(shift_expr),   /* rotate amount */
2421                           widenUto32(mk_x86g_calculate_eflags_all()),
2422                           mkU32(sz) );
2423       assign( r64, mkIRExprCCall(
2424                       Ity_I64, 
2425                       0/*regparm*/, 
2426                       left ? "x86g_calculate_RCL" : "x86g_calculate_RCR", 
2427                       left ? &x86g_calculate_RCL  : &x86g_calculate_RCR,
2428                       args
2429                    )
2430             );
2431       /* new eflags in hi half r64; new value in lo half r64 */
2432       assign( dst1, narrowTo(ty, unop(Iop_64to32, mkexpr(r64))) );
2433       stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(X86G_CC_OP_COPY) ));
2434       stmt( IRStmt_Put( OFFB_CC_DEP1, unop(Iop_64HIto32, mkexpr(r64)) ));
2435       stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0) ));
2436       /* Set NDEP even though it isn't used.  This makes redundant-PUT
2437          elimination of previous stores to this field work better. */
2438       stmt( IRStmt_Put( OFFB_CC_NDEP, mkU32(0) ));
2439    }
2440
2441    if (isShift) {
2442
2443       IRTemp pre32     = newTemp(Ity_I32);
2444       IRTemp res32     = newTemp(Ity_I32);
2445       IRTemp res32ss   = newTemp(Ity_I32);
2446       IRTemp shift_amt = newTemp(Ity_I8);
2447       IROp   op32;
2448
2449       switch (gregOfRM(modrm)) { 
2450          case 4: op32 = Iop_Shl32; break;
2451          case 5: op32 = Iop_Shr32; break;
2452          case 7: op32 = Iop_Sar32; break;
2453          /*NOTREACHED*/
2454          default: vpanic("dis_Grp2:shift"); break;
2455       }
2456
2457       /* Widen the value to be shifted to 32 bits, do the shift, and
2458          narrow back down.  This seems surprisingly long-winded, but
2459          unfortunately the Intel semantics requires that 8/16-bit
2460          shifts give defined results for shift values all the way up
2461          to 31, and this seems the simplest way to do it.  It has the
2462          advantage that the only IR level shifts generated are of 32
2463          bit values, and the shift amount is guaranteed to be in the
2464          range 0 .. 31, thereby observing the IR semantics requiring
2465          all shift values to be in the range 0 .. 2^word_size-1. */
2466
2467       /* shift_amt = shift_expr & 31, regardless of operation size */
2468       assign( shift_amt, binop(Iop_And8, shift_expr, mkU8(31)) );
2469
2470       /* suitably widen the value to be shifted to 32 bits. */
2471       assign( pre32, op32==Iop_Sar32 ? widenSto32(mkexpr(dst0))
2472                                      : widenUto32(mkexpr(dst0)) );
2473
2474       /* res32 = pre32 `shift` shift_amt */
2475       assign( res32, binop(op32, mkexpr(pre32), mkexpr(shift_amt)) );
2476
2477       /* res32ss = pre32 `shift` ((shift_amt - 1) & 31) */
2478       assign( res32ss,
2479               binop(op32,
2480                     mkexpr(pre32), 
2481                     binop(Iop_And8,
2482                           binop(Iop_Sub8,
2483                                 mkexpr(shift_amt), mkU8(1)),
2484                           mkU8(31))) );
2485
2486       /* Build the flags thunk. */
2487       setFlags_DEP1_DEP2_shift(op32, res32, res32ss, ty, shift_amt);
2488
2489       /* Narrow the result back down. */
2490       assign( dst1, narrowTo(ty, mkexpr(res32)) );
2491
2492    } /* if (isShift) */
2493
2494    else 
2495    if (isRotate) {
2496       Int    ccOp      = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : 2);
2497       Bool   left      = toBool(gregOfRM(modrm) == 0);
2498       IRTemp rot_amt   = newTemp(Ity_I8);
2499       IRTemp rot_amt32 = newTemp(Ity_I8);
2500       IRTemp oldFlags  = newTemp(Ity_I32);
2501
2502       /* rot_amt = shift_expr & mask */
2503       /* By masking the rotate amount thusly, the IR-level Shl/Shr
2504          expressions never shift beyond the word size and thus remain
2505          well defined. */
2506       assign(rot_amt32, binop(Iop_And8, shift_expr, mkU8(31)));
2507
2508       if (ty == Ity_I32)
2509          assign(rot_amt, mkexpr(rot_amt32));
2510       else
2511          assign(rot_amt, binop(Iop_And8, mkexpr(rot_amt32), mkU8(8*sz-1)));
2512
2513       if (left) {
2514
2515          /* dst1 = (dst0 << rot_amt) | (dst0 >>u (wordsize-rot_amt)) */
2516          assign(dst1, 
2517             binop( mkSizedOp(ty,Iop_Or8),
2518                    binop( mkSizedOp(ty,Iop_Shl8), 
2519                           mkexpr(dst0),
2520                           mkexpr(rot_amt)
2521                    ),
2522                    binop( mkSizedOp(ty,Iop_Shr8), 
2523                           mkexpr(dst0), 
2524                           binop(Iop_Sub8,mkU8(8*sz), mkexpr(rot_amt))
2525                    )
2526             )
2527          );
2528          ccOp += X86G_CC_OP_ROLB;
2529
2530       } else { /* right */
2531
2532          /* dst1 = (dst0 >>u rot_amt) | (dst0 << (wordsize-rot_amt)) */
2533          assign(dst1, 
2534             binop( mkSizedOp(ty,Iop_Or8),
2535                    binop( mkSizedOp(ty,Iop_Shr8), 
2536                           mkexpr(dst0),
2537                           mkexpr(rot_amt)
2538                    ),
2539                    binop( mkSizedOp(ty,Iop_Shl8), 
2540                           mkexpr(dst0), 
2541                           binop(Iop_Sub8,mkU8(8*sz), mkexpr(rot_amt))
2542                    )
2543             )
2544          );
2545          ccOp += X86G_CC_OP_RORB;
2546
2547       }
2548
2549       /* dst1 now holds the rotated value.  Build flag thunk.  We
2550          need the resulting value for this, and the previous flags.
2551          Except don't set it if the rotate count is zero. */
2552
2553       assign(oldFlags, mk_x86g_calculate_eflags_all());
2554
2555       /* CC_DEP1 is the rotated value.  CC_NDEP is flags before. */
2556       stmt( IRStmt_Put( OFFB_CC_OP,
2557                         IRExpr_Mux0X( mkexpr(rot_amt32),
2558                                       IRExpr_Get(OFFB_CC_OP,Ity_I32),
2559                                       mkU32(ccOp))) );
2560       stmt( IRStmt_Put( OFFB_CC_DEP1, 
2561                         IRExpr_Mux0X( mkexpr(rot_amt32),
2562                                       IRExpr_Get(OFFB_CC_DEP1,Ity_I32),
2563                                       widenUto32(mkexpr(dst1)))) );
2564       stmt( IRStmt_Put( OFFB_CC_DEP2, 
2565                         IRExpr_Mux0X( mkexpr(rot_amt32),
2566                                       IRExpr_Get(OFFB_CC_DEP2,Ity_I32),
2567                                       mkU32(0))) );
2568       stmt( IRStmt_Put( OFFB_CC_NDEP, 
2569                         IRExpr_Mux0X( mkexpr(rot_amt32),
2570                                       IRExpr_Get(OFFB_CC_NDEP,Ity_I32),
2571                                       mkexpr(oldFlags))) );
2572    } /* if (isRotate) */
2573
2574    /* Save result, and finish up. */
2575    if (epartIsReg(modrm)) {
2576       putIReg(sz, eregOfRM(modrm), mkexpr(dst1));
2577       if (vex_traceflags & VEX_TRACE_FE) {
2578          vex_printf("%s%c ",
2579                     nameGrp2(gregOfRM(modrm)), nameISize(sz) );
2580          if (shift_expr_txt)
2581             vex_printf("%s", shift_expr_txt);
2582          else
2583             ppIRExpr(shift_expr);
2584          vex_printf(", %s\n", nameIReg(sz,eregOfRM(modrm)));
2585       }
2586    } else {
2587       storeLE(mkexpr(addr), mkexpr(dst1));
2588       if (vex_traceflags & VEX_TRACE_FE) {
2589          vex_printf("%s%c ",
2590                     nameGrp2(gregOfRM(modrm)), nameISize(sz) );
2591          if (shift_expr_txt)
2592             vex_printf("%s", shift_expr_txt);
2593          else
2594             ppIRExpr(shift_expr);
2595          vex_printf(", %s\n", dis_buf);
2596       }
2597    }
2598    return delta;
2599 }
2600
2601
2602 /* Group 8 extended opcodes (but BT/BTS/BTC/BTR only). */
2603 static
2604 UInt dis_Grp8_Imm ( UChar sorb,
2605                     Bool locked,
2606                     Int delta, UChar modrm,
2607                     Int am_sz, Int sz, UInt src_val,
2608                     Bool* decode_OK )
2609 {
2610    /* src_val denotes a d8.
2611       And delta on entry points at the modrm byte. */
2612
2613    IRType ty     = szToITy(sz);
2614    IRTemp t2     = newTemp(Ity_I32);
2615    IRTemp t2m    = newTemp(Ity_I32);
2616    IRTemp t_addr = IRTemp_INVALID;
2617    HChar  dis_buf[50];
2618    UInt   mask;
2619
2620    /* we're optimists :-) */
2621    *decode_OK = True;
2622
2623    /* Limit src_val -- the bit offset -- to something within a word.
2624       The Intel docs say that literal offsets larger than a word are
2625       masked in this way. */
2626    switch (sz) {
2627       case 2:  src_val &= 15; break;
2628       case 4:  src_val &= 31; break;
2629       default: *decode_OK = False; return delta;
2630    }
2631
2632    /* Invent a mask suitable for the operation. */
2633    switch (gregOfRM(modrm)) {
2634       case 4: /* BT */  mask = 0;               break;
2635       case 5: /* BTS */ mask = 1 << src_val;    break;
2636       case 6: /* BTR */ mask = ~(1 << src_val); break;
2637       case 7: /* BTC */ mask = 1 << src_val;    break;
2638          /* If this needs to be extended, probably simplest to make a
2639             new function to handle the other cases (0 .. 3).  The
2640             Intel docs do however not indicate any use for 0 .. 3, so
2641             we don't expect this to happen. */
2642       default: *decode_OK = False; return delta;
2643    }
2644
2645    /* Fetch the value to be tested and modified into t2, which is
2646       32-bits wide regardless of sz. */
2647    if (epartIsReg(modrm)) {
2648       vassert(am_sz == 1);
2649       assign( t2, widenUto32(getIReg(sz, eregOfRM(modrm))) );
2650       delta += (am_sz + 1);
2651       DIP("%s%c $0x%x, %s\n", nameGrp8(gregOfRM(modrm)), nameISize(sz),
2652                               src_val, nameIReg(sz,eregOfRM(modrm)));
2653    } else {
2654       Int len;
2655       t_addr = disAMode ( &len, sorb, delta, dis_buf);
2656       delta  += (len+1);
2657       assign( t2, widenUto32(loadLE(ty, mkexpr(t_addr))) );
2658       DIP("%s%c $0x%x, %s\n", nameGrp8(gregOfRM(modrm)), nameISize(sz),
2659                               src_val, dis_buf);
2660    }
2661
2662    /* Compute the new value into t2m, if non-BT. */
2663    switch (gregOfRM(modrm)) {
2664       case 4: /* BT */
2665          break;
2666       case 5: /* BTS */
2667          assign( t2m, binop(Iop_Or32, mkU32(mask), mkexpr(t2)) );
2668          break;
2669       case 6: /* BTR */
2670          assign( t2m, binop(Iop_And32, mkU32(mask), mkexpr(t2)) );
2671          break;
2672       case 7: /* BTC */
2673          assign( t2m, binop(Iop_Xor32, mkU32(mask), mkexpr(t2)) );
2674          break;
2675       default: 
2676          /*NOTREACHED*/ /*the previous switch guards this*/
2677          vassert(0);
2678    }
2679
2680    /* Write the result back, if non-BT.  If the CAS fails then we
2681       side-exit from the trace at this point, and so the flag state is
2682       not affected.  This is of course as required. */
2683    if (gregOfRM(modrm) != 4 /* BT */) {
2684       if (epartIsReg(modrm)) {
2685          putIReg(sz, eregOfRM(modrm), narrowTo(ty, mkexpr(t2m)));
2686       } else {
2687          if (locked) {
2688             casLE( mkexpr(t_addr),
2689                    narrowTo(ty, mkexpr(t2))/*expd*/,
2690                    narrowTo(ty, mkexpr(t2m))/*new*/,
2691                    guest_EIP_curr_instr );
2692          } else {
2693             storeLE(mkexpr(t_addr), narrowTo(ty, mkexpr(t2m)));
2694          }
2695       }
2696    }
2697
2698    /* Copy relevant bit from t2 into the carry flag. */
2699    /* Flags: C=selected bit, O,S,Z,A,P undefined, so are set to zero. */
2700    stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(X86G_CC_OP_COPY) ));
2701    stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0) ));
2702    stmt( IRStmt_Put( 
2703             OFFB_CC_DEP1,
2704             binop(Iop_And32,
2705                   binop(Iop_Shr32, mkexpr(t2), mkU8(src_val)),
2706                   mkU32(1))
2707        ));
2708    /* Set NDEP even though it isn't used.  This makes redundant-PUT
2709       elimination of previous stores to this field work better. */
2710    stmt( IRStmt_Put( OFFB_CC_NDEP, mkU32(0) ));
2711
2712    return delta;
2713 }
2714
2715
2716 /* Signed/unsigned widening multiply.  Generate IR to multiply the
2717    value in EAX/AX/AL by the given IRTemp, and park the result in
2718    EDX:EAX/DX:AX/AX.
2719 */
2720 static void codegen_mulL_A_D ( Int sz, Bool syned, 
2721                                IRTemp tmp, HChar* tmp_txt )
2722 {
2723    IRType ty = szToITy(sz);
2724    IRTemp t1 = newTemp(ty);
2725
2726    assign( t1, getIReg(sz, R_EAX) );
2727
2728    switch (ty) {
2729       case Ity_I32: {
2730          IRTemp res64   = newTemp(Ity_I64);
2731          IRTemp resHi   = newTemp(Ity_I32);
2732          IRTemp resLo   = newTemp(Ity_I32);
2733          IROp   mulOp   = syned ? Iop_MullS32 : Iop_MullU32;
2734          UInt   tBaseOp = syned ? X86G_CC_OP_SMULB : X86G_CC_OP_UMULB;
2735          setFlags_MUL ( Ity_I32, t1, tmp, tBaseOp );
2736          assign( res64, binop(mulOp, mkexpr(t1), mkexpr(tmp)) );
2737          assign( resHi, unop(Iop_64HIto32,mkexpr(res64)));
2738          assign( resLo, unop(Iop_64to32,mkexpr(res64)));
2739          putIReg(4, R_EDX, mkexpr(resHi));
2740          putIReg(4, R_EAX, mkexpr(resLo));
2741          break;
2742       }
2743       case Ity_I16: {
2744          IRTemp res32   = newTemp(Ity_I32);
2745          IRTemp resHi   = newTemp(Ity_I16);
2746          IRTemp resLo   = newTemp(Ity_I16);
2747          IROp   mulOp   = syned ? Iop_MullS16 : Iop_MullU16;
2748          UInt   tBaseOp = syned ? X86G_CC_OP_SMULB : X86G_CC_OP_UMULB;
2749          setFlags_MUL ( Ity_I16, t1, tmp, tBaseOp );
2750          assign( res32, binop(mulOp, mkexpr(t1), mkexpr(tmp)) );
2751          assign( resHi, unop(Iop_32HIto16,mkexpr(res32)));
2752          assign( resLo, unop(Iop_32to16,mkexpr(res32)));
2753          putIReg(2, R_EDX, mkexpr(resHi));
2754          putIReg(2, R_EAX, mkexpr(resLo));
2755          break;
2756       }
2757       case Ity_I8: {
2758          IRTemp res16   = newTemp(Ity_I16);
2759          IRTemp resHi   = newTemp(Ity_I8);
2760          IRTemp resLo   = newTemp(Ity_I8);
2761          IROp   mulOp   = syned ? Iop_MullS8 : Iop_MullU8;
2762          UInt   tBaseOp = syned ? X86G_CC_OP_SMULB : X86G_CC_OP_UMULB;
2763          setFlags_MUL ( Ity_I8, t1, tmp, tBaseOp );
2764          assign( res16, binop(mulOp, mkexpr(t1), mkexpr(tmp)) );
2765          assign( resHi, unop(Iop_16HIto8,mkexpr(res16)));
2766          assign( resLo, unop(Iop_16to8,mkexpr(res16)));
2767          putIReg(2, R_EAX, mkexpr(res16));
2768          break;
2769       }
2770       default:
2771          vpanic("codegen_mulL_A_D(x86)");
2772    }
2773    DIP("%s%c %s\n", syned ? "imul" : "mul", nameISize(sz), tmp_txt);
2774 }
2775
2776
2777 /* Group 3 extended opcodes. */
2778 static 
2779 UInt dis_Grp3 ( UChar sorb, Bool locked, Int sz, Int delta, Bool* decode_OK )
2780 {
2781    UInt    d32;
2782    UChar   modrm;
2783    HChar   dis_buf[50];
2784    Int     len;
2785    IRTemp  addr;
2786    IRType  ty = szToITy(sz);
2787    IRTemp  t1 = newTemp(ty);
2788    IRTemp dst1, src, dst0;
2789
2790    *decode_OK = True; /* may change this later */
2791
2792    modrm = getIByte(delta);
2793
2794    if (locked && (gregOfRM(modrm) != 2 && gregOfRM(modrm) != 3)) {
2795       /* LOCK prefix only allowed with not and neg subopcodes */
2796       *decode_OK = False;
2797       return delta;
2798    }
2799
2800    if (epartIsReg(modrm)) {
2801       switch (gregOfRM(modrm)) {
2802          case 0: { /* TEST */
2803             delta++; d32 = getUDisp(sz, delta); delta += sz;
2804             dst1 = newTemp(ty);
2805             assign(dst1, binop(mkSizedOp(ty,Iop_And8),
2806                                getIReg(sz,eregOfRM(modrm)),
2807                                mkU(ty,d32)));
2808             setFlags_DEP1( Iop_And8, dst1, ty );
2809             DIP("test%c $0x%x, %s\n", nameISize(sz), d32, 
2810                                       nameIReg(sz, eregOfRM(modrm)));
2811             break;
2812          }
2813          case 1: /* UNDEFINED */
2814            /* The Intel docs imply this insn is undefined and binutils
2815               agrees.  Unfortunately Core 2 will run it (with who
2816               knows what result?)  sandpile.org reckons it's an alias
2817               for case 0.  We play safe. */
2818            *decode_OK = False;
2819            break;
2820          case 2: /* NOT */
2821             delta++;
2822             putIReg(sz, eregOfRM(modrm),
2823                         unop(mkSizedOp(ty,Iop_Not8),
2824                              getIReg(sz, eregOfRM(modrm))));
2825             DIP("not%c %s\n", nameISize(sz), nameIReg(sz, eregOfRM(modrm)));
2826             break;
2827          case 3: /* NEG */
2828             delta++;
2829             dst0 = newTemp(ty);
2830             src  = newTemp(ty);
2831             dst1 = newTemp(ty);
2832             assign(dst0, mkU(ty,0));
2833             assign(src,  getIReg(sz,eregOfRM(modrm)));
2834             assign(dst1, binop(mkSizedOp(ty,Iop_Sub8), mkexpr(dst0), mkexpr(src)));
2835             setFlags_DEP1_DEP2(Iop_Sub8, dst0, src, ty);
2836             putIReg(sz, eregOfRM(modrm), mkexpr(dst1));
2837             DIP("neg%c %s\n", nameISize(sz), nameIReg(sz, eregOfRM(modrm)));
2838             break;
2839          case 4: /* MUL (unsigned widening) */
2840             delta++;
2841             src = newTemp(ty);
2842             assign(src, getIReg(sz,eregOfRM(modrm)));
2843             codegen_mulL_A_D ( sz, False, src, nameIReg(sz,eregOfRM(modrm)) );
2844             break;
2845          case 5: /* IMUL (signed widening) */
2846             delta++;
2847             src = newTemp(ty);
2848             assign(src, getIReg(sz,eregOfRM(modrm)));
2849             codegen_mulL_A_D ( sz, True, src, nameIReg(sz,eregOfRM(modrm)) );
2850             break;
2851          case 6: /* DIV */
2852             delta++;
2853             assign( t1, getIReg(sz, eregOfRM(modrm)) );
2854             codegen_div ( sz, t1, False );
2855             DIP("div%c %s\n", nameISize(sz), nameIReg(sz, eregOfRM(modrm)));
2856             break;
2857          case 7: /* IDIV */
2858             delta++;
2859             assign( t1, getIReg(sz, eregOfRM(modrm)) );
2860             codegen_div ( sz, t1, True );
2861             DIP("idiv%c %s\n", nameISize(sz), nameIReg(sz, eregOfRM(modrm)));
2862             break;
2863          default: 
2864             /* This can't happen - gregOfRM should return 0 .. 7 only */
2865             vpanic("Grp3(x86)");
2866       }
2867    } else {
2868       addr = disAMode ( &len, sorb, delta, dis_buf );
2869       t1   = newTemp(ty);
2870       delta += len;
2871       assign(t1, loadLE(ty,mkexpr(addr)));
2872       switch (gregOfRM(modrm)) {
2873          case 0: { /* TEST */
2874             d32 = getUDisp(sz, delta); delta += sz;
2875             dst1 = newTemp(ty);
2876             assign(dst1, binop(mkSizedOp(ty,Iop_And8),
2877                                mkexpr(t1), mkU(ty,d32)));
2878             setFlags_DEP1( Iop_And8, dst1, ty );
2879             DIP("test%c $0x%x, %s\n", nameISize(sz), d32, dis_buf);
2880             break;
2881          }
2882          case 1: /* UNDEFINED */
2883            /* See comment above on R case */
2884            *decode_OK = False;
2885            break;
2886          case 2: /* NOT */
2887             dst1 = newTemp(ty);
2888             assign(dst1, unop(mkSizedOp(ty,Iop_Not8), mkexpr(t1)));
2889             if (locked) {
2890                casLE( mkexpr(addr), mkexpr(t1)/*expd*/, mkexpr(dst1)/*new*/,
2891                                     guest_EIP_curr_instr );
2892             } else {
2893                storeLE( mkexpr(addr), mkexpr(dst1) );
2894             }
2895             DIP("not%c %s\n", nameISize(sz), dis_buf);
2896             break;
2897          case 3: /* NEG */
2898             dst0 = newTemp(ty);
2899             src  = newTemp(ty);
2900             dst1 = newTemp(ty);
2901             assign(dst0, mkU(ty,0));
2902             assign(src,  mkexpr(t1));
2903             assign(dst1, binop(mkSizedOp(ty,Iop_Sub8),
2904                                mkexpr(dst0), mkexpr(src)));
2905             if (locked) {
2906                casLE( mkexpr(addr), mkexpr(t1)/*expd*/, mkexpr(dst1)/*new*/,
2907                                     guest_EIP_curr_instr );
2908             } else {
2909                storeLE( mkexpr(addr), mkexpr(dst1) );
2910             }
2911             setFlags_DEP1_DEP2(Iop_Sub8, dst0, src, ty);
2912             DIP("neg%c %s\n", nameISize(sz), dis_buf);
2913             break;
2914          case 4: /* MUL */
2915             codegen_mulL_A_D ( sz, False, t1, dis_buf );
2916             break;
2917          case 5: /* IMUL */
2918             codegen_mulL_A_D ( sz, True, t1, dis_buf );
2919             break;
2920          case 6: /* DIV */
2921             codegen_div ( sz, t1, False );
2922             DIP("div%c %s\n", nameISize(sz), dis_buf);
2923             break;
2924          case 7: /* IDIV */
2925             codegen_div ( sz, t1, True );
2926             DIP("idiv%c %s\n", nameISize(sz), dis_buf);
2927             break;
2928          default: 
2929             /* This can't happen - gregOfRM should return 0 .. 7 only */
2930             vpanic("Grp3(x86)");
2931       }
2932    }
2933    return delta;
2934 }
2935
2936
2937 /* Group 4 extended opcodes. */
2938 static
2939 UInt dis_Grp4 ( UChar sorb, Bool locked, Int delta, Bool* decode_OK )
2940 {
2941    Int   alen;
2942    UChar modrm;
2943    HChar dis_buf[50];
2944    IRType ty = Ity_I8;
2945    IRTemp t1 = newTemp(ty);
2946    IRTemp t2 = newTemp(ty);
2947
2948    *decode_OK = True;
2949
2950    modrm = getIByte(delta);
2951
2952    if (locked && (gregOfRM(modrm) != 0 && gregOfRM(modrm) != 1)) {
2953       /* LOCK prefix only allowed with inc and dec subopcodes */
2954       *decode_OK = False;
2955       return delta;
2956    }
2957
2958    if (epartIsReg(modrm)) {
2959       assign(t1, getIReg(1, eregOfRM(modrm)));
2960       switch (gregOfRM(modrm)) {
2961          case 0: /* INC */
2962             assign(t2, binop(Iop_Add8, mkexpr(t1), mkU8(1)));
2963             putIReg(1, eregOfRM(modrm), mkexpr(t2));
2964             setFlags_INC_DEC( True, t2, ty );
2965             break;
2966          case 1: /* DEC */
2967             assign(t2, binop(Iop_Sub8, mkexpr(t1), mkU8(1)));
2968             putIReg(1, eregOfRM(modrm), mkexpr(t2));
2969             setFlags_INC_DEC( False, t2, ty );
2970             break;
2971          default: 
2972             *decode_OK = False;
2973             return delta;
2974       }
2975       delta++;
2976       DIP("%sb %s\n", nameGrp4(gregOfRM(modrm)),
2977                       nameIReg(1, eregOfRM(modrm)));
2978    } else {
2979       IRTemp addr = disAMode ( &alen, sorb, delta, dis_buf );
2980       assign( t1, loadLE(ty, mkexpr(addr)) );
2981       switch (gregOfRM(modrm)) {
2982          case 0: /* INC */
2983             assign(t2, binop(Iop_Add8, mkexpr(t1), mkU8(1)));
2984             if (locked) {
2985                casLE( mkexpr(addr), mkexpr(t1)/*expd*/, mkexpr(t2)/*new*/, 
2986                       guest_EIP_curr_instr );
2987             } else {
2988                storeLE( mkexpr(addr), mkexpr(t2) );
2989             }
2990             setFlags_INC_DEC( True, t2, ty );
2991             break;
2992          case 1: /* DEC */
2993             assign(t2, binop(Iop_Sub8, mkexpr(t1), mkU8(1)));
2994             if (locked) {
2995                casLE( mkexpr(addr), mkexpr(t1)/*expd*/, mkexpr(t2)/*new*/, 
2996                       guest_EIP_curr_instr );
2997             } else {
2998                storeLE( mkexpr(addr), mkexpr(t2) );
2999             }
3000             setFlags_INC_DEC( False, t2, ty );
3001             break;
3002          default: 
3003             *decode_OK = False;
3004             return delta;
3005       }
3006       delta += alen;
3007       DIP("%sb %s\n", nameGrp4(gregOfRM(modrm)), dis_buf);
3008    }
3009    return delta;
3010 }
3011
3012
3013 /* Group 5 extended opcodes. */
3014 static
3015 UInt dis_Grp5 ( UChar sorb, Bool locked, Int sz, Int delta, 
3016                 DisResult* dres, Bool* decode_OK )
3017 {
3018    Int     len;
3019    UChar   modrm;
3020    HChar   dis_buf[50];
3021    IRTemp  addr = IRTemp_INVALID;
3022    IRType  ty = szToITy(sz);
3023    IRTemp  t1 = newTemp(ty);
3024    IRTemp  t2 = IRTemp_INVALID;
3025
3026    *decode_OK = True;
3027
3028    modrm = getIByte(delta);
3029
3030    if (locked && (gregOfRM(modrm) != 0 && gregOfRM(modrm) != 1)) {
3031       /* LOCK prefix only allowed with inc and dec subopcodes */
3032       *decode_OK = False;
3033       return delta;
3034    }
3035
3036    if (epartIsReg(modrm)) {
3037       assign(t1, getIReg(sz,eregOfRM(modrm)));
3038       switch (gregOfRM(modrm)) {
3039          case 0: /* INC */ 
3040             vassert(sz == 2 || sz == 4);
3041             t2 = newTemp(ty);
3042             assign(t2, binop(mkSizedOp(ty,Iop_Add8),
3043                              mkexpr(t1), mkU(ty,1)));
3044             setFlags_INC_DEC( True, t2, ty );
3045             putIReg(sz,eregOfRM(modrm),mkexpr(t2));
3046             break;
3047          case 1: /* DEC */ 
3048             vassert(sz == 2 || sz == 4);
3049             t2 = newTemp(ty);
3050             assign(t2, binop(mkSizedOp(ty,Iop_Sub8),
3051                              mkexpr(t1), mkU(ty,1)));
3052             setFlags_INC_DEC( False, t2, ty );
3053             putIReg(sz,eregOfRM(modrm),mkexpr(t2));
3054             break;
3055          case 2: /* call Ev */
3056             vassert(sz == 4);
3057             t2 = newTemp(Ity_I32);
3058             assign(t2, binop(Iop_Sub32, getIReg(4,R_ESP), mkU32(4)));
3059             putIReg(4, R_ESP, mkexpr(t2));
3060             storeLE( mkexpr(t2), mkU32(guest_EIP_bbstart+delta+1));
3061             jmp_treg(Ijk_Call,t1);
3062             dres->whatNext = Dis_StopHere;
3063             break;
3064          case 4: /* jmp Ev */
3065             vassert(sz == 4);
3066             jmp_treg(Ijk_Boring,t1);
3067             dres->whatNext = Dis_StopHere;
3068             break;
3069          case 6: /* PUSH Ev */
3070             vassert(sz == 4 || sz == 2);
3071             t2 = newTemp(Ity_I32);
3072             assign( t2, binop(Iop_Sub32,getIReg(4,R_ESP),mkU32(sz)) );
3073             putIReg(4, R_ESP, mkexpr(t2) );
3074             storeLE( mkexpr(t2), mkexpr(t1) );
3075             break;
3076          default: 
3077             *decode_OK = False;
3078             return delta;
3079       }
3080       delta++;
3081       DIP("%s%c %s\n", nameGrp5(gregOfRM(modrm)),
3082                        nameISize(sz), nameIReg(sz, eregOfRM(modrm)));
3083    } else {
3084       addr = disAMode ( &len, sorb, delta, dis_buf );
3085       assign(t1, loadLE(ty,mkexpr(addr)));
3086       switch (gregOfRM(modrm)) {
3087          case 0: /* INC */ 
3088             t2 = newTemp(ty);
3089             assign(t2, binop(mkSizedOp(ty,Iop_Add8),
3090                              mkexpr(t1), mkU(ty,1)));
3091             if (locked) {
3092                casLE( mkexpr(addr),
3093                       mkexpr(t1), mkexpr(t2), guest_EIP_curr_instr );
3094             } else {
3095                storeLE(mkexpr(addr),mkexpr(t2));
3096             }
3097             setFlags_INC_DEC( True, t2, ty );
3098             break;
3099          case 1: /* DEC */ 
3100             t2 = newTemp(ty);
3101             assign(t2, binop(mkSizedOp(ty,Iop_Sub8),
3102                              mkexpr(t1), mkU(ty,1)));
3103             if (locked) {
3104                casLE( mkexpr(addr),
3105                       mkexpr(t1), mkexpr(t2), guest_EIP_curr_instr );
3106             } else {
3107                storeLE(mkexpr(addr),mkexpr(t2));
3108             }
3109             setFlags_INC_DEC( False, t2, ty );
3110             break;
3111          case 2: /* call Ev */
3112             vassert(sz == 4);
3113             t2 = newTemp(Ity_I32);
3114             assign(t2, binop(Iop_Sub32, getIReg(4,R_ESP), mkU32(4)));
3115             putIReg(4, R_ESP, mkexpr(t2));
3116             storeLE( mkexpr(t2), mkU32(guest_EIP_bbstart+delta+len));
3117             jmp_treg(Ijk_Call,t1);
3118             dres->whatNext = Dis_StopHere;
3119             break;
3120          case 4: /* JMP Ev */
3121             vassert(sz == 4);
3122             jmp_treg(Ijk_Boring,t1);
3123             dres->whatNext = Dis_StopHere;
3124             break;
3125          case 6: /* PUSH Ev */
3126             vassert(sz == 4 || sz == 2);
3127             t2 = newTemp(Ity_I32);
3128             assign( t2, binop(Iop_Sub32,getIReg(4,R_ESP),mkU32(sz)) );
3129             putIReg(4, R_ESP, mkexpr(t2) );
3130             storeLE( mkexpr(t2), mkexpr(t1) );
3131             break;
3132          default: 
3133             *decode_OK = False;
3134             return delta;
3135       }
3136       delta += len;
3137       DIP("%s%c %s\n", nameGrp5(gregOfRM(modrm)),
3138                        nameISize(sz), dis_buf);
3139    }
3140    return delta;
3141 }
3142
3143
3144 /*------------------------------------------------------------*/
3145 /*--- Disassembling string ops (including REP prefixes)    ---*/
3146 /*------------------------------------------------------------*/
3147
3148 /* Code shared by all the string ops */
3149 static
3150 void dis_string_op_increment(Int sz, Int t_inc)
3151 {
3152    if (sz == 4 || sz == 2) {
3153       assign( t_inc, 
3154               binop(Iop_Shl32, IRExpr_Get( OFFB_DFLAG, Ity_I32 ),
3155                                mkU8(sz/2) ) );
3156    } else {
3157       assign( t_inc, 
3158               IRExpr_Get( OFFB_DFLAG, Ity_I32 ) );
3159    }
3160 }
3161
3162 static
3163 void dis_string_op( void (*dis_OP)( Int, IRTemp ), 
3164                     Int sz, HChar* name, UChar sorb )
3165 {
3166    IRTemp t_inc = newTemp(Ity_I32);
3167    vassert(sorb == 0); /* hmm.  so what was the point of passing it in? */
3168    dis_string_op_increment(sz, t_inc);
3169    dis_OP( sz, t_inc );
3170    DIP("%s%c\n", name, nameISize(sz));
3171 }
3172
3173 static 
3174 void dis_MOVS ( Int sz, IRTemp t_inc )
3175 {
3176    IRType ty = szToITy(sz);
3177    IRTemp td = newTemp(Ity_I32);   /* EDI */
3178    IRTemp ts = newTemp(Ity_I32);   /* ESI */
3179
3180    assign( td, getIReg(4, R_EDI) );
3181    assign( ts, getIReg(4, R_ESI) );
3182
3183    storeLE( mkexpr(td), loadLE(ty,mkexpr(ts)) );
3184
3185    putIReg( 4, R_EDI, binop(Iop_Add32, mkexpr(td), mkexpr(t_inc)) );
3186    putIReg( 4, R_ESI, binop(Iop_Add32, mkexpr(ts), mkexpr(t_inc)) );
3187 }
3188
3189 static 
3190 void dis_LODS ( Int sz, IRTemp t_inc )
3191 {
3192    IRType ty = szToITy(sz);
3193    IRTemp ts = newTemp(Ity_I32);   /* ESI */
3194
3195    assign( ts, getIReg(4, R_ESI) );
3196
3197    putIReg( sz, R_EAX, loadLE(ty, mkexpr(ts)) );
3198
3199    putIReg( 4, R_ESI, binop(Iop_Add32, mkexpr(ts), mkexpr(t_inc)) );
3200 }
3201
3202 static 
3203 void dis_STOS ( Int sz, IRTemp t_inc )
3204 {
3205    IRType ty = szToITy(sz);
3206    IRTemp ta = newTemp(ty);        /* EAX */
3207    IRTemp td = newTemp(Ity_I32);   /* EDI */
3208
3209    assign( ta, getIReg(sz, R_EAX) );
3210    assign( td, getIReg(4, R_EDI) );
3211
3212    storeLE( mkexpr(td), mkexpr(ta) );
3213
3214    putIReg( 4, R_EDI, binop(Iop_Add32, mkexpr(td), mkexpr(t_inc)) );
3215 }
3216
3217 static 
3218 void dis_CMPS ( Int sz, IRTemp t_inc )
3219 {
3220    IRType ty  = szToITy(sz);
3221    IRTemp tdv = newTemp(ty);      /* (EDI) */
3222    IRTemp tsv = newTemp(ty);      /* (ESI) */
3223    IRTemp td  = newTemp(Ity_I32); /*  EDI  */
3224    IRTemp ts  = newTemp(Ity_I32); /*  ESI  */
3225
3226    assign( td, getIReg(4, R_EDI) );
3227    assign( ts, getIReg(4, R_ESI) );
3228
3229    assign( tdv, loadLE(ty,mkexpr(td)) );
3230    assign( tsv, loadLE(ty,mkexpr(ts)) );
3231
3232    setFlags_DEP1_DEP2 ( Iop_Sub8, tsv, tdv, ty );
3233
3234    putIReg(4, R_EDI, binop(Iop_Add32, mkexpr(td), mkexpr(t_inc)) );
3235    putIReg(4, R_ESI, binop(Iop_Add32, mkexpr(ts), mkexpr(t_inc)) );
3236 }
3237
3238 static 
3239 void dis_SCAS ( Int sz, IRTemp t_inc )
3240 {
3241    IRType ty  = szToITy(sz);
3242    IRTemp ta  = newTemp(ty);       /*  EAX  */
3243    IRTemp td  = newTemp(Ity_I32);  /*  EDI  */
3244    IRTemp tdv = newTemp(ty);       /* (EDI) */
3245
3246    assign( ta, getIReg(sz, R_EAX) );
3247    assign( td, getIReg(4, R_EDI) );
3248
3249    assign( tdv, loadLE(ty,mkexpr(td)) );
3250    setFlags_DEP1_DEP2 ( Iop_Sub8, ta, tdv, ty );
3251
3252    putIReg(4, R_EDI, binop(Iop_Add32, mkexpr(td), mkexpr(t_inc)) );
3253 }
3254
3255
3256 /* Wrap the appropriate string op inside a REP/REPE/REPNE.
3257    We assume the insn is the last one in the basic block, and so emit a jump
3258    to the next insn, rather than just falling through. */
3259 static 
3260 void dis_REP_op ( X86Condcode cond,
3261                   void (*dis_OP)(Int, IRTemp),
3262                   Int sz, Addr32 eip, Addr32 eip_next, HChar* name )
3263 {
3264    IRTemp t_inc = newTemp(Ity_I32);
3265    IRTemp tc    = newTemp(Ity_I32);  /*  ECX  */
3266
3267    assign( tc, getIReg(4,R_ECX) );
3268
3269    stmt( IRStmt_Exit( binop(Iop_CmpEQ32,mkexpr(tc),mkU32(0)),
3270                       Ijk_Boring,
3271                       IRConst_U32(eip_next) ) );
3272
3273    putIReg(4, R_ECX, binop(Iop_Sub32, mkexpr(tc), mkU32(1)) );
3274
3275    dis_string_op_increment(sz, t_inc);
3276    dis_OP (sz, t_inc);
3277
3278    if (cond == X86CondAlways) {
3279       jmp_lit(Ijk_Boring,eip);
3280    } else {
3281       stmt( IRStmt_Exit( mk_x86g_calculate_condition(cond),
3282                          Ijk_Boring,
3283                          IRConst_U32(eip) ) );
3284       jmp_lit(Ijk_Boring,eip_next);
3285    }
3286    DIP("%s%c\n", name, nameISize(sz));
3287 }
3288
3289
3290 /*------------------------------------------------------------*/
3291 /*--- Arithmetic, etc.                                     ---*/
3292 /*------------------------------------------------------------*/
3293
3294 /* IMUL E, G.  Supplied eip points to the modR/M byte. */
3295 static
3296 UInt dis_mul_E_G ( UChar       sorb,
3297                    Int         size, 
3298                    Int         delta0 )
3299 {
3300    Int    alen;
3301    HChar  dis_buf[50];
3302    UChar  rm = getIByte(delta0);
3303    IRType ty = szToITy(size);
3304    IRTemp te = newTemp(ty);
3305    IRTemp tg = newTemp(ty);
3306    IRTemp resLo = newTemp(ty);
3307
3308    assign( tg, getIReg(size, gregOfRM(rm)) );
3309    if (epartIsReg(rm)) {
3310       assign( te, getIReg(size, eregOfRM(rm)) );
3311    } else {
3312       IRTemp addr = disAMode( &alen, sorb, delta0, dis_buf );
3313       assign( te, loadLE(ty,mkexpr(addr)) );
3314    }
3315
3316    setFlags_MUL ( ty, te, tg, X86G_CC_OP_SMULB );
3317
3318    assign( resLo, binop( mkSizedOp(ty, Iop_Mul8), mkexpr(te), mkexpr(tg) ) );
3319
3320    putIReg(size, gregOfRM(rm), mkexpr(resLo) );
3321
3322    if (epartIsReg(rm)) {
3323       DIP("imul%c %s, %s\n", nameISize(size), 
3324                              nameIReg(size,eregOfRM(rm)),
3325                              nameIReg(size,gregOfRM(rm)));
3326       return 1+delta0;
3327    } else {
3328       DIP("imul%c %s, %s\n", nameISize(size), 
3329                              dis_buf, nameIReg(size,gregOfRM(rm)));
3330       return alen+delta0;
3331    }
3332 }
3333
3334
3335 /* IMUL I * E -> G.  Supplied eip points to the modR/M byte. */
3336 static
3337 UInt dis_imul_I_E_G ( UChar       sorb,
3338                       Int         size, 
3339                       Int         delta,
3340                       Int         litsize )
3341 {
3342    Int    d32, alen;
3343    HChar  dis_buf[50];
3344    UChar  rm = getIByte(delta);
3345    IRType ty = szToITy(size);
3346    IRTemp te = newTemp(ty);
3347    IRTemp tl = newTemp(ty);
3348    IRTemp resLo = newTemp(ty);
3349
3350    vassert(size == 1 || size == 2 || size == 4);
3351
3352    if (epartIsReg(rm)) {
3353       assign(te, getIReg(size, eregOfRM(rm)));
3354       delta++;
3355    } else {
3356       IRTemp addr = disAMode( &alen, sorb, delta, dis_buf );
3357       assign(te, loadLE(ty, mkexpr(addr)));
3358       delta += alen;
3359    }
3360    d32 = getSDisp(litsize,delta);
3361    delta += litsize;
3362
3363    if (size == 1) d32 &= 0xFF;
3364    if (size == 2) d32 &= 0xFFFF;
3365
3366    assign(tl, mkU(ty,d32));
3367
3368    assign( resLo, binop( mkSizedOp(ty, Iop_Mul8), mkexpr(te), mkexpr(tl) ));
3369
3370    setFlags_MUL ( ty, te, tl, X86G_CC_OP_SMULB );
3371
3372    putIReg(size, gregOfRM(rm), mkexpr(resLo));
3373
3374    DIP("imul %d, %s, %s\n", d32, 
3375        ( epartIsReg(rm) ? nameIReg(size,eregOfRM(rm)) : dis_buf ),
3376        nameIReg(size,gregOfRM(rm)) );
3377    return delta;
3378 }
3379
3380
3381 /* Generate an IR sequence to do a count-leading-zeroes operation on
3382    the supplied IRTemp, and return a new IRTemp holding the result.
3383    'ty' may be Ity_I16 or Ity_I32 only.  In the case where the
3384    argument is zero, return the number of bits in the word (the
3385    natural semantics). */
3386 static IRTemp gen_LZCNT ( IRType ty, IRTemp src )
3387 {
3388    vassert(ty == Ity_I32 || ty == Ity_I16);
3389
3390    IRTemp src32 = newTemp(Ity_I32);
3391    assign(src32, widenUto32( mkexpr(src) ));
3392
3393    IRTemp src32x = newTemp(Ity_I32);
3394    assign(src32x, 
3395           binop(Iop_Shl32, mkexpr(src32),
3396                            mkU8(32 - 8 * sizeofIRType(ty))));
3397
3398    // Clz32 has undefined semantics when its input is zero, so
3399    // special-case around that.
3400    IRTemp res32 = newTemp(Ity_I32);
3401    assign(res32,
3402           IRExpr_Mux0X(
3403              unop(Iop_1Uto8,
3404                   binop(Iop_CmpEQ32, mkexpr(src32x), mkU32(0))),
3405              unop(Iop_Clz32, mkexpr(src32x)),
3406              mkU32(8 * sizeofIRType(ty))
3407    ));
3408
3409    IRTemp res = newTemp(ty);
3410    assign(res, narrowTo(ty, mkexpr(res32)));
3411    return res;
3412 }
3413
3414
3415 /*------------------------------------------------------------*/
3416 /*---                                                      ---*/
3417 /*--- x87 FLOATING POINT INSTRUCTIONS                      ---*/
3418 /*---                                                      ---*/
3419 /*------------------------------------------------------------*/
3420
3421 /* --- Helper functions for dealing with the register stack. --- */
3422
3423 /* --- Set the emulation-warning pseudo-register. --- */
3424
3425 static void put_emwarn ( IRExpr* e /* :: Ity_I32 */ )
3426 {
3427    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I32);
3428    stmt( IRStmt_Put( OFFB_EMWARN, e ) );
3429 }
3430
3431 /* --- Produce an IRExpr* denoting a 64-bit QNaN. --- */
3432
3433 static IRExpr* mkQNaN64 ( void )
3434 {
3435   /* QNaN is 0 2047 1 0(51times) 
3436      == 0b 11111111111b 1 0(51times)
3437      == 0x7FF8 0000 0000 0000
3438    */
3439    return IRExpr_Const(IRConst_F64i(0x7FF8000000000000ULL));
3440 }
3441
3442 /* --------- Get/put the top-of-stack pointer. --------- */
3443
3444 static IRExpr* get_ftop ( void )
3445 {
3446    return IRExpr_Get( OFFB_FTOP, Ity_I32 );
3447 }
3448
3449 static void put_ftop ( IRExpr* e )
3450 {
3451    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I32);
3452    stmt( IRStmt_Put( OFFB_FTOP, e ) );
3453 }
3454
3455 /* --------- Get/put the C3210 bits. --------- */
3456
3457 static IRExpr* get_C3210 ( void )
3458 {
3459    return IRExpr_Get( OFFB_FC3210, Ity_I32 );
3460 }
3461
3462 static void put_C3210 ( IRExpr* e )
3463 {
3464    stmt( IRStmt_Put( OFFB_FC3210, e ) );
3465 }
3466
3467 /* --------- Get/put the FPU rounding mode. --------- */
3468 static IRExpr* /* :: Ity_I32 */ get_fpround ( void )
3469 {
3470    return IRExpr_Get( OFFB_FPROUND, Ity_I32 );
3471 }
3472
3473 static void put_fpround ( IRExpr* /* :: Ity_I32 */ e )
3474 {
3475    stmt( IRStmt_Put( OFFB_FPROUND, e ) );
3476 }
3477
3478
3479 /* --------- Synthesise a 2-bit FPU rounding mode. --------- */
3480 /* Produces a value in 0 .. 3, which is encoded as per the type
3481    IRRoundingMode.  Since the guest_FPROUND value is also encoded as
3482    per IRRoundingMode, we merely need to get it and mask it for
3483    safety.
3484 */
3485 static IRExpr* /* :: Ity_I32 */ get_roundingmode ( void )
3486 {
3487    return binop( Iop_And32, get_fpround(), mkU32(3) );
3488 }
3489
3490 static IRExpr* /* :: Ity_I32 */ get_FAKE_roundingmode ( void )
3491 {
3492    return mkU32(Irrm_NEAREST);
3493 }
3494
3495
3496 /* --------- Get/set FP register tag bytes. --------- */
3497
3498 /* Given i, and some expression e, generate 'ST_TAG(i) = e'. */
3499
3500 static void put_ST_TAG ( Int i, IRExpr* value )
3501 {
3502    IRRegArray* descr;
3503    vassert(typeOfIRExpr(irsb->tyenv, value) == Ity_I8);
3504    descr = mkIRRegArray( OFFB_FPTAGS, Ity_I8, 8 );
3505    stmt( IRStmt_PutI( descr, get_ftop(), i, value ) );
3506 }
3507
3508 /* Given i, generate an expression yielding 'ST_TAG(i)'.  This will be
3509    zero to indicate "Empty" and nonzero to indicate "NonEmpty".  */
3510
3511 static IRExpr* get_ST_TAG ( Int i )
3512 {
3513    IRRegArray* descr = mkIRRegArray( OFFB_FPTAGS, Ity_I8, 8 );
3514    return IRExpr_GetI( descr, get_ftop(), i );
3515 }
3516
3517
3518 /* --------- Get/set FP registers. --------- */
3519
3520 /* Given i, and some expression e, emit 'ST(i) = e' and set the
3521    register's tag to indicate the register is full.  The previous
3522    state of the register is not checked. */
3523
3524 static void put_ST_UNCHECKED ( Int i, IRExpr* value )
3525 {
3526    IRRegArray* descr;
3527    vassert(typeOfIRExpr(irsb->tyenv, value) == Ity_F64);
3528    descr = mkIRRegArray( OFFB_FPREGS, Ity_F64, 8 );
3529    stmt( IRStmt_PutI( descr, get_ftop(), i, value ) );
3530    /* Mark the register as in-use. */
3531    put_ST_TAG(i, mkU8(1));
3532 }
3533
3534 /* Given i, and some expression e, emit
3535       ST(i) = is_full(i) ? NaN : e
3536    and set the tag accordingly.
3537 */
3538
3539 static void put_ST ( Int i, IRExpr* value )
3540 {
3541    put_ST_UNCHECKED( i,
3542                      IRExpr_Mux0X( get_ST_TAG(i),
3543                                    /* 0 means empty */
3544                                    value,
3545                                    /* non-0 means full */
3546                                    mkQNaN64()
3547                    )
3548    );
3549 }
3550
3551
3552 /* Given i, generate an expression yielding 'ST(i)'. */
3553
3554 static IRExpr* get_ST_UNCHECKED ( Int i )
3555 {
3556    IRRegArray* descr = mkIRRegArray( OFFB_FPREGS, Ity_F64, 8 );
3557    return IRExpr_GetI( descr, get_ftop(), i );
3558 }
3559
3560
3561 /* Given i, generate an expression yielding 
3562   is_full(i) ? ST(i) : NaN
3563 */
3564
3565 static IRExpr* get_ST ( Int i )
3566 {
3567    return
3568       IRExpr_Mux0X( get_ST_TAG(i),
3569                     /* 0 means empty */
3570                     mkQNaN64(),
3571                     /* non-0 means full */
3572                     get_ST_UNCHECKED(i));
3573 }
3574
3575
3576 /* Adjust FTOP downwards by one register. */
3577
3578 static void fp_push ( void )
3579 {
3580    put_ftop( binop(Iop_Sub32, get_ftop(), mkU32(1)) );
3581 }
3582
3583 /* Adjust FTOP upwards by one register, and mark the vacated register
3584    as empty.  */
3585
3586 static void fp_pop ( void )
3587 {
3588    put_ST_TAG(0, mkU8(0));
3589    put_ftop( binop(Iop_Add32, get_ftop(), mkU32(1)) );
3590 }
3591
3592 /* Clear the C2 bit of the FPU status register, for
3593    sin/cos/tan/sincos. */
3594
3595 static void clear_C2 ( void )
3596 {
3597    put_C3210( binop(Iop_And32, get_C3210(), mkU32(~X86G_FC_MASK_C2)) );
3598 }
3599
3600 /* Invent a plausible-looking FPU status word value:
3601       ((ftop & 7) << 11) | (c3210 & 0x4700)
3602  */
3603 static IRExpr* get_FPU_sw ( void )
3604 {
3605    return
3606       unop(Iop_32to16,
3607            binop(Iop_Or32,
3608                  binop(Iop_Shl32, 
3609                        binop(Iop_And32, get_ftop(), mkU32(7)), 
3610                              mkU8(11)),
3611                        binop(Iop_And32, get_C3210(), mkU32(0x4700))
3612       ));
3613 }
3614
3615
3616 /* ------------------------------------------------------- */
3617 /* Given all that stack-mangling junk, we can now go ahead
3618    and describe FP instructions. 
3619 */
3620
3621 /* ST(0) = ST(0) `op` mem64/32(addr)
3622    Need to check ST(0)'s tag on read, but not on write.
3623 */
3624 static
3625 void fp_do_op_mem_ST_0 ( IRTemp addr, HChar* op_txt, HChar* dis_buf, 
3626                          IROp op, Bool dbl )
3627 {
3628    DIP("f%s%c %s\n", op_txt, dbl?'l':'s', dis_buf);
3629    if (dbl) {
3630       put_ST_UNCHECKED(0, 
3631          triop( op, 
3632                 get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
3633                 get_ST(0), 
3634                 loadLE(Ity_F64,mkexpr(addr))
3635          ));
3636    } else {
3637       put_ST_UNCHECKED(0, 
3638          triop( op, 
3639                 get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
3640                 get_ST(0), 
3641                 unop(Iop_F32toF64, loadLE(Ity_F32,mkexpr(addr)))
3642          ));
3643    }
3644 }
3645
3646
3647 /* ST(0) = mem64/32(addr) `op` ST(0)
3648    Need to check ST(0)'s tag on read, but not on write.
3649 */
3650 static
3651 void fp_do_oprev_mem_ST_0 ( IRTemp addr, HChar* op_txt, HChar* dis_buf, 
3652                             IROp op, Bool dbl )
3653 {
3654    DIP("f%s%c %s\n", op_txt, dbl?'l':'s', dis_buf);
3655    if (dbl) {
3656       put_ST_UNCHECKED(0, 
3657          triop( op, 
3658                 get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
3659                 loadLE(Ity_F64,mkexpr(addr)),
3660                 get_ST(0)
3661          ));
3662    } else {
3663       put_ST_UNCHECKED(0, 
3664          triop( op, 
3665                 get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
3666                 unop(Iop_F32toF64, loadLE(Ity_F32,mkexpr(addr))),
3667                 get_ST(0)
3668          ));
3669    }
3670 }
3671
3672
3673 /* ST(dst) = ST(dst) `op` ST(src).
3674    Check dst and src tags when reading but not on write.
3675 */
3676 static
3677 void fp_do_op_ST_ST ( HChar* op_txt, IROp op, UInt st_src, UInt st_dst,
3678                       Bool pop_after )
3679 {
3680    DIP("f%s%s st(%d), st(%d)\n", op_txt, pop_after?"p":"", 
3681                                  (Int)st_src, (Int)st_dst );
3682    put_ST_UNCHECKED( 
3683       st_dst, 
3684       triop( op, 
3685              get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
3686              get_ST(st_dst), 
3687              get_ST(st_src) ) 
3688    );
3689    if (pop_after)
3690       fp_pop();
3691 }
3692
3693 /* ST(dst) = ST(src) `op` ST(dst).
3694    Check dst and src tags when reading but not on write.
3695 */
3696 static
3697 void fp_do_oprev_ST_ST ( HChar* op_txt, IROp op, UInt st_src, UInt st_dst,
3698                          Bool pop_after )
3699 {
3700    DIP("f%s%s st(%d), st(%d)\n", op_txt, pop_after?"p":"",
3701                                  (Int)st_src, (Int)st_dst );
3702    put_ST_UNCHECKED( 
3703       st_dst, 
3704       triop( op, 
3705              get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
3706              get_ST(st_src), 
3707              get_ST(st_dst) ) 
3708    );
3709    if (pop_after)
3710       fp_pop();
3711 }
3712
3713 /* %eflags(Z,P,C) = UCOMI( st(0), st(i) ) */
3714 static void fp_do_ucomi_ST0_STi ( UInt i, Bool pop_after )
3715 {
3716    DIP("fucomi%s %%st(0),%%st(%d)\n", pop_after ? "p" : "", (Int)i );
3717    /* This is a bit of a hack (and isn't really right).  It sets
3718       Z,P,C,O correctly, but forces A and S to zero, whereas the Intel
3719       documentation implies A and S are unchanged. 
3720    */
3721    /* It's also fishy in that it is used both for COMIP and
3722       UCOMIP, and they aren't the same (although similar). */
3723    stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(X86G_CC_OP_COPY) ));
3724    stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0) ));
3725    stmt( IRStmt_Put( OFFB_CC_DEP1,
3726                      binop( Iop_And32,
3727                             binop(Iop_CmpF64, get_ST(0), get_ST(i)),
3728                             mkU32(0x45)
3729        )));
3730    /* Set NDEP even though it isn't used.  This makes redundant-PUT
3731       elimination of previous stores to this field work better. */
3732    stmt( IRStmt_Put( OFFB_CC_NDEP, mkU32(0) ));
3733    if (pop_after)
3734       fp_pop();
3735 }
3736
3737
3738 static
3739 UInt dis_FPU ( Bool* decode_ok, UChar sorb, Int delta )
3740 {
3741    Int    len;
3742    UInt   r_src, r_dst;
3743    HChar  dis_buf[50];
3744    IRTemp t1, t2;
3745
3746    /* On entry, delta points at the second byte of the insn (the modrm
3747       byte).*/
3748    UChar first_opcode = getIByte(delta-1);
3749    UChar modrm        = getIByte(delta+0);
3750
3751    /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xD8 opcodes +-+-+-+-+-+-+-+ */
3752
3753    if (first_opcode == 0xD8) {
3754       if (modrm < 0xC0) {
3755
3756          /* bits 5,4,3 are an opcode extension, and the modRM also
3757            specifies an address. */
3758          IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
3759          delta += len;
3760
3761          switch (gregOfRM(modrm)) {
3762
3763             case 0: /* FADD single-real */
3764                fp_do_op_mem_ST_0 ( addr, "add", dis_buf, Iop_AddF64, False );
3765                break;
3766
3767             case 1: /* FMUL single-real */
3768                fp_do_op_mem_ST_0 ( addr, "mul", dis_buf, Iop_MulF64, False );
3769                break;
3770
3771             case 2: /* FCOM single-real */
3772                DIP("fcoms %s\n", dis_buf);
3773                /* This forces C1 to zero, which isn't right. */
3774                put_C3210( 
3775                    binop( Iop_And32,
3776                           binop(Iop_Shl32, 
3777                                 binop(Iop_CmpF64, 
3778                                       get_ST(0),
3779                                       unop(Iop_F32toF64, 
3780                                            loadLE(Ity_F32,mkexpr(addr)))),
3781                                 mkU8(8)),
3782                           mkU32(0x4500)
3783                    ));
3784                break;  
3785
3786             case 3: /* FCOMP single-real */
3787                DIP("fcomps %s\n", dis_buf);
3788                /* This forces C1 to zero, which isn't right. */
3789                put_C3210( 
3790                    binop( Iop_And32,
3791                           binop(Iop_Shl32, 
3792                                 binop(Iop_CmpF64, 
3793                                       get_ST(0),
3794                                       unop(Iop_F32toF64, 
3795                                            loadLE(Ity_F32,mkexpr(addr)))),
3796                                 mkU8(8)),
3797                           mkU32(0x4500)
3798                    ));
3799                fp_pop();
3800                break;  
3801
3802             case 4: /* FSUB single-real */
3803                fp_do_op_mem_ST_0 ( addr, "sub", dis_buf, Iop_SubF64, False );
3804                break;
3805
3806             case 5: /* FSUBR single-real */
3807                fp_do_oprev_mem_ST_0 ( addr, "subr", dis_buf, Iop_SubF64, False );
3808                break;
3809
3810             case 6: /* FDIV single-real */
3811                fp_do_op_mem_ST_0 ( addr, "div", dis_buf, Iop_DivF64, False );
3812                break;
3813
3814             case 7: /* FDIVR single-real */
3815                fp_do_oprev_mem_ST_0 ( addr, "divr", dis_buf, Iop_DivF64, False );
3816                break;
3817
3818             default:
3819                vex_printf("unhandled opc_aux = 0x%2x\n", gregOfRM(modrm));
3820                vex_printf("first_opcode == 0xD8\n");
3821                goto decode_fail;
3822          }
3823       } else {
3824          delta++;
3825          switch (modrm) {
3826
3827             case 0xC0 ... 0xC7: /* FADD %st(?),%st(0) */
3828                fp_do_op_ST_ST ( "add", Iop_AddF64, modrm - 0xC0, 0, False );
3829                break;
3830
3831             case 0xC8 ... 0xCF: /* FMUL %st(?),%st(0) */
3832                fp_do_op_ST_ST ( "mul", Iop_MulF64, modrm - 0xC8, 0, False );
3833                break;
3834
3835             /* Dunno if this is right */
3836             case 0xD0 ... 0xD7: /* FCOM %st(?),%st(0) */
3837                r_dst = (UInt)modrm - 0xD0;
3838                DIP("fcom %%st(0),%%st(%d)\n", (Int)r_dst);
3839                /* This forces C1 to zero, which isn't right. */
3840                put_C3210( 
3841                    binop( Iop_And32,
3842                           binop(Iop_Shl32, 
3843                                 binop(Iop_CmpF64, get_ST(0), get_ST(r_dst)),
3844                                 mkU8(8)),
3845                           mkU32(0x4500)
3846                    ));
3847                break;
3848
3849             /* Dunno if this is right */
3850             case 0xD8 ... 0xDF: /* FCOMP %st(?),%st(0) */
3851                r_dst = (UInt)modrm - 0xD8;
3852                DIP("fcomp %%st(0),%%st(%d)\n", (Int)r_dst);
3853                /* This forces C1 to zero, which isn't right. */
3854                put_C3210( 
3855                    binop( Iop_And32,
3856                           binop(Iop_Shl32, 
3857                                 binop(Iop_CmpF64, get_ST(0), get_ST(r_dst)),
3858                                 mkU8(8)),
3859                           mkU32(0x4500)
3860                    ));
3861                fp_pop();
3862                break;
3863
3864             case 0xE0 ... 0xE7: /* FSUB %st(?),%st(0) */
3865                fp_do_op_ST_ST ( "sub", Iop_SubF64, modrm - 0xE0, 0, False );
3866                break;
3867
3868             case 0xE8 ... 0xEF: /* FSUBR %st(?),%st(0) */
3869                fp_do_oprev_ST_ST ( "subr", Iop_SubF64, modrm - 0xE8, 0, False );
3870                break;
3871
3872             case 0xF0 ... 0xF7: /* FDIV %st(?),%st(0) */
3873                fp_do_op_ST_ST ( "div", Iop_DivF64, modrm - 0xF0, 0, False );
3874                break;
3875
3876             case 0xF8 ... 0xFF: /* FDIVR %st(?),%st(0) */
3877                fp_do_oprev_ST_ST ( "divr", Iop_DivF64, modrm - 0xF8, 0, False );
3878                break;
3879
3880             default:
3881                goto decode_fail;
3882          }
3883       }
3884    }
3885
3886    /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xD9 opcodes +-+-+-+-+-+-+-+ */
3887    else
3888    if (first_opcode == 0xD9) {
3889       if (modrm < 0xC0) {
3890
3891          /* bits 5,4,3 are an opcode extension, and the modRM also
3892             specifies an address. */
3893          IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
3894          delta += len;
3895
3896          switch (gregOfRM(modrm)) {
3897
3898             case 0: /* FLD single-real */
3899                DIP("flds %s\n", dis_buf);
3900                fp_push();
3901                put_ST(0, unop(Iop_F32toF64,
3902                               loadLE(Ity_F32, mkexpr(addr))));
3903                break;
3904
3905             case 2: /* FST single-real */
3906                DIP("fsts %s\n", dis_buf);
3907                storeLE(mkexpr(addr),
3908                        binop(Iop_F64toF32, get_roundingmode(), get_ST(0)));
3909                break;
3910
3911             case 3: /* FSTP single-real */
3912                DIP("fstps %s\n", dis_buf);
3913                storeLE(mkexpr(addr), 
3914                        binop(Iop_F64toF32, get_roundingmode(), get_ST(0)));
3915                fp_pop();
3916                break;
3917
3918             case 4: { /* FLDENV m28 */
3919                /* Uses dirty helper: 
3920                      VexEmWarn x86g_do_FLDENV ( VexGuestX86State*, HWord ) */
3921                IRTemp   ew = newTemp(Ity_I32);
3922                IRDirty* d  = unsafeIRDirty_0_N ( 
3923                                 0/*regparms*/, 
3924                                 "x86g_dirtyhelper_FLDENV", 
3925                                 &x86g_dirtyhelper_FLDENV,
3926                                 mkIRExprVec_1( mkexpr(addr) )
3927                              );
3928                d->needsBBP = True;
3929                d->tmp      = ew;
3930                /* declare we're reading memory */
3931                d->mFx   = Ifx_Read;
3932                d->mAddr = mkexpr(addr);
3933                d->mSize = 28;
3934
3935                /* declare we're writing guest state */
3936                d->nFxState = 4;
3937
3938                d->fxState[0].fx     = Ifx_Write;
3939                d->fxState[0].offset = OFFB_FTOP;
3940                d->fxState[0].size   = sizeof(UInt);
3941
3942                d->fxState[1].fx     = Ifx_Write;
3943                d->fxState[1].offset = OFFB_FPTAGS;
3944                d->fxState[1].size   = 8 * sizeof(UChar);
3945
3946                d->fxState[2].fx     = Ifx_Write;
3947                d->fxState[2].offset = OFFB_FPROUND;
3948                d->fxState[2].size   = sizeof(UInt);
3949
3950                d->fxState[3].fx     = Ifx_Write;
3951                d->fxState[3].offset = OFFB_FC3210;
3952                d->fxState[3].size   = sizeof(UInt);
3953
3954                stmt( IRStmt_Dirty(d) );
3955
3956                /* ew contains any emulation warning we may need to
3957                   issue.  If needed, side-exit to the next insn,
3958                   reporting the warning, so that Valgrind's dispatcher
3959                   sees the warning. */
3960                put_emwarn( mkexpr(ew) );
3961                stmt( 
3962                   IRStmt_Exit(
3963                      binop(Iop_CmpNE32, mkexpr(ew), mkU32(0)),
3964                      Ijk_EmWarn,
3965                      IRConst_U32( ((Addr32)guest_EIP_bbstart)+delta)
3966                   )
3967                );
3968
3969                DIP("fldenv %s\n", dis_buf);
3970                break;
3971             }
3972
3973             case 5: {/* FLDCW */
3974                /* The only thing we observe in the control word is the
3975                   rounding mode.  Therefore, pass the 16-bit value
3976                   (x87 native-format control word) to a clean helper,
3977                   getting back a 64-bit value, the lower half of which
3978                   is the FPROUND value to store, and the upper half of
3979                   which is the emulation-warning token which may be
3980                   generated.
3981                */
3982                /* ULong x86h_check_fldcw ( UInt ); */
3983                IRTemp t64 = newTemp(Ity_I64);
3984                IRTemp ew = newTemp(Ity_I32);
3985                DIP("fldcw %s\n", dis_buf);
3986                assign( t64, mkIRExprCCall(
3987                                Ity_I64, 0/*regparms*/, 
3988                                "x86g_check_fldcw",
3989                                &x86g_check_fldcw, 
3990                                mkIRExprVec_1( 
3991                                   unop( Iop_16Uto32, 
3992                                         loadLE(Ity_I16, mkexpr(addr)))
3993                                )
3994                             )
3995                      );
3996
3997                put_fpround( unop(Iop_64to32, mkexpr(t64)) );
3998                assign( ew, unop(Iop_64HIto32, mkexpr(t64) ) );
3999                put_emwarn( mkexpr(ew) );
4000                /* Finally, if an emulation warning was reported,
4001                   side-exit to the next insn, reporting the warning,
4002                   so that Valgrind's dispatcher sees the warning. */
4003                stmt( 
4004                   IRStmt_Exit(
4005                      binop(Iop_CmpNE32, mkexpr(ew), mkU32(0)),
4006                      Ijk_EmWarn,
4007                      IRConst_U32( ((Addr32)guest_EIP_bbstart)+delta)
4008                   )
4009                );
4010                break;
4011             }
4012
4013             case 6: { /* FNSTENV m28 */
4014                /* Uses dirty helper: 
4015                      void x86g_do_FSTENV ( VexGuestX86State*, HWord ) */
4016                IRDirty* d = unsafeIRDirty_0_N ( 
4017                                0/*regparms*/, 
4018                                "x86g_dirtyhelper_FSTENV", 
4019                                &x86g_dirtyhelper_FSTENV,
4020                                mkIRExprVec_1( mkexpr(addr) )
4021                             );
4022                d->needsBBP = True;
4023                /* declare we're writing memory */
4024                d->mFx   = Ifx_Write;
4025                d->mAddr = mkexpr(addr);
4026                d->mSize = 28;
4027
4028                /* declare we're reading guest state */
4029                d->nFxState = 4;
4030
4031                d->fxState[0].fx     = Ifx_Read;
4032                d->fxState[0].offset = OFFB_FTOP;
4033                d->fxState[0].size   = sizeof(UInt);
4034
4035                d->fxState[1].fx     = Ifx_Read;
4036                d->fxState[1].offset = OFFB_FPTAGS;
4037                d->fxState[1].size   = 8 * sizeof(UChar);
4038
4039                d->fxState[2].fx     = Ifx_Read;
4040                d->fxState[2].offset = OFFB_FPROUND;
4041                d->fxState[2].size   = sizeof(UInt);
4042
4043                d->fxState[3].fx     = Ifx_Read;
4044                d->fxState[3].offset = OFFB_FC3210;
4045                d->fxState[3].size   = sizeof(UInt);
4046
4047                stmt( IRStmt_Dirty(d) );
4048
4049                DIP("fnstenv %s\n", dis_buf);
4050                break;
4051             }
4052
4053             case 7: /* FNSTCW */
4054               /* Fake up a native x87 FPU control word.  The only
4055                  thing it depends on is FPROUND[1:0], so call a clean
4056                  helper to cook it up. */
4057                /* UInt x86h_create_fpucw ( UInt fpround ) */
4058                DIP("fnstcw %s\n", dis_buf);
4059                storeLE(
4060                   mkexpr(addr), 
4061                   unop( Iop_32to16, 
4062                         mkIRExprCCall(
4063                            Ity_I32, 0/*regp*/,
4064                            "x86g_create_fpucw", &x86g_create_fpucw, 
4065                            mkIRExprVec_1( get_fpround() ) 
4066                         ) 
4067                   ) 
4068                );
4069                break;
4070
4071             default:
4072                vex_printf("unhandled opc_aux = 0x%2x\n", gregOfRM(modrm));
4073                vex_printf("first_opcode == 0xD9\n");
4074                goto decode_fail;
4075          }
4076
4077       } else {
4078          delta++;
4079          switch (modrm) {
4080
4081             case 0xC0 ... 0xC7: /* FLD %st(?) */
4082                r_src = (UInt)modrm - 0xC0;
4083                DIP("fld %%st(%d)\n", (Int)r_src);
4084                t1 = newTemp(Ity_F64);
4085                assign(t1, get_ST(r_src));
4086                fp_push();
4087                put_ST(0, mkexpr(t1));
4088                break;
4089
4090             case 0xC8 ... 0xCF: /* FXCH %st(?) */
4091                r_src = (UInt)modrm - 0xC8;
4092                DIP("fxch %%st(%d)\n", (Int)r_src);
4093                t1 = newTemp(Ity_F64);
4094                t2 = newTemp(Ity_F64);
4095                assign(t1, get_ST(0));
4096                assign(t2, get_ST(r_src));
4097                put_ST_UNCHECKED(0, mkexpr(t2));
4098                put_ST_UNCHECKED(r_src, mkexpr(t1));
4099                break;
4100
4101             case 0xE0: /* FCHS */
4102                DIP("fchs\n");
4103                put_ST_UNCHECKED(0, unop(Iop_NegF64, get_ST(0)));
4104                break;
4105
4106             case 0xE1: /* FABS */
4107                DIP("fabs\n");
4108                put_ST_UNCHECKED(0, unop(Iop_AbsF64, get_ST(0)));
4109                break;
4110
4111             case 0xE4: /* FTST */
4112                DIP("ftst\n");
4113                /* This forces C1 to zero, which isn't right. */
4114                /* Well, in fact the Intel docs say (bizarrely): "C1 is
4115                   set to 0 if stack underflow occurred; otherwise, set
4116                   to 0" which is pretty nonsensical.  I guess it's a
4117                    typo. */
4118                put_C3210( 
4119                    binop( Iop_And32,
4120                           binop(Iop_Shl32, 
4121                                 binop(Iop_CmpF64, 
4122                                       get_ST(0),
4123                                       IRExpr_Const(IRConst_F64i(0x0ULL))),
4124                                 mkU8(8)),
4125                           mkU32(0x4500)
4126                    ));
4127                break;
4128
4129             case 0xE5: { /* FXAM */
4130                /* This is an interesting one.  It examines %st(0),
4131                   regardless of whether the tag says it's empty or not.
4132                   Here, just pass both the tag (in our format) and the
4133                   value (as a double, actually a ULong) to a helper
4134                   function. */
4135                IRExpr** args
4136                   = mkIRExprVec_2( unop(Iop_8Uto32, get_ST_TAG(0)),
4137                                    unop(Iop_ReinterpF64asI64, 
4138                                         get_ST_UNCHECKED(0)) );
4139                put_C3210(mkIRExprCCall(
4140                             Ity_I32, 
4141                             0/*regparm*/, 
4142                             "x86g_calculate_FXAM", &x86g_calculate_FXAM,
4143                             args
4144                         ));
4145                DIP("fxam\n");
4146                break;
4147             }
4148
4149             case 0xE8: /* FLD1 */
4150                DIP("fld1\n");
4151                fp_push();
4152                /* put_ST(0, IRExpr_Const(IRConst_F64(1.0))); */
4153                put_ST(0, IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)));
4154                break;
4155
4156             case 0xE9: /* FLDL2T */
4157                DIP("fldl2t\n");
4158                fp_push();
4159                /* put_ST(0, IRExpr_Const(IRConst_F64(3.32192809488736234781))); */
4160                put_ST(0, IRExpr_Const(IRConst_F64i(0x400a934f0979a371ULL)));
4161                break;
4162
4163             case 0xEA: /* FLDL2E */
4164                DIP("fldl2e\n");
4165                fp_push();
4166                /* put_ST(0, IRExpr_Const(IRConst_F64(1.44269504088896340739))); */
4167                put_ST(0, IRExpr_Const(IRConst_F64i(0x3ff71547652b82feULL)));
4168                break;
4169
4170             case 0xEB: /* FLDPI */
4171                DIP("fldpi\n");
4172                fp_push();
4173                /* put_ST(0, IRExpr_Const(IRConst_F64(3.14159265358979323851))); */
4174                put_ST(0, IRExpr_Const(IRConst_F64i(0x400921fb54442d18ULL)));
4175                break;
4176
4177             case 0xEC: /* FLDLG2 */
4178                DIP("fldlg2\n");
4179                fp_push();
4180                /* put_ST(0, IRExpr_Const(IRConst_F64(0.301029995663981143))); */
4181                put_ST(0, IRExpr_Const(IRConst_F64i(0x3fd34413509f79ffULL)));
4182                break;
4183
4184             case 0xED: /* FLDLN2 */
4185                DIP("fldln2\n");
4186                fp_push();
4187                /* put_ST(0, IRExpr_Const(IRConst_F64(0.69314718055994530942))); */
4188                put_ST(0, IRExpr_Const(IRConst_F64i(0x3fe62e42fefa39efULL)));
4189                break;
4190
4191             case 0xEE: /* FLDZ */
4192                DIP("fldz\n");
4193                fp_push();
4194                /* put_ST(0, IRExpr_Const(IRConst_F64(0.0))); */
4195                put_ST(0, IRExpr_Const(IRConst_F64i(0x0000000000000000ULL)));
4196                break;
4197
4198             case 0xF0: /* F2XM1 */
4199                DIP("f2xm1\n");
4200                put_ST_UNCHECKED(0, 
4201                   binop(Iop_2xm1F64, 
4202                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
4203                         get_ST(0)));
4204                break;
4205
4206             case 0xF1: /* FYL2X */
4207                DIP("fyl2x\n");
4208                put_ST_UNCHECKED(1, 
4209                   triop(Iop_Yl2xF64,
4210                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
4211                         get_ST(1), 
4212                         get_ST(0)));
4213                fp_pop();
4214                break;
4215
4216             case 0xF2: /* FPTAN */
4217                DIP("ftan\n");
4218                put_ST_UNCHECKED(0, 
4219                   binop(Iop_TanF64, 
4220                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
4221                         get_ST(0)));
4222                fp_push();
4223                put_ST(0, IRExpr_Const(IRConst_F64(1.0)));
4224                clear_C2(); /* HACK */
4225                break;
4226
4227             case 0xF3: /* FPATAN */
4228                DIP("fpatan\n");
4229                put_ST_UNCHECKED(1, 
4230                   triop(Iop_AtanF64,
4231                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
4232                         get_ST(1), 
4233                         get_ST(0)));
4234                fp_pop();
4235                break;
4236
4237             case 0xF4: { /* FXTRACT */
4238                IRTemp argF = newTemp(Ity_F64);
4239                IRTemp sigF = newTemp(Ity_F64);
4240                IRTemp expF = newTemp(Ity_F64);
4241                IRTemp argI = newTemp(Ity_I64);
4242                IRTemp sigI = newTemp(Ity_I64);
4243                IRTemp expI = newTemp(Ity_I64);
4244                DIP("fxtract\n");
4245                assign( argF, get_ST(0) );
4246                assign( argI, unop(Iop_ReinterpF64asI64, mkexpr(argF)));
4247                assign( sigI, 
4248                        mkIRExprCCall(
4249                           Ity_I64, 0/*regparms*/, 
4250                           "x86amd64g_calculate_FXTRACT", 
4251                           &x86amd64g_calculate_FXTRACT, 
4252                           mkIRExprVec_2( mkexpr(argI), 
4253                                          mkIRExpr_HWord(0)/*sig*/ )) 
4254                );
4255                assign( expI, 
4256                        mkIRExprCCall(
4257                           Ity_I64, 0/*regparms*/, 
4258                           "x86amd64g_calculate_FXTRACT", 
4259                           &x86amd64g_calculate_FXTRACT, 
4260                           mkIRExprVec_2( mkexpr(argI), 
4261                                          mkIRExpr_HWord(1)/*exp*/ )) 
4262                );
4263                assign( sigF, unop(Iop_ReinterpI64asF64, mkexpr(sigI)) );
4264                assign( expF, unop(Iop_ReinterpI64asF64, mkexpr(expI)) );
4265                /* exponent */
4266                put_ST_UNCHECKED(0, mkexpr(expF) );
4267                fp_push();
4268                /* significand */
4269                put_ST(0, mkexpr(sigF) );
4270                break;
4271             }
4272
4273             case 0xF5: { /* FPREM1 -- IEEE compliant */
4274                IRTemp a1 = newTemp(Ity_F64);
4275                IRTemp a2 = newTemp(Ity_F64);
4276                DIP("fprem1\n");
4277                /* Do FPREM1 twice, once to get the remainder, and once
4278                   to get the C3210 flag values. */
4279                assign( a1, get_ST(0) );
4280                assign( a2, get_ST(1) );
4281                put_ST_UNCHECKED(0, 
4282                   triop(Iop_PRem1F64,
4283                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
4284                         mkexpr(a1), 
4285                         mkexpr(a2)));
4286                put_C3210(
4287                   triop(Iop_PRem1C3210F64,
4288                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
4289                         mkexpr(a1), 
4290                         mkexpr(a2)) );
4291                break;
4292             }
4293
4294             case 0xF7: /* FINCSTP */
4295                DIP("fprem\n");
4296                put_ftop( binop(Iop_Add32, get_ftop(), mkU32(1)) );
4297                break;
4298
4299             case 0xF8: { /* FPREM -- not IEEE compliant */
4300                IRTemp a1 = newTemp(Ity_F64);
4301                IRTemp a2 = newTemp(Ity_F64);
4302                DIP("fprem\n");
4303                /* Do FPREM twice, once to get the remainder, and once
4304                   to get the C3210 flag values. */
4305                assign( a1, get_ST(0) );
4306                assign( a2, get_ST(1) );
4307                put_ST_UNCHECKED(0, 
4308                   triop(Iop_PRemF64,
4309                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
4310                         mkexpr(a1), 
4311                         mkexpr(a2)));
4312                put_C3210( 
4313                   triop(Iop_PRemC3210F64,
4314                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
4315                         mkexpr(a1), 
4316                         mkexpr(a2)) );
4317                break;
4318             }
4319
4320             case 0xF9: /* FYL2XP1 */
4321                DIP("fyl2xp1\n");
4322                put_ST_UNCHECKED(1, 
4323                   triop(Iop_Yl2xp1F64,
4324                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
4325                         get_ST(1), 
4326                         get_ST(0)));
4327                fp_pop();
4328                break;
4329
4330             case 0xFA: /* FSQRT */
4331                DIP("fsqrt\n");
4332                put_ST_UNCHECKED(0, 
4333                   binop(Iop_SqrtF64, 
4334                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
4335                         get_ST(0)));
4336                break;
4337
4338             case 0xFB: { /* FSINCOS */
4339                IRTemp a1 = newTemp(Ity_F64);
4340                assign( a1, get_ST(0) );
4341                DIP("fsincos\n");
4342                put_ST_UNCHECKED(0, 
4343                   binop(Iop_SinF64, 
4344                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
4345                         mkexpr(a1)));
4346                fp_push();
4347                put_ST(0, 
4348                   binop(Iop_CosF64,
4349                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
4350                         mkexpr(a1)));
4351                clear_C2(); /* HACK */
4352                break;
4353             }
4354
4355             case 0xFC: /* FRNDINT */
4356                DIP("frndint\n");
4357                put_ST_UNCHECKED(0,
4358                   binop(Iop_RoundF64toInt, get_roundingmode(), get_ST(0)) );
4359                break;
4360
4361             case 0xFD: /* FSCALE */
4362                DIP("fscale\n");
4363                put_ST_UNCHECKED(0, 
4364                   triop(Iop_ScaleF64,
4365                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
4366                         get_ST(0), 
4367                         get_ST(1)));
4368                break;
4369
4370             case 0xFE: /* FSIN */
4371                DIP("fsin\n");
4372                put_ST_UNCHECKED(0, 
4373                   binop(Iop_SinF64, 
4374                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
4375                         get_ST(0)));
4376                clear_C2(); /* HACK */
4377                break;
4378
4379             case 0xFF: /* FCOS */
4380                DIP("fcos\n");
4381                put_ST_UNCHECKED(0, 
4382                   binop(Iop_CosF64, 
4383                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
4384                         get_ST(0)));
4385                clear_C2(); /* HACK */
4386                break;
4387
4388             default:
4389                goto decode_fail;
4390          }
4391       }
4392    }
4393
4394    /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDA opcodes +-+-+-+-+-+-+-+ */
4395    else
4396    if (first_opcode == 0xDA) {
4397
4398       if (modrm < 0xC0) {
4399
4400          /* bits 5,4,3 are an opcode extension, and the modRM also
4401             specifies an address. */
4402          IROp   fop;
4403          IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
4404          delta += len;
4405          switch (gregOfRM(modrm)) {
4406
4407             case 0: /* FIADD m32int */ /* ST(0) += m32int */
4408                DIP("fiaddl %s\n", dis_buf);
4409                fop = Iop_AddF64;
4410                goto do_fop_m32;
4411
4412             case 1: /* FIMUL m32int */ /* ST(0) *= m32int */
4413                DIP("fimull %s\n", dis_buf);
4414                fop = Iop_MulF64;
4415                goto do_fop_m32;
4416
4417             case 2: /* FICOM m32int */
4418                DIP("ficoml %s\n", dis_buf);
4419                /* This forces C1 to zero, which isn't right. */
4420                put_C3210( 
4421                    binop( Iop_And32,
4422                           binop(Iop_Shl32, 
4423                                 binop(Iop_CmpF64, 
4424                                       get_ST(0),
4425                                       unop(Iop_I32StoF64, 
4426                                            loadLE(Ity_I32,mkexpr(addr)))),
4427                                 mkU8(8)),
4428                           mkU32(0x4500)
4429                    ));
4430                break;
4431
4432             case 3: /* FICOMP m32int */
4433                DIP("ficompl %s\n", dis_buf);
4434                /* This forces C1 to zero, which isn't right. */
4435                put_C3210( 
4436                    binop( Iop_And32,
4437                           binop(Iop_Shl32, 
4438                                 binop(Iop_CmpF64, 
4439                                       get_ST(0),
4440                                       unop(Iop_I32StoF64, 
4441                                            loadLE(Ity_I32,mkexpr(addr)))),
4442                                 mkU8(8)),
4443                           mkU32(0x4500)
4444                    ));
4445                fp_pop();
4446                break;
4447
4448             case 4: /* FISUB m32int */ /* ST(0) -= m32int */
4449                DIP("fisubl %s\n", dis_buf);
4450                fop = Iop_SubF64;
4451                goto do_fop_m32;
4452
4453             case 5: /* FISUBR m32int */ /* ST(0) = m32int - ST(0) */
4454                DIP("fisubrl %s\n", dis_buf);
4455                fop = Iop_SubF64;
4456                goto do_foprev_m32;
4457
4458             case 6: /* FIDIV m32int */ /* ST(0) /= m32int */
4459                DIP("fidivl %s\n", dis_buf);
4460                fop = Iop_DivF64;
4461                goto do_fop_m32;
4462
4463             case 7: /* FIDIVR m32int */ /* ST(0) = m32int / ST(0) */
4464                DIP("fidivrl %s\n", dis_buf);
4465                fop = Iop_DivF64;
4466                goto do_foprev_m32;
4467
4468             do_fop_m32:
4469                put_ST_UNCHECKED(0, 
4470                   triop(fop, 
4471                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
4472                         get_ST(0),
4473                         unop(Iop_I32StoF64,
4474                              loadLE(Ity_I32, mkexpr(addr)))));
4475                break;
4476
4477             do_foprev_m32:
4478                put_ST_UNCHECKED(0, 
4479                   triop(fop, 
4480                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
4481                         unop(Iop_I32StoF64,
4482                              loadLE(Ity_I32, mkexpr(addr))),
4483                         get_ST(0)));
4484                break;
4485
4486             default:
4487                vex_printf("unhandled opc_aux = 0x%2x\n", gregOfRM(modrm));
4488                vex_printf("first_opcode == 0xDA\n");
4489                goto decode_fail;
4490          }
4491
4492       } else {
4493
4494          delta++;
4495          switch (modrm) {
4496
4497             case 0xC0 ... 0xC7: /* FCMOVB ST(i), ST(0) */
4498                r_src = (UInt)modrm - 0xC0;
4499                DIP("fcmovb %%st(%d), %%st(0)\n", (Int)r_src);
4500                put_ST_UNCHECKED(0, 
4501                                 IRExpr_Mux0X( 
4502                                     unop(Iop_1Uto8,
4503                                          mk_x86g_calculate_condition(X86CondB)), 
4504                                     get_ST(0), get_ST(r_src)) );
4505                break;
4506
4507             case 0xC8 ... 0xCF: /* FCMOVE(Z) ST(i), ST(0) */
4508                r_src = (UInt)modrm - 0xC8;
4509                DIP("fcmovz %%st(%d), %%st(0)\n", (Int)r_src);
4510                put_ST_UNCHECKED(0, 
4511                                 IRExpr_Mux0X( 
4512                                     unop(Iop_1Uto8,
4513                                          mk_x86g_calculate_condition(X86CondZ)), 
4514                                     get_ST(0), get_ST(r_src)) );
4515                break;
4516
4517             case 0xD0 ... 0xD7: /* FCMOVBE ST(i), ST(0) */
4518                r_src = (UInt)modrm - 0xD0;
4519                DIP("fcmovbe %%st(%d), %%st(0)\n", (Int)r_src);
4520                put_ST_UNCHECKED(0, 
4521                                 IRExpr_Mux0X( 
4522                                     unop(Iop_1Uto8,
4523                                          mk_x86g_calculate_condition(X86CondBE)), 
4524                                     get_ST(0), get_ST(r_src)) );
4525                break;
4526
4527             case 0xD8 ... 0xDF: /* FCMOVU ST(i), ST(0) */
4528                r_src = (UInt)modrm - 0xD8;
4529                DIP("fcmovu %%st(%d), %%st(0)\n", (Int)r_src);
4530                put_ST_UNCHECKED(0, 
4531                                 IRExpr_Mux0X( 
4532                                     unop(Iop_1Uto8,
4533                                          mk_x86g_calculate_condition(X86CondP)), 
4534                                     get_ST(0), get_ST(r_src)) );
4535                break;
4536
4537             case 0xE9: /* FUCOMPP %st(0),%st(1) */
4538                DIP("fucompp %%st(0),%%st(1)\n");
4539                /* This forces C1 to zero, which isn't right. */
4540                put_C3210( 
4541                    binop( Iop_And32,
4542                           binop(Iop_Shl32, 
4543                                 binop(Iop_CmpF64, get_ST(0), get_ST(1)),
4544                                 mkU8(8)),
4545                           mkU32(0x4500)
4546                    ));
4547                fp_pop();
4548                fp_pop();
4549                break;
4550
4551             default:
4552                goto decode_fail;
4553          }
4554
4555       }
4556    }
4557
4558    /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDB opcodes +-+-+-+-+-+-+-+ */
4559    else
4560    if (first_opcode == 0xDB) {
4561       if (modrm < 0xC0) {
4562
4563          /* bits 5,4,3 are an opcode extension, and the modRM also
4564             specifies an address. */
4565          IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
4566          delta += len;
4567
4568          switch (gregOfRM(modrm)) {
4569
4570             case 0: /* FILD m32int */
4571                DIP("fildl %s\n", dis_buf);
4572                fp_push();
4573                put_ST(0, unop(Iop_I32StoF64,
4574                               loadLE(Ity_I32, mkexpr(addr))));
4575                break;
4576
4577             case 1: /* FISTTPL m32 (SSE3) */
4578                DIP("fisttpl %s\n", dis_buf);
4579                storeLE( mkexpr(addr), 
4580                         binop(Iop_F64toI32S, mkU32(Irrm_ZERO), get_ST(0)) );
4581                fp_pop();
4582                break;
4583
4584             case 2: /* FIST m32 */
4585                DIP("fistl %s\n", dis_buf);
4586                storeLE( mkexpr(addr), 
4587                         binop(Iop_F64toI32S, get_roundingmode(), get_ST(0)) );
4588                break;
4589
4590             case 3: /* FISTP m32 */
4591                DIP("fistpl %s\n", dis_buf);
4592                storeLE( mkexpr(addr), 
4593                         binop(Iop_F64toI32S, get_roundingmode(), get_ST(0)) );
4594                fp_pop();
4595                break;
4596
4597             case 5: { /* FLD extended-real */
4598                /* Uses dirty helper: 
4599                      ULong x86g_loadF80le ( UInt )
4600                   addr holds the address.  First, do a dirty call to
4601                   get hold of the data. */
4602                IRTemp   val  = newTemp(Ity_I64);
4603                IRExpr** args = mkIRExprVec_1 ( mkexpr(addr) );
4604
4605                IRDirty* d = unsafeIRDirty_1_N ( 
4606                                val, 
4607                                0/*regparms*/, 
4608                                "x86g_dirtyhelper_loadF80le", 
4609                                &x86g_dirtyhelper_loadF80le, 
4610                                args 
4611                             );
4612                /* declare that we're reading memory */
4613                d->mFx   = Ifx_Read;
4614                d->mAddr = mkexpr(addr);
4615                d->mSize = 10;
4616
4617                /* execute the dirty call, dumping the result in val. */
4618                stmt( IRStmt_Dirty(d) );
4619                fp_push();
4620                put_ST(0, unop(Iop_ReinterpI64asF64, mkexpr(val)));
4621
4622                DIP("fldt %s\n", dis_buf);
4623                break;
4624             }
4625
4626             case 7: { /* FSTP extended-real */
4627                /* Uses dirty helper: void x86g_storeF80le ( UInt, ULong ) */
4628                IRExpr** args 
4629                   = mkIRExprVec_2( mkexpr(addr), 
4630                                    unop(Iop_ReinterpF64asI64, get_ST(0)) );
4631
4632                IRDirty* d = unsafeIRDirty_0_N ( 
4633                                0/*regparms*/, 
4634                                "x86g_dirtyhelper_storeF80le", 
4635                                &x86g_dirtyhelper_storeF80le,
4636                                args 
4637                             );
4638                /* declare we're writing memory */
4639                d->mFx   = Ifx_Write;
4640                d->mAddr = mkexpr(addr);
4641                d->mSize = 10;
4642
4643                /* execute the dirty call. */
4644                stmt( IRStmt_Dirty(d) );
4645                fp_pop();
4646
4647                DIP("fstpt\n %s", dis_buf);
4648                break;
4649             }
4650
4651             default:
4652                vex_printf("unhandled opc_aux = 0x%2x\n", gregOfRM(modrm));
4653                vex_printf("first_opcode == 0xDB\n");
4654                goto decode_fail;
4655          }
4656
4657       } else {
4658
4659          delta++;
4660          switch (modrm) {
4661
4662             case 0xC0 ... 0xC7: /* FCMOVNB ST(i), ST(0) */
4663                r_src = (UInt)modrm - 0xC0;
4664                DIP("fcmovnb %%st(%d), %%st(0)\n", (Int)r_src);
4665                put_ST_UNCHECKED(0, 
4666                                 IRExpr_Mux0X( 
4667                                     unop(Iop_1Uto8,
4668                                          mk_x86g_calculate_condition(X86CondNB)), 
4669                                     get_ST(0), get_ST(r_src)) );
4670                break;
4671
4672             case 0xC8 ... 0xCF: /* FCMOVNE(NZ) ST(i), ST(0) */
4673                r_src = (UInt)modrm - 0xC8;
4674                DIP("fcmovnz %%st(%d), %%st(0)\n", (Int)r_src);
4675                put_ST_UNCHECKED(0, 
4676                                 IRExpr_Mux0X( 
4677                                     unop(Iop_1Uto8,
4678                                          mk_x86g_calculate_condition(X86CondNZ)), 
4679                                     get_ST(0), get_ST(r_src)) );
4680                break;
4681
4682             case 0xD0 ... 0xD7: /* FCMOVNBE ST(i), ST(0) */
4683                r_src = (UInt)modrm - 0xD0;
4684                DIP("fcmovnbe %%st(%d), %%st(0)\n", (Int)r_src);
4685                put_ST_UNCHECKED(0, 
4686                                 IRExpr_Mux0X( 
4687                                     unop(Iop_1Uto8,
4688                                          mk_x86g_calculate_condition(X86CondNBE)), 
4689                                     get_ST(0), get_ST(r_src)) );
4690                break;
4691
4692             case 0xD8 ... 0xDF: /* FCMOVNU ST(i), ST(0) */
4693                r_src = (UInt)modrm - 0xD8;
4694                DIP("fcmovnu %%st(%d), %%st(0)\n", (Int)r_src);
4695                put_ST_UNCHECKED(0, 
4696                                 IRExpr_Mux0X( 
4697                                     unop(Iop_1Uto8,
4698                                          mk_x86g_calculate_condition(X86CondNP)), 
4699                                     get_ST(0), get_ST(r_src)) );
4700                break;
4701
4702             case 0xE2:
4703                DIP("fnclex\n");
4704                break;
4705
4706             case 0xE3: {
4707                /* Uses dirty helper: 
4708                      void x86g_do_FINIT ( VexGuestX86State* ) */
4709                IRDirty* d  = unsafeIRDirty_0_N ( 
4710                                 0/*regparms*/, 
4711                                 "x86g_dirtyhelper_FINIT", 
4712                                 &x86g_dirtyhelper_FINIT,
4713                                 mkIRExprVec_0()
4714                              );
4715                d->needsBBP = True;
4716
4717                /* declare we're writing guest state */
4718                d->nFxState = 5;
4719
4720                d->fxState[0].fx     = Ifx_Write;
4721                d->fxState[0].offset = OFFB_FTOP;
4722                d->fxState[0].size   = sizeof(UInt);
4723
4724                d->fxState[1].fx     = Ifx_Write;
4725                d->fxState[1].offset = OFFB_FPREGS;
4726                d->fxState[1].size   = 8 * sizeof(ULong);
4727
4728                d->fxState[2].fx     = Ifx_Write;
4729                d->fxState[2].offset = OFFB_FPTAGS;
4730                d->fxState[2].size   = 8 * sizeof(UChar);
4731
4732                d->fxState[3].fx     = Ifx_Write;
4733                d->fxState[3].offset = OFFB_FPROUND;
4734                d->fxState[3].size   = sizeof(UInt);
4735
4736                d->fxState[4].fx     = Ifx_Write;
4737                d->fxState[4].offset = OFFB_FC3210;
4738                d->fxState[4].size   = sizeof(UInt);
4739
4740                stmt( IRStmt_Dirty(d) );
4741
4742                DIP("fninit\n");
4743                break;
4744             }
4745
4746             case 0xE8 ... 0xEF: /* FUCOMI %st(0),%st(?) */
4747                fp_do_ucomi_ST0_STi( (UInt)modrm - 0xE8, False );
4748                break;
4749
4750             case 0xF0 ... 0xF7: /* FCOMI %st(0),%st(?) */
4751                fp_do_ucomi_ST0_STi( (UInt)modrm - 0xF0, False );
4752                break;
4753
4754             default:
4755                goto decode_fail;
4756          }
4757       }
4758    }
4759
4760    /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDC opcodes +-+-+-+-+-+-+-+ */
4761    else
4762    if (first_opcode == 0xDC) {
4763       if (modrm < 0xC0) {
4764
4765          /* bits 5,4,3 are an opcode extension, and the modRM also
4766             specifies an address. */
4767          IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
4768          delta += len;
4769
4770          switch (gregOfRM(modrm)) {
4771
4772             case 0: /* FADD double-real */
4773                fp_do_op_mem_ST_0 ( addr, "add", dis_buf, Iop_AddF64, True );
4774                break;
4775
4776             case 1: /* FMUL double-real */
4777                fp_do_op_mem_ST_0 ( addr, "mul", dis_buf, Iop_MulF64, True );
4778                break;
4779
4780             case 2: /* FCOM double-real */
4781                DIP("fcoml %s\n", dis_buf);
4782                /* This forces C1 to zero, which isn't right. */
4783                put_C3210( 
4784                    binop( Iop_And32,
4785                           binop(Iop_Shl32, 
4786                                 binop(Iop_CmpF64, 
4787                                       get_ST(0),
4788                                       loadLE(Ity_F64,mkexpr(addr))),
4789                                 mkU8(8)),
4790                           mkU32(0x4500)
4791                    ));
4792                break;  
4793
4794             case 3: /* FCOMP double-real */
4795                DIP("fcompl %s\n", dis_buf);
4796                /* This forces C1 to zero, which isn't right. */
4797                put_C3210( 
4798                    binop( Iop_And32,
4799                           binop(Iop_Shl32, 
4800                                 binop(Iop_CmpF64, 
4801                                       get_ST(0),
4802                                       loadLE(Ity_F64,mkexpr(addr))),
4803                                 mkU8(8)),
4804                           mkU32(0x4500)
4805                    ));
4806                fp_pop();
4807                break;  
4808
4809             case 4: /* FSUB double-real */
4810                fp_do_op_mem_ST_0 ( addr, "sub", dis_buf, Iop_SubF64, True );
4811                break;
4812
4813             case 5: /* FSUBR double-real */
4814                fp_do_oprev_mem_ST_0 ( addr, "subr", dis_buf, Iop_SubF64, True );
4815                break;
4816
4817             case 6: /* FDIV double-real */
4818                fp_do_op_mem_ST_0 ( addr, "div", dis_buf, Iop_DivF64, True );
4819                break;
4820
4821             case 7: /* FDIVR double-real */
4822                fp_do_oprev_mem_ST_0 ( addr, "divr", dis_buf, Iop_DivF64, True );
4823                break;
4824
4825             default:
4826                vex_printf("unhandled opc_aux = 0x%2x\n", gregOfRM(modrm));
4827                vex_printf("first_opcode == 0xDC\n");
4828                goto decode_fail;
4829          }
4830
4831       } else {
4832
4833          delta++;
4834          switch (modrm) {
4835
4836             case 0xC0 ... 0xC7: /* FADD %st(0),%st(?) */
4837                fp_do_op_ST_ST ( "add", Iop_AddF64, 0, modrm - 0xC0, False );
4838                break;
4839
4840             case 0xC8 ... 0xCF: /* FMUL %st(0),%st(?) */
4841                fp_do_op_ST_ST ( "mul", Iop_MulF64, 0, modrm - 0xC8, False );
4842                break;
4843
4844             case 0xE0 ... 0xE7: /* FSUBR %st(0),%st(?) */
4845                fp_do_oprev_ST_ST ( "subr", Iop_SubF64, 0, modrm - 0xE0, False );
4846                break;
4847
4848             case 0xE8 ... 0xEF: /* FSUB %st(0),%st(?) */
4849                fp_do_op_ST_ST ( "sub", Iop_SubF64, 0, modrm - 0xE8, False );
4850                break;
4851
4852             case 0xF0 ... 0xF7: /* FDIVR %st(0),%st(?) */
4853                fp_do_oprev_ST_ST ( "divr", Iop_DivF64, 0, modrm - 0xF0, False );
4854                break;
4855
4856             case 0xF8 ... 0xFF: /* FDIV %st(0),%st(?) */
4857                fp_do_op_ST_ST ( "div", Iop_DivF64, 0, modrm - 0xF8, False );
4858                break;
4859
4860             default:
4861                goto decode_fail;
4862          }
4863
4864       }
4865    }
4866
4867    /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDD opcodes +-+-+-+-+-+-+-+ */
4868    else
4869    if (first_opcode == 0xDD) {
4870
4871       if (modrm < 0xC0) {
4872
4873          /* bits 5,4,3 are an opcode extension, and the modRM also
4874             specifies an address. */
4875          IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
4876          delta += len;
4877
4878          switch (gregOfRM(modrm)) {
4879
4880             case 0: /* FLD double-real */
4881                DIP("fldl %s\n", dis_buf);
4882                fp_push();
4883                put_ST(0, loadLE(Ity_F64, mkexpr(addr)));
4884                break;
4885
4886             case 1: /* FISTTPQ m64 (SSE3) */
4887                DIP("fistppll %s\n", dis_buf);
4888                storeLE( mkexpr(addr), 
4889                         binop(Iop_F64toI64S, mkU32(Irrm_ZERO), get_ST(0)) );
4890                fp_pop();
4891                break;
4892
4893             case 2: /* FST double-real */
4894                DIP("fstl %s\n", dis_buf);
4895                storeLE(mkexpr(addr), get_ST(0));
4896                break;
4897
4898             case 3: /* FSTP double-real */
4899                DIP("fstpl %s\n", dis_buf);
4900                storeLE(mkexpr(addr), get_ST(0));
4901                fp_pop();
4902                break;
4903
4904             case 4: { /* FRSTOR m108 */
4905                /* Uses dirty helper: 
4906                      VexEmWarn x86g_do_FRSTOR ( VexGuestX86State*, Addr32 ) */
4907                IRTemp   ew = newTemp(Ity_I32);
4908                IRDirty* d  = unsafeIRDirty_0_N ( 
4909                                 0/*regparms*/, 
4910                                 "x86g_dirtyhelper_FRSTOR", 
4911                                 &x86g_dirtyhelper_FRSTOR,
4912                                 mkIRExprVec_1( mkexpr(addr) )
4913                              );
4914                d->needsBBP = True;
4915                d->tmp      = ew;
4916                /* declare we're reading memory */
4917                d->mFx   = Ifx_Read;
4918                d->mAddr = mkexpr(addr);
4919                d->mSize = 108;
4920
4921                /* declare we're writing guest state */
4922                d->nFxState = 5;
4923
4924                d->fxState[0].fx     = Ifx_Write;
4925                d->fxState[0].offset = OFFB_FTOP;
4926                d->fxState[0].size   = sizeof(UInt);
4927
4928                d->fxState[1].fx     = Ifx_Write;
4929                d->fxState[1].offset = OFFB_FPREGS;
4930                d->fxState[1].size   = 8 * sizeof(ULong);
4931
4932                d->fxState[2].fx     = Ifx_Write;
4933                d->fxState[2].offset = OFFB_FPTAGS;
4934                d->fxState[2].size   = 8 * sizeof(UChar);
4935
4936                d->fxState[3].fx     = Ifx_Write;
4937                d->fxState[3].offset = OFFB_FPROUND;
4938                d->fxState[3].size   = sizeof(UInt);
4939
4940                d->fxState[4].fx     = Ifx_Write;
4941                d->fxState[4].offset = OFFB_FC3210;
4942                d->fxState[4].size   = sizeof(UInt);
4943
4944                stmt( IRStmt_Dirty(d) );
4945
4946                /* ew contains any emulation warning we may need to
4947                   issue.  If needed, side-exit to the next insn,
4948                   reporting the warning, so that Valgrind's dispatcher
4949                   sees the warning. */
4950                put_emwarn( mkexpr(ew) );
4951                stmt( 
4952                   IRStmt_Exit(
4953                      binop(Iop_CmpNE32, mkexpr(ew), mkU32(0)),
4954                      Ijk_EmWarn,
4955                      IRConst_U32( ((Addr32)guest_EIP_bbstart)+delta)
4956                   )
4957                );
4958
4959                DIP("frstor %s\n", dis_buf);
4960                break;
4961             }
4962
4963             case 6: { /* FNSAVE m108 */
4964                /* Uses dirty helper: 
4965                      void x86g_do_FSAVE ( VexGuestX86State*, UInt ) */
4966                IRDirty* d = unsafeIRDirty_0_N ( 
4967                                0/*regparms*/, 
4968                                "x86g_dirtyhelper_FSAVE", 
4969                                &x86g_dirtyhelper_FSAVE,
4970                                mkIRExprVec_1( mkexpr(addr) )
4971                             );
4972                d->needsBBP = True;
4973                /* declare we're writing memory */
4974                d->mFx   = Ifx_Write;
4975                d->mAddr = mkexpr(addr);
4976                d->mSize = 108;
4977
4978                /* declare we're reading guest state */
4979                d->nFxState = 5;
4980
4981                d->fxState[0].fx     = Ifx_Read;
4982                d->fxState[0].offset = OFFB_FTOP;
4983                d->fxState[0].size   = sizeof(UInt);
4984
4985                d->fxState[1].fx     = Ifx_Read;
4986                d->fxState[1].offset = OFFB_FPREGS;
4987                d->fxState[1].size   = 8 * sizeof(ULong);
4988
4989                d->fxState[2].fx     = Ifx_Read;
4990                d->fxState[2].offset = OFFB_FPTAGS;
4991                d->fxState[2].size   = 8 * sizeof(UChar);
4992
4993                d->fxState[3].fx     = Ifx_Read;
4994                d->fxState[3].offset = OFFB_FPROUND;
4995                d->fxState[3].size   = sizeof(UInt);
4996
4997                d->fxState[4].fx     = Ifx_Read;
4998                d->fxState[4].offset = OFFB_FC3210;
4999                d->fxState[4].size   = sizeof(UInt);
5000
5001                stmt( IRStmt_Dirty(d) );
5002
5003                DIP("fnsave %s\n", dis_buf);
5004                break;
5005             }
5006
5007             case 7: { /* FNSTSW m16 */
5008                IRExpr* sw = get_FPU_sw();
5009                vassert(typeOfIRExpr(irsb->tyenv, sw) == Ity_I16);
5010                storeLE( mkexpr(addr), sw );
5011                DIP("fnstsw %s\n", dis_buf);
5012                break;
5013             }
5014
5015             default:
5016                vex_printf("unhandled opc_aux = 0x%2x\n", gregOfRM(modrm));
5017                vex_printf("first_opcode == 0xDD\n");
5018                goto decode_fail;
5019          }
5020       } else {
5021          delta++;
5022          switch (modrm) {
5023
5024             case 0xC0 ... 0xC7: /* FFREE %st(?) */
5025                r_dst = (UInt)modrm - 0xC0;
5026                DIP("ffree %%st(%d)\n", (Int)r_dst);
5027                put_ST_TAG ( r_dst, mkU8(0) );
5028                break;
5029
5030             case 0xD0 ... 0xD7: /* FST %st(0),%st(?) */
5031                r_dst = (UInt)modrm - 0xD0;
5032                DIP("fst %%st(0),%%st(%d)\n", (Int)r_dst);
5033                /* P4 manual says: "If the destination operand is a
5034                   non-empty register, the invalid-operation exception
5035                   is not generated.  Hence put_ST_UNCHECKED. */
5036                put_ST_UNCHECKED(r_dst, get_ST(0));
5037                break;
5038
5039             case 0xD8 ... 0xDF: /* FSTP %st(0),%st(?) */
5040                r_dst = (UInt)modrm - 0xD8;
5041                DIP("fstp %%st(0),%%st(%d)\n", (Int)r_dst);
5042                /* P4 manual says: "If the destination operand is a
5043                   non-empty register, the invalid-operation exception
5044                   is not generated.  Hence put_ST_UNCHECKED. */
5045                put_ST_UNCHECKED(r_dst, get_ST(0));
5046                fp_pop();
5047                break;
5048
5049             case 0xE0 ... 0xE7: /* FUCOM %st(0),%st(?) */
5050                r_dst = (UInt)modrm - 0xE0;
5051                DIP("fucom %%st(0),%%st(%d)\n", (Int)r_dst);
5052                /* This forces C1 to zero, which isn't right. */
5053                put_C3210( 
5054                    binop( Iop_And32,
5055                           binop(Iop_Shl32, 
5056                                 binop(Iop_CmpF64, get_ST(0), get_ST(r_dst)),
5057                                 mkU8(8)),
5058                           mkU32(0x4500)
5059                    ));
5060                break;
5061
5062             case 0xE8 ... 0xEF: /* FUCOMP %st(0),%st(?) */
5063                r_dst = (UInt)modrm - 0xE8;
5064                DIP("fucomp %%st(0),%%st(%d)\n", (Int)r_dst);
5065                /* This forces C1 to zero, which isn't right. */
5066                put_C3210( 
5067                    binop( Iop_And32,
5068                           binop(Iop_Shl32, 
5069                                 binop(Iop_CmpF64, get_ST(0), get_ST(r_dst)),
5070                                 mkU8(8)),
5071                           mkU32(0x4500)
5072                    ));
5073                fp_pop();
5074                break;
5075
5076             default:
5077                goto decode_fail;
5078          }
5079       }
5080    }
5081
5082    /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDE opcodes +-+-+-+-+-+-+-+ */
5083    else
5084    if (first_opcode == 0xDE) {
5085
5086       if (modrm < 0xC0) {
5087
5088          /* bits 5,4,3 are an opcode extension, and the modRM also
5089             specifies an address. */
5090          IROp   fop;
5091          IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
5092          delta += len;
5093
5094          switch (gregOfRM(modrm)) {
5095
5096             case 0: /* FIADD m16int */ /* ST(0) += m16int */
5097                DIP("fiaddw %s\n", dis_buf);
5098                fop = Iop_AddF64;
5099                goto do_fop_m16;
5100
5101             case 1: /* FIMUL m16int */ /* ST(0) *= m16int */
5102                DIP("fimulw %s\n", dis_buf);
5103                fop = Iop_MulF64;
5104                goto do_fop_m16;
5105
5106             case 2: /* FICOM m16int */
5107                DIP("ficomw %s\n", dis_buf);
5108                /* This forces C1 to zero, which isn't right. */
5109                put_C3210( 
5110                    binop( Iop_And32,
5111                           binop(Iop_Shl32, 
5112                                 binop(Iop_CmpF64, 
5113                                       get_ST(0),
5114                                       unop(Iop_I32StoF64, 
5115                                          unop(Iop_16Sto32,
5116                                            loadLE(Ity_I16,mkexpr(addr))))),
5117                                 mkU8(8)),
5118                           mkU32(0x4500)
5119                    ));
5120                break;
5121
5122             case 3: /* FICOMP m16int */
5123                DIP("ficompw %s\n", dis_buf);
5124                /* This forces C1 to zero, which isn't right. */
5125                put_C3210( 
5126                    binop( Iop_And32,
5127                           binop(Iop_Shl32, 
5128                                 binop(Iop_CmpF64, 
5129                                       get_ST(0),
5130                                       unop(Iop_I32StoF64, 
5131                                          unop(Iop_16Sto32,
5132                                               loadLE(Ity_I16,mkexpr(addr))))),
5133                                 mkU8(8)),
5134                           mkU32(0x4500)
5135                    ));
5136                fp_pop();
5137                break;
5138
5139             case 4: /* FISUB m16int */ /* ST(0) -= m16int */
5140                DIP("fisubw %s\n", dis_buf);
5141                fop = Iop_SubF64;
5142                goto do_fop_m16;
5143
5144             case 5: /* FISUBR m16int */ /* ST(0) = m16int - ST(0) */
5145                DIP("fisubrw %s\n", dis_buf);
5146                fop = Iop_SubF64;
5147                goto do_foprev_m16;
5148
5149             case 6: /* FIDIV m16int */ /* ST(0) /= m16int */
5150                DIP("fisubw %s\n", dis_buf);
5151                fop = Iop_DivF64;
5152                goto do_fop_m16;
5153
5154             case 7: /* FIDIVR m16int */ /* ST(0) = m16int / ST(0) */
5155                DIP("fidivrw %s\n", dis_buf);
5156                fop = Iop_DivF64;
5157                goto do_foprev_m16;
5158
5159             do_fop_m16:
5160                put_ST_UNCHECKED(0, 
5161                   triop(fop, 
5162                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
5163                         get_ST(0),
5164                         unop(Iop_I32StoF64,
5165                              unop(Iop_16Sto32, 
5166                                   loadLE(Ity_I16, mkexpr(addr))))));
5167                break;
5168
5169             do_foprev_m16:
5170                put_ST_UNCHECKED(0, 
5171                   triop(fop, 
5172                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
5173                         unop(Iop_I32StoF64,
5174                              unop(Iop_16Sto32, 
5175                                   loadLE(Ity_I16, mkexpr(addr)))),
5176                         get_ST(0)));
5177                break;
5178
5179             default:
5180                vex_printf("unhandled opc_aux = 0x%2x\n", gregOfRM(modrm));
5181                vex_printf("first_opcode == 0xDE\n");
5182                goto decode_fail;
5183          }
5184
5185       } else {
5186
5187          delta++;
5188          switch (modrm) {
5189
5190             case 0xC0 ... 0xC7: /* FADDP %st(0),%st(?) */
5191                fp_do_op_ST_ST ( "add", Iop_AddF64, 0, modrm - 0xC0, True );
5192                break;
5193
5194             case 0xC8 ... 0xCF: /* FMULP %st(0),%st(?) */
5195                fp_do_op_ST_ST ( "mul", Iop_MulF64, 0, modrm - 0xC8, True );
5196                break;
5197
5198             case 0xD9: /* FCOMPP %st(0),%st(1) */
5199                DIP("fuompp %%st(0),%%st(1)\n");
5200                /* This forces C1 to zero, which isn't right. */
5201                put_C3210( 
5202                    binop( Iop_And32,
5203                           binop(Iop_Shl32, 
5204                                 binop(Iop_CmpF64, get_ST(0), get_ST(1)),
5205                                 mkU8(8)),
5206                           mkU32(0x4500)
5207                    ));
5208                fp_pop();
5209                fp_pop();
5210                break;
5211
5212             case 0xE0 ... 0xE7: /* FSUBRP %st(0),%st(?) */
5213                fp_do_oprev_ST_ST ( "subr", Iop_SubF64, 0,  modrm - 0xE0, True );
5214                break;
5215
5216             case 0xE8 ... 0xEF: /* FSUBP %st(0),%st(?) */
5217                fp_do_op_ST_ST ( "sub", Iop_SubF64, 0,  modrm - 0xE8, True );
5218                break;
5219
5220             case 0xF0 ... 0xF7: /* FDIVRP %st(0),%st(?) */
5221                fp_do_oprev_ST_ST ( "divr", Iop_DivF64, 0, modrm - 0xF0, True );
5222                break;
5223
5224             case 0xF8 ... 0xFF: /* FDIVP %st(0),%st(?) */
5225                fp_do_op_ST_ST ( "div", Iop_DivF64, 0, modrm - 0xF8, True );
5226                break;
5227
5228             default: 
5229                goto decode_fail;
5230          }
5231
5232       }
5233    }
5234
5235    /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDF opcodes +-+-+-+-+-+-+-+ */
5236    else
5237    if (first_opcode == 0xDF) {
5238
5239       if (modrm < 0xC0) {
5240
5241          /* bits 5,4,3 are an opcode extension, and the modRM also
5242             specifies an address. */
5243          IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
5244          delta += len;
5245
5246          switch (gregOfRM(modrm)) {
5247
5248             case 0: /* FILD m16int */
5249                DIP("fildw %s\n", dis_buf);
5250                fp_push();
5251                put_ST(0, unop(Iop_I32StoF64,
5252                               unop(Iop_16Sto32,
5253                                    loadLE(Ity_I16, mkexpr(addr)))));
5254                break;
5255
5256             case 1: /* FISTTPS m16 (SSE3) */
5257                DIP("fisttps %s\n", dis_buf);
5258                storeLE( mkexpr(addr), 
5259                         binop(Iop_F64toI16S, mkU32(Irrm_ZERO), get_ST(0)) );
5260                fp_pop();
5261                break;
5262
5263             case 2: /* FIST m16 */
5264                DIP("fistp %s\n", dis_buf);
5265                storeLE( mkexpr(addr), 
5266                         binop(Iop_F64toI16S, get_roundingmode(), get_ST(0)) );
5267                break;
5268
5269             case 3: /* FISTP m16 */
5270                DIP("fistps %s\n", dis_buf);
5271                storeLE( mkexpr(addr), 
5272                         binop(Iop_F64toI16S, get_roundingmode(), get_ST(0)) );
5273                fp_pop();
5274                break;
5275
5276             case 5: /* FILD m64 */
5277                DIP("fildll %s\n", dis_buf);
5278                fp_push();
5279                put_ST(0, binop(Iop_I64StoF64,
5280                                get_roundingmode(),
5281                                loadLE(Ity_I64, mkexpr(addr))));
5282                break;
5283
5284             case 7: /* FISTP m64 */
5285                DIP("fistpll %s\n", dis_buf);
5286                storeLE( mkexpr(addr), 
5287                         binop(Iop_F64toI64S, get_roundingmode(), get_ST(0)) );
5288                fp_pop();
5289                break;
5290
5291             default:
5292                vex_printf("unhandled opc_aux = 0x%2x\n", gregOfRM(modrm));
5293                vex_printf("first_opcode == 0xDF\n");
5294                goto decode_fail;
5295          }
5296
5297       } else {
5298
5299          delta++;
5300          switch (modrm) {
5301
5302             case 0xC0: /* FFREEP %st(0) */
5303                DIP("ffreep %%st(%d)\n", 0);
5304                put_ST_TAG ( 0, mkU8(0) );
5305                fp_pop();
5306                break;
5307
5308             case 0xE0: /* FNSTSW %ax */
5309                DIP("fnstsw %%ax\n");
5310                /* Get the FPU status word value and dump it in %AX. */
5311                if (0) {
5312                   /* The obvious thing to do is simply dump the 16-bit
5313                      status word value in %AX.  However, due to a
5314                      limitation in Memcheck's origin tracking
5315                      machinery, this causes Memcheck not to track the
5316                      origin of any undefinedness into %AH (only into
5317                      %AL/%AX/%EAX), which means origins are lost in
5318                      the sequence "fnstsw %ax; test $M,%ah; jcond .." */
5319                   putIReg(2, R_EAX, get_FPU_sw());
5320                } else {
5321                   /* So a somewhat lame kludge is to make it very
5322                      clear to Memcheck that the value is written to
5323                      both %AH and %AL.  This generates marginally
5324                      worse code, but I don't think it matters much. */
5325                   IRTemp t16 = newTemp(Ity_I16);
5326                   assign(t16, get_FPU_sw());
5327                   putIReg( 1, R_AL, unop(Iop_16to8, mkexpr(t16)) );
5328                   putIReg( 1, R_AH, unop(Iop_16HIto8, mkexpr(t16)) );
5329                }
5330                break;
5331
5332             case 0xE8 ... 0xEF: /* FUCOMIP %st(0),%st(?) */
5333                fp_do_ucomi_ST0_STi( (UInt)modrm - 0xE8, True );
5334                break;
5335
5336             case 0xF0 ... 0xF7: /* FCOMIP %st(0),%st(?) */
5337                /* not really right since COMIP != UCOMIP */
5338                fp_do_ucomi_ST0_STi( (UInt)modrm - 0xF0, True );
5339                break;
5340
5341             default: 
5342                goto decode_fail;
5343          }
5344       }
5345
5346    }
5347
5348    else
5349    vpanic("dis_FPU(x86): invalid primary opcode");
5350
5351    *decode_ok = True;
5352    return delta;
5353
5354   decode_fail:
5355    *decode_ok = False;
5356    return delta;
5357 }
5358
5359
5360 /*------------------------------------------------------------*/
5361 /*---                                                      ---*/
5362 /*--- MMX INSTRUCTIONS                                     ---*/
5363 /*---                                                      ---*/
5364 /*------------------------------------------------------------*/
5365
5366 /* Effect of MMX insns on x87 FPU state (table 11-2 of 
5367    IA32 arch manual, volume 3):
5368
5369    Read from, or write to MMX register (viz, any insn except EMMS):
5370    * All tags set to Valid (non-empty) -- FPTAGS[i] := nonzero
5371    * FP stack pointer set to zero
5372
5373    EMMS:
5374    * All tags set to Invalid (empty) -- FPTAGS[i] := zero
5375    * FP stack pointer set to zero
5376 */
5377
5378 static void do_MMX_preamble ( void )
5379 {
5380    Int         i;
5381    IRRegArray* descr = mkIRRegArray( OFFB_FPTAGS, Ity_I8, 8 );
5382    IRExpr*     zero  = mkU32(0);
5383    IRExpr*     tag1  = mkU8(1);
5384    put_ftop(zero);
5385    for (i = 0; i < 8; i++)
5386       stmt( IRStmt_PutI( descr, zero, i, tag1 ) );
5387 }
5388
5389 static void do_EMMS_preamble ( void )
5390 {
5391    Int         i;
5392    IRRegArray* descr = mkIRRegArray( OFFB_FPTAGS, Ity_I8, 8 );
5393    IRExpr*     zero  = mkU32(0);
5394    IRExpr*     tag0  = mkU8(0);
5395    put_ftop(zero);
5396    for (i = 0; i < 8; i++)
5397       stmt( IRStmt_PutI( descr, zero, i, tag0 ) );
5398 }
5399
5400
5401 static IRExpr* getMMXReg ( UInt archreg )
5402 {
5403    vassert(archreg < 8);
5404    return IRExpr_Get( OFFB_FPREGS + 8 * archreg, Ity_I64 );
5405 }
5406
5407
5408 static void putMMXReg ( UInt archreg, IRExpr* e )
5409 {
5410    vassert(archreg < 8);
5411    vassert(typeOfIRExpr(irsb->tyenv,e) == Ity_I64);
5412    stmt( IRStmt_Put( OFFB_FPREGS + 8 * archreg, e ) );
5413 }
5414
5415
5416 /* Helper for non-shift MMX insns.  Note this is incomplete in the
5417    sense that it does not first call do_MMX_preamble() -- that is the
5418    responsibility of its caller. */
5419
5420 static 
5421 UInt dis_MMXop_regmem_to_reg ( UChar  sorb,
5422                                Int    delta,
5423                                UChar  opc,
5424                                HChar* name,
5425                                Bool   show_granularity )
5426 {
5427    HChar   dis_buf[50];
5428    UChar   modrm = getIByte(delta);
5429    Bool    isReg = epartIsReg(modrm);
5430    IRExpr* argL  = NULL;
5431    IRExpr* argR  = NULL;
5432    IRExpr* argG  = NULL;
5433    IRExpr* argE  = NULL;
5434    IRTemp  res   = newTemp(Ity_I64);
5435
5436    Bool    invG  = False;
5437    IROp    op    = Iop_INVALID;
5438    void*   hAddr = NULL;
5439    HChar*  hName = NULL;
5440    Bool    eLeft = False;
5441
5442 #  define XXX(_name) do { hAddr = &_name; hName = #_name; } while (0)
5443
5444    switch (opc) {
5445       /* Original MMX ones */
5446       case 0xFC: op = Iop_Add8x8; break;
5447       case 0xFD: op = Iop_Add16x4; break;
5448       case 0xFE: op = Iop_Add32x2; break;
5449
5450       case 0xEC: op = Iop_QAdd8Sx8; break;
5451       case 0xED: op = Iop_QAdd16Sx4; break;
5452
5453       case 0xDC: op = Iop_QAdd8Ux8; break;
5454       case 0xDD: op = Iop_QAdd16Ux4; break;
5455
5456       case 0xF8: op = Iop_Sub8x8;  break;
5457       case 0xF9: op = Iop_Sub16x4; break;
5458       case 0xFA: op = Iop_Sub32x2; break;
5459
5460       case 0xE8: op = Iop_QSub8Sx8; break;
5461       case 0xE9: op = Iop_QSub16Sx4; break;
5462
5463       case 0xD8: op = Iop_QSub8Ux8; break;
5464       case 0xD9: op = Iop_QSub16Ux4; break;
5465
5466       case 0xE5: op = Iop_MulHi16Sx4; break;
5467       case 0xD5: op = Iop_Mul16x4; break;
5468       case 0xF5: XXX(x86g_calculate_mmx_pmaddwd); break;
5469
5470       case 0x74: op = Iop_CmpEQ8x8; break;
5471       case 0x75: op = Iop_CmpEQ16x4; break;
5472       case 0x76: op = Iop_CmpEQ32x2; break;
5473
5474       case 0x64: op = Iop_CmpGT8Sx8; break;
5475       case 0x65: op = Iop_CmpGT16Sx4; break;
5476       case 0x66: op = Iop_CmpGT32Sx2; break;
5477
5478       case 0x6B: op = Iop_QNarrow32Sx2; eLeft = True; break;
5479       case 0x63: op = Iop_QNarrow16Sx4; eLeft = True; break;
5480       case 0x67: op = Iop_QNarrow16Ux4; eLeft = True; break;
5481
5482       case 0x68: op = Iop_InterleaveHI8x8;  eLeft = True; break;
5483       case 0x69: op = Iop_InterleaveHI16x4; eLeft = True; break;
5484       case 0x6A: op = Iop_InterleaveHI32x2; eLeft = True; break;
5485
5486       case 0x60: op = Iop_InterleaveLO8x8;  eLeft = True; break;
5487       case 0x61: op = Iop_InterleaveLO16x4; eLeft = True; break;
5488       case 0x62: op = Iop_InterleaveLO32x2; eLeft = True; break;
5489
5490       case 0xDB: op = Iop_And64; break;
5491       case 0xDF: op = Iop_And64; invG = True; break;
5492       case 0xEB: op = Iop_Or64; break;
5493       case 0xEF: /* Possibly do better here if argL and argR are the
5494                     same reg */
5495                  op = Iop_Xor64; break;
5496
5497       /* Introduced in SSE1 */
5498       case 0xE0: op = Iop_Avg8Ux8;    break;
5499       case 0xE3: op = Iop_Avg16Ux4;   break;
5500       case 0xEE: op = Iop_Max16Sx4;   break;
5501       case 0xDE: op = Iop_Max8Ux8;    break;
5502       case 0xEA: op = Iop_Min16Sx4;   break;
5503       case 0xDA: op = Iop_Min8Ux8;    break;
5504       case 0xE4: op = Iop_MulHi16Ux4; break;
5505       case 0xF6: XXX(x86g_calculate_mmx_psadbw); break;
5506
5507       /* Introduced in SSE2 */
5508       case 0xD4: op = Iop_Add64; break;
5509       case 0xFB: op = Iop_Sub64; break;
5510
5511       default: 
5512          vex_printf("\n0x%x\n", (Int)opc);
5513          vpanic("dis_MMXop_regmem_to_reg");
5514    }
5515
5516 #  undef XXX
5517
5518    argG = getMMXReg(gregOfRM(modrm));
5519    if (invG)
5520       argG = unop(Iop_Not64, argG);
5521
5522    if (isReg) {
5523       delta++;
5524       argE = getMMXReg(eregOfRM(modrm));
5525    } else {
5526       Int    len;
5527       IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
5528       delta += len;
5529       argE = loadLE(Ity_I64, mkexpr(addr));
5530    }
5531
5532    if (eLeft) {
5533       argL = argE;
5534       argR = argG;
5535    } else {
5536       argL = argG;
5537       argR = argE;
5538    }
5539
5540    if (op != Iop_INVALID) {
5541       vassert(hName == NULL);
5542       vassert(hAddr == NULL);
5543       assign(res, binop(op, argL, argR));
5544    } else {
5545       vassert(hName != NULL);
5546       vassert(hAddr != NULL);
5547       assign( res, 
5548               mkIRExprCCall(
5549                  Ity_I64, 
5550                  0/*regparms*/, hName, hAddr,
5551                  mkIRExprVec_2( argL, argR )
5552               ) 
5553             );
5554    }
5555
5556    putMMXReg( gregOfRM(modrm), mkexpr(res) );
5557
5558    DIP("%s%s %s, %s\n", 
5559        name, show_granularity ? nameMMXGran(opc & 3) : "",
5560        ( isReg ? nameMMXReg(eregOfRM(modrm)) : dis_buf ),
5561        nameMMXReg(gregOfRM(modrm)) );
5562
5563    return delta;
5564 }
5565
5566
5567 /* Vector by scalar shift of G by the amount specified at the bottom
5568    of E.  This is a straight copy of dis_SSE_shiftG_byE. */
5569
5570 static UInt dis_MMX_shiftG_byE ( UChar sorb, Int delta, 
5571                                  HChar* opname, IROp op )
5572 {
5573    HChar   dis_buf[50];
5574    Int     alen, size;
5575    IRTemp  addr;
5576    Bool    shl, shr, sar;
5577    UChar   rm   = getIByte(delta);
5578    IRTemp  g0   = newTemp(Ity_I64);
5579    IRTemp  g1   = newTemp(Ity_I64);
5580    IRTemp  amt  = newTemp(Ity_I32);
5581    IRTemp  amt8 = newTemp(Ity_I8);
5582
5583    if (epartIsReg(rm)) {
5584       assign( amt, unop(Iop_64to32, getMMXReg(eregOfRM(rm))) );
5585       DIP("%s %s,%s\n", opname,
5586                         nameMMXReg(eregOfRM(rm)),
5587                         nameMMXReg(gregOfRM(rm)) );
5588       delta++;
5589    } else {
5590       addr = disAMode ( &alen, sorb, delta, dis_buf );
5591       assign( amt, loadLE(Ity_I32, mkexpr(addr)) );
5592       DIP("%s %s,%s\n", opname,
5593                         dis_buf,
5594                         nameMMXReg(gregOfRM(rm)) );
5595       delta += alen;
5596    }
5597    assign( g0,   getMMXReg(gregOfRM(rm)) );
5598    assign( amt8, unop(Iop_32to8, mkexpr(amt)) );
5599
5600    shl = shr = sar = False;
5601    size = 0;
5602    switch (op) {
5603       case Iop_ShlN16x4: shl = True; size = 32; break;
5604       case Iop_ShlN32x2: shl = True; size = 32; break;
5605       case Iop_Shl64:    shl = True; size = 64; break;
5606       case Iop_ShrN16x4: shr = True; size = 16; break;
5607       case Iop_ShrN32x2: shr = True; size = 32; break;
5608       case Iop_Shr64:    shr = True; size = 64; break;
5609       case Iop_SarN16x4: sar = True; size = 16; break;
5610       case Iop_SarN32x2: sar = True; size = 32; break;
5611       default: vassert(0);
5612    }
5613
5614    if (shl || shr) {
5615      assign( 
5616         g1,
5617         IRExpr_Mux0X(
5618            unop(Iop_1Uto8,binop(Iop_CmpLT32U,mkexpr(amt),mkU32(size))),
5619            mkU64(0),
5620            binop(op, mkexpr(g0), mkexpr(amt8))
5621         )
5622      );
5623    } else 
5624    if (sar) {
5625      assign( 
5626         g1,
5627         IRExpr_Mux0X(
5628            unop(Iop_1Uto8,binop(Iop_CmpLT32U,mkexpr(amt),mkU32(size))),
5629            binop(op, mkexpr(g0), mkU8(size-1)),
5630            binop(op, mkexpr(g0), mkexpr(amt8))
5631         )
5632      );
5633    } else {
5634       /*NOTREACHED*/
5635       vassert(0);
5636    }
5637
5638    putMMXReg( gregOfRM(rm), mkexpr(g1) );
5639    return delta;
5640 }
5641
5642
5643 /* Vector by scalar shift of E by an immediate byte.  This is a
5644    straight copy of dis_SSE_shiftE_imm. */
5645
5646 static 
5647 UInt dis_MMX_shiftE_imm ( Int delta, HChar* opname, IROp op )
5648 {
5649    Bool    shl, shr, sar;
5650    UChar   rm   = getIByte(delta);
5651    IRTemp  e0   = newTemp(Ity_I64);
5652    IRTemp  e1   = newTemp(Ity_I64);
5653    UChar   amt, size;
5654    vassert(epartIsReg(rm));
5655    vassert(gregOfRM(rm) == 2 
5656            || gregOfRM(rm) == 4 || gregOfRM(rm) == 6);
5657    amt = getIByte(delta+1);
5658    delta += 2;
5659    DIP("%s $%d,%s\n", opname,
5660                       (Int)amt,
5661                       nameMMXReg(eregOfRM(rm)) );
5662
5663    assign( e0, getMMXReg(eregOfRM(rm)) );
5664
5665    shl = shr = sar = False;
5666    size = 0;
5667    switch (op) {
5668       case Iop_ShlN16x4: shl = True; size = 16; break;
5669       case Iop_ShlN32x2: shl = True; size = 32; break;
5670       case Iop_Shl64:    shl = True; size = 64; break;
5671       case Iop_SarN16x4: sar = True; size = 16; break;
5672       case Iop_SarN32x2: sar = True; size = 32; break;
5673       case Iop_ShrN16x4: shr = True; size = 16; break;
5674       case Iop_ShrN32x2: shr = True; size = 32; break;
5675       case Iop_Shr64:    shr = True; size = 64; break;
5676       default: vassert(0);
5677    }
5678
5679    if (shl || shr) {
5680       assign( e1, amt >= size 
5681                      ? mkU64(0)
5682                      : binop(op, mkexpr(e0), mkU8(amt))
5683       );
5684    } else 
5685    if (sar) {
5686       assign( e1, amt >= size 
5687                      ? binop(op, mkexpr(e0), mkU8(size-1))
5688                      : binop(op, mkexpr(e0), mkU8(amt))
5689       );
5690    } else {
5691       /*NOTREACHED*/
5692       vassert(0);
5693    }
5694
5695    putMMXReg( eregOfRM(rm), mkexpr(e1) );
5696    return delta;
5697 }
5698
5699
5700 /* Completely handle all MMX instructions except emms. */
5701
5702 static
5703 UInt dis_MMX ( Bool* decode_ok, UChar sorb, Int sz, Int delta )
5704 {
5705    Int   len;
5706    UChar modrm;
5707    HChar dis_buf[50];
5708    UChar opc = getIByte(delta);
5709    delta++;
5710
5711    /* dis_MMX handles all insns except emms. */
5712    do_MMX_preamble();
5713
5714    switch (opc) {
5715
5716       case 0x6E: 
5717          /* MOVD (src)ireg-or-mem (E), (dst)mmxreg (G)*/
5718          if (sz != 4) 
5719             goto mmx_decode_failure;
5720          modrm = getIByte(delta);
5721          if (epartIsReg(modrm)) {
5722             delta++;
5723             putMMXReg(
5724                gregOfRM(modrm),
5725                binop( Iop_32HLto64,
5726                       mkU32(0),
5727                       getIReg(4, eregOfRM(modrm)) ) );
5728             DIP("movd %s, %s\n", 
5729                 nameIReg(4,eregOfRM(modrm)), nameMMXReg(gregOfRM(modrm)));
5730          } else {
5731             IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
5732             delta += len;
5733             putMMXReg(
5734                gregOfRM(modrm),
5735                binop( Iop_32HLto64,
5736                       mkU32(0),
5737                       loadLE(Ity_I32, mkexpr(addr)) ) );
5738             DIP("movd %s, %s\n", dis_buf, nameMMXReg(gregOfRM(modrm)));
5739          }
5740          break;
5741
5742       case 0x7E: /* MOVD (src)mmxreg (G), (dst)ireg-or-mem (E) */
5743          if (sz != 4) 
5744             goto mmx_decode_failure;
5745          modrm = getIByte(delta);
5746          if (epartIsReg(modrm)) {
5747             delta++;
5748             putIReg( 4, eregOfRM(modrm),
5749                      unop(Iop_64to32, getMMXReg(gregOfRM(modrm)) ) );
5750             DIP("movd %s, %s\n", 
5751                 nameMMXReg(gregOfRM(modrm)), nameIReg(4,eregOfRM(modrm)));
5752          } else {
5753             IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
5754             delta += len;
5755             storeLE( mkexpr(addr),
5756                      unop(Iop_64to32, getMMXReg(gregOfRM(modrm)) ) );
5757             DIP("movd %s, %s\n", nameMMXReg(gregOfRM(modrm)), dis_buf);
5758          }
5759          break;
5760
5761       case 0x6F:
5762          /* MOVQ (src)mmxreg-or-mem, (dst)mmxreg */
5763          if (sz != 4) 
5764             goto mmx_decode_failure;
5765          modrm = getIByte(delta);
5766          if (epartIsReg(modrm)) {
5767             delta++;
5768             putMMXReg( gregOfRM(modrm), getMMXReg(eregOfRM(modrm)) );
5769             DIP("movq %s, %s\n", 
5770                 nameMMXReg(eregOfRM(modrm)), nameMMXReg(gregOfRM(modrm)));
5771          } else {
5772             IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
5773             delta += len;
5774             putMMXReg( gregOfRM(modrm), loadLE(Ity_I64, mkexpr(addr)) );
5775             DIP("movq %s, %s\n", 
5776                 dis_buf, nameMMXReg(gregOfRM(modrm)));
5777          }
5778          break;
5779
5780       case 0x7F:
5781          /* MOVQ (src)mmxreg, (dst)mmxreg-or-mem */
5782          if (sz != 4) 
5783             goto mmx_decode_failure;
5784          modrm = getIByte(delta);
5785          if (epartIsReg(modrm)) {
5786             delta++;
5787             putMMXReg( eregOfRM(modrm), getMMXReg(gregOfRM(modrm)) );
5788             DIP("movq %s, %s\n", 
5789                 nameMMXReg(gregOfRM(modrm)), nameMMXReg(eregOfRM(modrm)));
5790          } else {
5791             IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
5792             delta += len;
5793             storeLE( mkexpr(addr), getMMXReg(gregOfRM(modrm)) );
5794             DIP("mov(nt)q %s, %s\n", 
5795                 nameMMXReg(gregOfRM(modrm)), dis_buf);
5796          }
5797          break;
5798
5799       case 0xFC: 
5800       case 0xFD: 
5801       case 0xFE: /* PADDgg (src)mmxreg-or-mem, (dst)mmxreg */
5802          if (sz != 4) 
5803             goto mmx_decode_failure;
5804          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "padd", True );
5805          break;
5806
5807       case 0xEC: 
5808       case 0xED: /* PADDSgg (src)mmxreg-or-mem, (dst)mmxreg */
5809          if (sz != 4) 
5810             goto mmx_decode_failure;
5811          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "padds", True );
5812          break;
5813
5814       case 0xDC: 
5815       case 0xDD: /* PADDUSgg (src)mmxreg-or-mem, (dst)mmxreg */
5816          if (sz != 4) 
5817             goto mmx_decode_failure;
5818          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "paddus", True );
5819          break;
5820
5821       case 0xF8: 
5822       case 0xF9: 
5823       case 0xFA: /* PSUBgg (src)mmxreg-or-mem, (dst)mmxreg */
5824          if (sz != 4) 
5825             goto mmx_decode_failure;
5826          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "psub", True );
5827          break;
5828
5829       case 0xE8: 
5830       case 0xE9: /* PSUBSgg (src)mmxreg-or-mem, (dst)mmxreg */
5831          if (sz != 4) 
5832             goto mmx_decode_failure;
5833          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "psubs", True );
5834          break;
5835
5836       case 0xD8: 
5837       case 0xD9: /* PSUBUSgg (src)mmxreg-or-mem, (dst)mmxreg */
5838          if (sz != 4) 
5839             goto mmx_decode_failure;
5840          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "psubus", True );
5841          break;
5842
5843       case 0xE5: /* PMULHW (src)mmxreg-or-mem, (dst)mmxreg */
5844          if (sz != 4) 
5845             goto mmx_decode_failure;
5846          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "pmulhw", False );
5847          break;
5848
5849       case 0xD5: /* PMULLW (src)mmxreg-or-mem, (dst)mmxreg */
5850          if (sz != 4) 
5851             goto mmx_decode_failure;
5852          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "pmullw", False );
5853          break;
5854
5855       case 0xF5: /* PMADDWD (src)mmxreg-or-mem, (dst)mmxreg */
5856          vassert(sz == 4);
5857          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "pmaddwd", False );
5858          break;
5859
5860       case 0x74: 
5861       case 0x75: 
5862       case 0x76: /* PCMPEQgg (src)mmxreg-or-mem, (dst)mmxreg */
5863          if (sz != 4) 
5864             goto mmx_decode_failure;
5865          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "pcmpeq", True );
5866          break;
5867
5868       case 0x64: 
5869       case 0x65: 
5870       case 0x66: /* PCMPGTgg (src)mmxreg-or-mem, (dst)mmxreg */
5871          if (sz != 4) 
5872             goto mmx_decode_failure;
5873          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "pcmpgt", True );
5874          break;
5875
5876       case 0x6B: /* PACKSSDW (src)mmxreg-or-mem, (dst)mmxreg */
5877          if (sz != 4) 
5878             goto mmx_decode_failure;
5879          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "packssdw", False );
5880          break;
5881
5882       case 0x63: /* PACKSSWB (src)mmxreg-or-mem, (dst)mmxreg */
5883          if (sz != 4) 
5884             goto mmx_decode_failure;
5885          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "packsswb", False );
5886          break;
5887
5888       case 0x67: /* PACKUSWB (src)mmxreg-or-mem, (dst)mmxreg */
5889          if (sz != 4) 
5890             goto mmx_decode_failure;
5891          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "packuswb", False );
5892          break;
5893
5894       case 0x68: 
5895       case 0x69: 
5896       case 0x6A: /* PUNPCKHgg (src)mmxreg-or-mem, (dst)mmxreg */
5897          if (sz != 4) 
5898             goto mmx_decode_failure;
5899          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "punpckh", True );
5900          break;
5901
5902       case 0x60: 
5903       case 0x61: 
5904       case 0x62: /* PUNPCKLgg (src)mmxreg-or-mem, (dst)mmxreg */
5905          if (sz != 4) 
5906             goto mmx_decode_failure;
5907          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "punpckl", True );
5908          break;
5909
5910       case 0xDB: /* PAND (src)mmxreg-or-mem, (dst)mmxreg */
5911          if (sz != 4) 
5912             goto mmx_decode_failure;
5913          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "pand", False );
5914          break;
5915
5916       case 0xDF: /* PANDN (src)mmxreg-or-mem, (dst)mmxreg */
5917          if (sz != 4) 
5918             goto mmx_decode_failure;
5919          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "pandn", False );
5920          break;
5921
5922       case 0xEB: /* POR (src)mmxreg-or-mem, (dst)mmxreg */
5923          if (sz != 4) 
5924             goto mmx_decode_failure;
5925          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "por", False );
5926          break;
5927
5928       case 0xEF: /* PXOR (src)mmxreg-or-mem, (dst)mmxreg */
5929          if (sz != 4) 
5930             goto mmx_decode_failure;
5931          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "pxor", False );
5932          break; 
5933
5934 #     define SHIFT_BY_REG(_name,_op)                                 \
5935                 delta = dis_MMX_shiftG_byE(sorb, delta, _name, _op); \
5936                 break;
5937
5938       /* PSLLgg (src)mmxreg-or-mem, (dst)mmxreg */
5939       case 0xF1: SHIFT_BY_REG("psllw", Iop_ShlN16x4);
5940       case 0xF2: SHIFT_BY_REG("pslld", Iop_ShlN32x2);
5941       case 0xF3: SHIFT_BY_REG("psllq", Iop_Shl64);
5942
5943       /* PSRLgg (src)mmxreg-or-mem, (dst)mmxreg */
5944       case 0xD1: SHIFT_BY_REG("psrlw", Iop_ShrN16x4);
5945       case 0xD2: SHIFT_BY_REG("psrld", Iop_ShrN32x2);
5946       case 0xD3: SHIFT_BY_REG("psrlq", Iop_Shr64);
5947
5948       /* PSRAgg (src)mmxreg-or-mem, (dst)mmxreg */
5949       case 0xE1: SHIFT_BY_REG("psraw", Iop_SarN16x4);
5950       case 0xE2: SHIFT_BY_REG("psrad", Iop_SarN32x2);
5951
5952 #     undef SHIFT_BY_REG
5953
5954       case 0x71: 
5955       case 0x72: 
5956       case 0x73: {
5957          /* (sz==4): PSLLgg/PSRAgg/PSRLgg mmxreg by imm8 */
5958          UChar byte2, subopc;
5959          if (sz != 4) 
5960             goto mmx_decode_failure;
5961          byte2  = getIByte(delta);           /* amode / sub-opcode */
5962          subopc = toUChar( (byte2 >> 3) & 7 );
5963
5964 #        define SHIFT_BY_IMM(_name,_op)                         \
5965              do { delta = dis_MMX_shiftE_imm(delta,_name,_op);  \
5966              } while (0)
5967
5968               if (subopc == 2 /*SRL*/ && opc == 0x71) 
5969                  SHIFT_BY_IMM("psrlw", Iop_ShrN16x4);
5970          else if (subopc == 2 /*SRL*/ && opc == 0x72) 
5971                  SHIFT_BY_IMM("psrld", Iop_ShrN32x2);
5972          else if (subopc == 2 /*SRL*/ && opc == 0x73) 
5973                  SHIFT_BY_IMM("psrlq", Iop_Shr64);
5974
5975          else if (subopc == 4 /*SAR*/ && opc == 0x71) 
5976                  SHIFT_BY_IMM("psraw", Iop_SarN16x4);
5977          else if (subopc == 4 /*SAR*/ && opc == 0x72) 
5978                  SHIFT_BY_IMM("psrad", Iop_SarN32x2);
5979
5980          else if (subopc == 6 /*SHL*/ && opc == 0x71) 
5981                  SHIFT_BY_IMM("psllw", Iop_ShlN16x4);
5982          else if (subopc == 6 /*SHL*/ && opc == 0x72) 
5983                  SHIFT_BY_IMM("pslld", Iop_ShlN32x2);
5984          else if (subopc == 6 /*SHL*/ && opc == 0x73) 
5985                  SHIFT_BY_IMM("psllq", Iop_Shl64);
5986
5987          else goto mmx_decode_failure;
5988
5989 #        undef SHIFT_BY_IMM
5990          break;
5991       }
5992
5993       case 0xF7: {
5994          IRTemp addr    = newTemp(Ity_I32);
5995          IRTemp regD    = newTemp(Ity_I64);
5996          IRTemp regM    = newTemp(Ity_I64);
5997          IRTemp mask    = newTemp(Ity_I64);
5998          IRTemp olddata = newTemp(Ity_I64);
5999          IRTemp newdata = newTemp(Ity_I64);
6000
6001          modrm = getIByte(delta);
6002          if (sz != 4 || (!epartIsReg(modrm)))
6003             goto mmx_decode_failure;
6004          delta++;
6005
6006          assign( addr, handleSegOverride( sorb, getIReg(4, R_EDI) ));
6007          assign( regM, getMMXReg( eregOfRM(modrm) ));
6008          assign( regD, getMMXReg( gregOfRM(modrm) ));
6009          assign( mask, binop(Iop_SarN8x8, mkexpr(regM), mkU8(7)) );
6010          assign( olddata, loadLE( Ity_I64, mkexpr(addr) ));
6011          assign( newdata, 
6012                  binop(Iop_Or64, 
6013                        binop(Iop_And64, 
6014                              mkexpr(regD), 
6015                              mkexpr(mask) ),
6016                        binop(Iop_And64, 
6017                              mkexpr(olddata),
6018                              unop(Iop_Not64, mkexpr(mask)))) );
6019          storeLE( mkexpr(addr), mkexpr(newdata) );
6020          DIP("maskmovq %s,%s\n", nameMMXReg( eregOfRM(modrm) ),
6021                                  nameMMXReg( gregOfRM(modrm) ) );
6022          break;
6023       }
6024
6025       /* --- MMX decode failure --- */
6026       default:
6027       mmx_decode_failure:
6028          *decode_ok = False;
6029          return delta; /* ignored */
6030
6031    }
6032
6033    *decode_ok = True;
6034    return delta;
6035 }
6036
6037
6038 /*------------------------------------------------------------*/
6039 /*--- More misc arithmetic and other obscure insns.        ---*/
6040 /*------------------------------------------------------------*/
6041
6042 /* Double length left and right shifts.  Apparently only required in
6043    v-size (no b- variant). */
6044 static
6045 UInt dis_SHLRD_Gv_Ev ( UChar sorb,
6046                        Int delta, UChar modrm,
6047                        Int sz,
6048                        IRExpr* shift_amt,
6049                        Bool amt_is_literal,
6050                        HChar* shift_amt_txt,
6051                        Bool left_shift )
6052 {
6053    /* shift_amt :: Ity_I8 is the amount to shift.  shift_amt_txt is used
6054       for printing it.   And eip on entry points at the modrm byte. */
6055    Int len;
6056    HChar dis_buf[50];
6057
6058    IRType ty       = szToITy(sz);
6059    IRTemp gsrc     = newTemp(ty);
6060    IRTemp esrc     = newTemp(ty);
6061    IRTemp addr     = IRTemp_INVALID;
6062    IRTemp tmpSH    = newTemp(Ity_I8);
6063    IRTemp tmpL     = IRTemp_INVALID;
6064    IRTemp tmpRes   = IRTemp_INVALID;
6065    IRTemp tmpSubSh = IRTemp_INVALID;
6066    IROp   mkpair;
6067    IROp   getres;
6068    IROp   shift;
6069    IRExpr* mask = NULL;
6070
6071    vassert(sz == 2 || sz == 4);
6072
6073    /* The E-part is the destination; this is shifted.  The G-part
6074       supplies bits to be shifted into the E-part, but is not
6075       changed.  
6076
6077       If shifting left, form a double-length word with E at the top
6078       and G at the bottom, and shift this left.  The result is then in
6079       the high part.
6080
6081       If shifting right, form a double-length word with G at the top
6082       and E at the bottom, and shift this right.  The result is then
6083       at the bottom.  */
6084
6085    /* Fetch the operands. */
6086
6087    assign( gsrc, getIReg(sz, gregOfRM(modrm)) );
6088
6089    if (epartIsReg(modrm)) {
6090       delta++;
6091       assign( esrc, getIReg(sz, eregOfRM(modrm)) );
6092       DIP("sh%cd%c %s, %s, %s\n",
6093           ( left_shift ? 'l' : 'r' ), nameISize(sz), 
6094           shift_amt_txt,
6095           nameIReg(sz, gregOfRM(modrm)), nameIReg(sz, eregOfRM(modrm)));
6096    } else {
6097       addr = disAMode ( &len, sorb, delta, dis_buf );
6098       delta += len;
6099       assign( esrc, loadLE(ty, mkexpr(addr)) );
6100       DIP("sh%cd%c %s, %s, %s\n", 
6101           ( left_shift ? 'l' : 'r' ), nameISize(sz), 
6102           shift_amt_txt,
6103           nameIReg(sz, gregOfRM(modrm)), dis_buf);
6104    }
6105
6106    /* Round up the relevant primops. */
6107
6108    if (sz == 4) {
6109       tmpL     = newTemp(Ity_I64);
6110       tmpRes   = newTemp(Ity_I32);
6111       tmpSubSh = newTemp(Ity_I32);
6112       mkpair   = Iop_32HLto64;
6113       getres   = left_shift ? Iop_64HIto32 : Iop_64to32;
6114       shift    = left_shift ? Iop_Shl64 : Iop_Shr64;
6115       mask     = mkU8(31);
6116    } else {
6117       /* sz == 2 */
6118       tmpL     = newTemp(Ity_I32);
6119       tmpRes   = newTemp(Ity_I16);
6120       tmpSubSh = newTemp(Ity_I16);
6121       mkpair   = Iop_16HLto32;
6122       getres   = left_shift ? Iop_32HIto16 : Iop_32to16;
6123       shift    = left_shift ? Iop_Shl32 : Iop_Shr32;
6124       mask     = mkU8(15);
6125    }
6126
6127    /* Do the shift, calculate the subshift value, and set 
6128       the flag thunk. */
6129
6130    assign( tmpSH, binop(Iop_And8, shift_amt, mask) );
6131
6132    if (left_shift)
6133       assign( tmpL, binop(mkpair, mkexpr(esrc), mkexpr(gsrc)) );
6134    else
6135       assign( tmpL, binop(mkpair, mkexpr(gsrc), mkexpr(esrc)) );
6136
6137    assign( tmpRes, unop(getres, binop(shift, mkexpr(tmpL), mkexpr(tmpSH)) ) );
6138    assign( tmpSubSh, 
6139            unop(getres, 
6140                 binop(shift, 
6141                       mkexpr(tmpL), 
6142                       binop(Iop_And8, 
6143                             binop(Iop_Sub8, mkexpr(tmpSH), mkU8(1) ),
6144                             mask))) );
6145
6146    setFlags_DEP1_DEP2_shift ( left_shift ? Iop_Shl32 : Iop_Sar32,
6147                               tmpRes, tmpSubSh, ty, tmpSH );
6148
6149    /* Put result back. */
6150
6151    if (epartIsReg(modrm)) {
6152       putIReg(sz, eregOfRM(modrm), mkexpr(tmpRes));
6153    } else {
6154       storeLE( mkexpr(addr), mkexpr(tmpRes) );
6155    }
6156
6157    if (amt_is_literal) delta++;
6158    return delta;
6159 }
6160
6161
6162 /* Handle BT/BTS/BTR/BTC Gv, Ev.  Apparently b-size is not
6163    required. */
6164
6165 typedef enum { BtOpNone, BtOpSet, BtOpReset, BtOpComp } BtOp;
6166
6167 static HChar* nameBtOp ( BtOp op )
6168 {
6169    switch (op) {
6170       case BtOpNone:  return "";
6171       case BtOpSet:   return "s";
6172       case BtOpReset: return "r";
6173       case BtOpComp:  return "c";
6174       default: vpanic("nameBtOp(x86)");
6175    }
6176 }
6177
6178
6179 static
6180 UInt dis_bt_G_E ( VexAbiInfo* vbi,
6181                   UChar sorb, Bool locked, Int sz, Int delta, BtOp op )
6182 {
6183    HChar  dis_buf[50];
6184    UChar  modrm;
6185    Int    len;
6186    IRTemp t_fetched, t_bitno0, t_bitno1, t_bitno2, t_addr0, 
6187           t_addr1, t_esp, t_mask, t_new;
6188
6189    vassert(sz == 2 || sz == 4);
6190
6191    t_fetched = t_bitno0 = t_bitno1 = t_bitno2 
6192              = t_addr0 = t_addr1 = t_esp 
6193              = t_mask = t_new = IRTemp_INVALID;
6194
6195    t_fetched = newTemp(Ity_I8);
6196    t_new     = newTemp(Ity_I8);
6197    t_bitno0  = newTemp(Ity_I32);
6198    t_bitno1  = newTemp(Ity_I32);
6199    t_bitno2  = newTemp(Ity_I8);
6200    t_addr1   = newTemp(Ity_I32);
6201    modrm     = getIByte(delta);
6202
6203    assign( t_bitno0, widenSto32(getIReg(sz, gregOfRM(modrm))) );
6204    
6205    if (epartIsReg(modrm)) {
6206       delta++;
6207       /* Get it onto the client's stack. */
6208       t_esp = newTemp(Ity_I32);
6209       t_addr0 = newTemp(Ity_I32);
6210
6211       /* For the choice of the value 128, see comment in dis_bt_G_E in
6212          guest_amd64_toIR.c.  We point out here only that 128 is
6213          fast-cased in Memcheck and is > 0, so seems like a good
6214          choice. */
6215       vassert(vbi->guest_stack_redzone_size == 0);
6216       assign( t_esp, binop(Iop_Sub32, getIReg(4, R_ESP), mkU32(128)) );
6217       putIReg(4, R_ESP, mkexpr(t_esp));
6218
6219       storeLE( mkexpr(t_esp), getIReg(sz, eregOfRM(modrm)) );
6220
6221       /* Make t_addr0 point at it. */
6222       assign( t_addr0, mkexpr(t_esp) );
6223
6224       /* Mask out upper bits of the shift amount, since we're doing a
6225          reg. */
6226       assign( t_bitno1, binop(Iop_And32, 
6227                               mkexpr(t_bitno0), 
6228                               mkU32(sz == 4 ? 31 : 15)) );
6229
6230    } else {
6231       t_addr0 = disAMode ( &len, sorb, delta, dis_buf );
6232       delta += len;
6233       assign( t_bitno1, mkexpr(t_bitno0) );
6234    }
6235   
6236    /* At this point: t_addr0 is the address being operated on.  If it
6237       was a reg, we will have pushed it onto the client's stack.
6238       t_bitno1 is the bit number, suitably masked in the case of a
6239       reg.  */
6240   
6241    /* Now the main sequence. */
6242    assign( t_addr1, 
6243            binop(Iop_Add32, 
6244                  mkexpr(t_addr0), 
6245                  binop(Iop_Sar32, mkexpr(t_bitno1), mkU8(3))) );
6246
6247    /* t_addr1 now holds effective address */
6248
6249    assign( t_bitno2, 
6250            unop(Iop_32to8, 
6251                 binop(Iop_And32, mkexpr(t_bitno1), mkU32(7))) );
6252
6253    /* t_bitno2 contains offset of bit within byte */
6254
6255    if (op != BtOpNone) {
6256       t_mask = newTemp(Ity_I8);
6257       assign( t_mask, binop(Iop_Shl8, mkU8(1), mkexpr(t_bitno2)) );
6258    }
6259
6260    /* t_mask is now a suitable byte mask */
6261
6262    assign( t_fetched, loadLE(Ity_I8, mkexpr(t_addr1)) );
6263
6264    if (op != BtOpNone) {
6265       switch (op) {
6266          case BtOpSet:
6267             assign( t_new,
6268                     binop(Iop_Or8, mkexpr(t_fetched), mkexpr(t_mask)) );
6269             break;
6270          case BtOpComp:
6271             assign( t_new,
6272                     binop(Iop_Xor8, mkexpr(t_fetched), mkexpr(t_mask)) );
6273             break;
6274          case BtOpReset:
6275             assign( t_new,
6276                     binop(Iop_And8, mkexpr(t_fetched), 
6277                                     unop(Iop_Not8, mkexpr(t_mask))) );
6278             break;
6279          default: 
6280             vpanic("dis_bt_G_E(x86)");
6281       }
6282       if (locked && !epartIsReg(modrm)) {
6283          casLE( mkexpr(t_addr1), mkexpr(t_fetched)/*expd*/,
6284                                  mkexpr(t_new)/*new*/,
6285                                  guest_EIP_curr_instr );
6286       } else {
6287          storeLE( mkexpr(t_addr1), mkexpr(t_new) );
6288       }
6289    }
6290  
6291    /* Side effect done; now get selected bit into Carry flag */
6292    /* Flags: C=selected bit, O,S,Z,A,P undefined, so are set to zero. */
6293    stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(X86G_CC_OP_COPY) ));
6294    stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0) ));
6295    stmt( IRStmt_Put( 
6296             OFFB_CC_DEP1,
6297             binop(Iop_And32,
6298                   binop(Iop_Shr32, 
6299                         unop(Iop_8Uto32, mkexpr(t_fetched)),
6300                         mkexpr(t_bitno2)),
6301                   mkU32(1)))
6302        );
6303    /* Set NDEP even though it isn't used.  This makes redundant-PUT
6304       elimination of previous stores to this field work better. */
6305    stmt( IRStmt_Put( OFFB_CC_NDEP, mkU32(0) ));
6306
6307    /* Move reg operand from stack back to reg */
6308    if (epartIsReg(modrm)) {
6309       /* t_esp still points at it. */
6310       putIReg(sz, eregOfRM(modrm), loadLE(szToITy(sz), mkexpr(t_esp)) );
6311       putIReg(4, R_ESP, binop(Iop_Add32, mkexpr(t_esp), mkU32(128)) );
6312    }
6313
6314    DIP("bt%s%c %s, %s\n",
6315        nameBtOp(op), nameISize(sz), nameIReg(sz, gregOfRM(modrm)), 
6316        ( epartIsReg(modrm) ? nameIReg(sz, eregOfRM(modrm)) : dis_buf ) );
6317  
6318    return delta;
6319 }
6320
6321
6322
6323 /* Handle BSF/BSR.  Only v-size seems necessary. */
6324 static
6325 UInt dis_bs_E_G ( UChar sorb, Int sz, Int delta, Bool fwds )
6326 {
6327    Bool   isReg;
6328    UChar  modrm;
6329    HChar  dis_buf[50];
6330    
6331    IRType ty  = szToITy(sz);
6332    IRTemp src = newTemp(ty);
6333    IRTemp dst = newTemp(ty);
6334
6335    IRTemp src32 = newTemp(Ity_I32);
6336    IRTemp dst32 = newTemp(Ity_I32);
6337    IRTemp src8  = newTemp(Ity_I8);
6338
6339    vassert(sz == 4 || sz == 2);
6340
6341    modrm = getIByte(delta);
6342
6343    isReg = epartIsReg(modrm);
6344    if (isReg) {
6345       delta++;
6346       assign( src, getIReg(sz, eregOfRM(modrm)) );
6347    } else {
6348       Int    len;
6349       IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
6350       delta += len;
6351       assign( src, loadLE(ty, mkexpr(addr)) );
6352    }
6353
6354    DIP("bs%c%c %s, %s\n",
6355        fwds ? 'f' : 'r', nameISize(sz), 
6356        ( isReg ? nameIReg(sz, eregOfRM(modrm)) : dis_buf ), 
6357        nameIReg(sz, gregOfRM(modrm)));
6358
6359    /* Generate an 8-bit expression which is zero iff the 
6360       original is zero, and nonzero otherwise */
6361    assign( src8,
6362            unop(Iop_1Uto8, binop(mkSizedOp(ty,Iop_CmpNE8),
6363                            mkexpr(src), mkU(ty,0))) );
6364
6365    /* Flags: Z is 1 iff source value is zero.  All others 
6366       are undefined -- we force them to zero. */
6367    stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(X86G_CC_OP_COPY) ));
6368    stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0) ));
6369    stmt( IRStmt_Put( 
6370             OFFB_CC_DEP1,
6371             IRExpr_Mux0X( mkexpr(src8),
6372                           /* src==0 */
6373                           mkU32(X86G_CC_MASK_Z),
6374                           /* src!=0 */
6375                           mkU32(0)
6376                         )
6377        ));
6378    /* Set NDEP even though it isn't used.  This makes redundant-PUT
6379       elimination of previous stores to this field work better. */
6380    stmt( IRStmt_Put( OFFB_CC_NDEP, mkU32(0) ));
6381
6382    /* Result: iff source value is zero, we can't use
6383       Iop_Clz32/Iop_Ctz32 as they have no defined result in that case.
6384       But anyway, Intel x86 semantics say the result is undefined in
6385       such situations.  Hence handle the zero case specially. */
6386
6387    /* Bleh.  What we compute:
6388
6389           bsf32:  if src == 0 then 0 else  Ctz32(src)
6390           bsr32:  if src == 0 then 0 else  31 - Clz32(src)
6391
6392           bsf16:  if src == 0 then 0 else  Ctz32(16Uto32(src))
6393           bsr16:  if src == 0 then 0 else  31 - Clz32(16Uto32(src))
6394
6395       First, widen src to 32 bits if it is not already.
6396
6397       Postscript 15 Oct 04: it seems that at least VIA Nehemiah leaves the
6398       dst register unchanged when src == 0.  Hence change accordingly.
6399    */
6400    if (sz == 2)
6401       assign( src32, unop(Iop_16Uto32, mkexpr(src)) );
6402    else
6403       assign( src32, mkexpr(src) );
6404
6405    /* The main computation, guarding against zero. */
6406    assign( dst32,   
6407            IRExpr_Mux0X( 
6408               mkexpr(src8),
6409               /* src == 0 -- leave dst unchanged */
6410               widenUto32( getIReg( sz, gregOfRM(modrm) ) ),
6411               /* src != 0 */
6412               fwds ? unop(Iop_Ctz32, mkexpr(src32))
6413                    : binop(Iop_Sub32, 
6414                            mkU32(31), 
6415                            unop(Iop_Clz32, mkexpr(src32)))
6416            )
6417          );
6418
6419    if (sz == 2)
6420       assign( dst, unop(Iop_32to16, mkexpr(dst32)) );
6421    else
6422       assign( dst, mkexpr(dst32) );
6423
6424    /* dump result back */
6425    putIReg( sz, gregOfRM(modrm), mkexpr(dst) );
6426
6427    return delta;
6428 }
6429
6430
6431 static 
6432 void codegen_xchg_eAX_Reg ( Int sz, Int reg )
6433 {
6434    IRType ty = szToITy(sz);
6435    IRTemp t1 = newTemp(ty);
6436    IRTemp t2 = newTemp(ty);
6437    vassert(sz == 2 || sz == 4);
6438    assign( t1, getIReg(sz, R_EAX) );
6439    assign( t2, getIReg(sz, reg) );
6440    putIReg( sz, R_EAX, mkexpr(t2) );
6441    putIReg( sz, reg, mkexpr(t1) );
6442    DIP("xchg%c %s, %s\n", 
6443        nameISize(sz), nameIReg(sz, R_EAX), nameIReg(sz, reg));
6444 }
6445
6446
6447 static 
6448 void codegen_SAHF ( void )
6449 {
6450    /* Set the flags to:
6451       (x86g_calculate_flags_all() & X86G_CC_MASK_O)  -- retain the old O flag
6452       | (%AH & (X86G_CC_MASK_S|X86G_CC_MASK_Z|X86G_CC_MASK_A
6453                 |X86G_CC_MASK_P|X86G_CC_MASK_C)
6454    */
6455    UInt   mask_SZACP = X86G_CC_MASK_S|X86G_CC_MASK_Z|X86G_CC_MASK_A
6456                        |X86G_CC_MASK_C|X86G_CC_MASK_P;
6457    IRTemp oldflags   = newTemp(Ity_I32);
6458    assign( oldflags, mk_x86g_calculate_eflags_all() );
6459    stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(X86G_CC_OP_COPY) ));
6460    stmt( IRStmt_Put( OFFB_CC_NDEP, mkU32(0) ));
6461    stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0) ));
6462    stmt( IRStmt_Put( OFFB_CC_DEP1,
6463          binop(Iop_Or32,
6464                binop(Iop_And32, mkexpr(oldflags), mkU32(X86G_CC_MASK_O)),
6465                binop(Iop_And32, 
6466                      binop(Iop_Shr32, getIReg(4, R_EAX), mkU8(8)),
6467                      mkU32(mask_SZACP))
6468               )
6469    ));
6470    /* Set NDEP even though it isn't used.  This makes redundant-PUT
6471       elimination of previous stores to this field work better. */
6472    stmt( IRStmt_Put( OFFB_CC_NDEP, mkU32(0) ));
6473 }
6474
6475
6476 static 
6477 void codegen_LAHF ( void  )
6478 {
6479    /* AH <- EFLAGS(SF:ZF:0:AF:0:PF:1:CF) */
6480    IRExpr* eax_with_hole;
6481    IRExpr* new_byte;
6482    IRExpr* new_eax;
6483    UInt    mask_SZACP = X86G_CC_MASK_S|X86G_CC_MASK_Z|X86G_CC_MASK_A
6484                         |X86G_CC_MASK_C|X86G_CC_MASK_P;
6485
6486    IRTemp  flags = newTemp(Ity_I32);
6487    assign( flags, mk_x86g_calculate_eflags_all() );
6488
6489    eax_with_hole 
6490       = binop(Iop_And32, getIReg(4, R_EAX), mkU32(0xFFFF00FF));
6491    new_byte 
6492       = binop(Iop_Or32, binop(Iop_And32, mkexpr(flags), mkU32(mask_SZACP)),
6493                         mkU32(1<<1));
6494    new_eax 
6495       = binop(Iop_Or32, eax_with_hole,
6496                         binop(Iop_Shl32, new_byte, mkU8(8)));
6497    putIReg(4, R_EAX, new_eax);
6498 }
6499
6500
6501 static
6502 UInt dis_cmpxchg_G_E ( UChar       sorb,
6503                        Bool        locked,
6504                        Int         size, 
6505                        Int         delta0 )
6506 {
6507    HChar dis_buf[50];
6508    Int   len;
6509
6510    IRType ty    = szToITy(size);
6511    IRTemp acc   = newTemp(ty);
6512    IRTemp src   = newTemp(ty);
6513    IRTemp dest  = newTemp(ty);
6514    IRTemp dest2 = newTemp(ty);
6515    IRTemp acc2  = newTemp(ty);
6516    IRTemp cond8 = newTemp(Ity_I8);
6517    IRTemp addr  = IRTemp_INVALID;
6518    UChar  rm    = getUChar(delta0);
6519
6520    /* There are 3 cases to consider:
6521
6522       reg-reg: ignore any lock prefix, generate sequence based
6523                on Mux0X
6524
6525       reg-mem, not locked: ignore any lock prefix, generate sequence
6526                            based on Mux0X
6527
6528       reg-mem, locked: use IRCAS
6529    */
6530    if (epartIsReg(rm)) {
6531       /* case 1 */
6532       assign( dest, getIReg(size, eregOfRM(rm)) );
6533       delta0++;
6534       assign( src, getIReg(size, gregOfRM(rm)) );
6535       assign( acc, getIReg(size, R_EAX) );
6536       setFlags_DEP1_DEP2(Iop_Sub8, acc, dest, ty);
6537       assign( cond8, unop(Iop_1Uto8, mk_x86g_calculate_condition(X86CondZ)) );
6538       assign( dest2, IRExpr_Mux0X(mkexpr(cond8), mkexpr(dest), mkexpr(src)) );
6539       assign( acc2,  IRExpr_Mux0X(mkexpr(cond8), mkexpr(dest), mkexpr(acc)) );
6540       putIReg(size, R_EAX, mkexpr(acc2));
6541       putIReg(size, eregOfRM(rm), mkexpr(dest2));
6542       DIP("cmpxchg%c %s,%s\n", nameISize(size),
6543                                nameIReg(size,gregOfRM(rm)),
6544                                nameIReg(size,eregOfRM(rm)) );
6545    } 
6546    else if (!epartIsReg(rm) && !locked) {
6547       /* case 2 */
6548       addr = disAMode ( &len, sorb, delta0, dis_buf );
6549       assign( dest, loadLE(ty, mkexpr(addr)) );
6550       delta0 += len;
6551       assign( src, getIReg(size, gregOfRM(rm)) );
6552       assign( acc, getIReg(size, R_EAX) );
6553       setFlags_DEP1_DEP2(Iop_Sub8, acc, dest, ty);
6554       assign( cond8, unop(Iop_1Uto8, mk_x86g_calculate_condition(X86CondZ)) );
6555       assign( dest2, IRExpr_Mux0X(mkexpr(cond8), mkexpr(dest), mkexpr(src)) );
6556       assign( acc2,  IRExpr_Mux0X(mkexpr(cond8), mkexpr(dest), mkexpr(acc)) );
6557       putIReg(size, R_EAX, mkexpr(acc2));
6558       storeLE( mkexpr(addr), mkexpr(dest2) );
6559       DIP("cmpxchg%c %s,%s\n", nameISize(size), 
6560                                nameIReg(size,gregOfRM(rm)), dis_buf);
6561    }
6562    else if (!epartIsReg(rm) && locked) {
6563       /* case 3 */
6564       /* src is new value.  acc is expected value.  dest is old value.
6565          Compute success from the output of the IRCAS, and steer the
6566          new value for EAX accordingly: in case of success, EAX is
6567          unchanged. */
6568       addr = disAMode ( &len, sorb, delta0, dis_buf );
6569       delta0 += len;
6570       assign( src, getIReg(size, gregOfRM(rm)) );
6571       assign( acc, getIReg(size, R_EAX) );
6572       stmt( IRStmt_CAS( 
6573          mkIRCAS( IRTemp_INVALID, dest, Iend_LE, mkexpr(addr), 
6574                   NULL, mkexpr(acc), NULL, mkexpr(src) )
6575       ));
6576       setFlags_DEP1_DEP2(Iop_Sub8, acc, dest, ty);
6577       assign( cond8, unop(Iop_1Uto8, mk_x86g_calculate_condition(X86CondZ)) );
6578       assign( acc2,  IRExpr_Mux0X(mkexpr(cond8), mkexpr(dest), mkexpr(acc)) );
6579       putIReg(size, R_EAX, mkexpr(acc2));
6580       DIP("cmpxchg%c %s,%s\n", nameISize(size), 
6581                                nameIReg(size,gregOfRM(rm)), dis_buf);
6582    }
6583    else vassert(0);
6584
6585    return delta0;
6586 }
6587
6588
6589 /* Handle conditional move instructions of the form
6590       cmovcc E(reg-or-mem), G(reg)
6591
6592    E(src) is reg-or-mem
6593    G(dst) is reg.
6594
6595    If E is reg, -->    GET %E, tmps
6596                        GET %G, tmpd
6597                        CMOVcc tmps, tmpd
6598                        PUT tmpd, %G
6599  
6600    If E is mem  -->    (getAddr E) -> tmpa
6601                        LD (tmpa), tmps
6602                        GET %G, tmpd
6603                        CMOVcc tmps, tmpd
6604                        PUT tmpd, %G
6605 */
6606 static
6607 UInt dis_cmov_E_G ( UChar       sorb,
6608                     Int         sz, 
6609                     X86Condcode cond,
6610                     Int         delta0 )
6611 {
6612    UChar rm  = getIByte(delta0);
6613    HChar dis_buf[50];
6614    Int   len;
6615
6616    IRType ty   = szToITy(sz);
6617    IRTemp tmps = newTemp(ty);
6618    IRTemp tmpd = newTemp(ty);
6619
6620    if (epartIsReg(rm)) {
6621       assign( tmps, getIReg(sz, eregOfRM(rm)) );
6622       assign( tmpd, getIReg(sz, gregOfRM(rm)) );
6623
6624       putIReg(sz, gregOfRM(rm),
6625                   IRExpr_Mux0X( unop(Iop_1Uto8,
6626                                      mk_x86g_calculate_condition(cond)),
6627                                 mkexpr(tmpd),
6628                                 mkexpr(tmps) )
6629              );
6630       DIP("cmov%c%s %s,%s\n", nameISize(sz), 
6631                               name_X86Condcode(cond),
6632                               nameIReg(sz,eregOfRM(rm)),
6633                               nameIReg(sz,gregOfRM(rm)));
6634       return 1+delta0;
6635    }
6636
6637    /* E refers to memory */    
6638    {
6639       IRTemp addr = disAMode ( &len, sorb, delta0, dis_buf );
6640       assign( tmps, loadLE(ty, mkexpr(addr)) );
6641       assign( tmpd, getIReg(sz, gregOfRM(rm)) );
6642
6643       putIReg(sz, gregOfRM(rm),
6644                   IRExpr_Mux0X( unop(Iop_1Uto8,
6645                                      mk_x86g_calculate_condition(cond)),
6646                                 mkexpr(tmpd),
6647                                 mkexpr(tmps) )
6648              );
6649
6650       DIP("cmov%c%s %s,%s\n", nameISize(sz), 
6651                               name_X86Condcode(cond),
6652                               dis_buf,
6653                               nameIReg(sz,gregOfRM(rm)));
6654       return len+delta0;
6655    }
6656 }
6657
6658
6659 static
6660 UInt dis_xadd_G_E ( UChar sorb, Bool locked, Int sz, Int delta0,
6661                     Bool* decodeOK )
6662 {
6663    Int   len;
6664    UChar rm = getIByte(delta0);
6665    HChar dis_buf[50];
6666
6667    IRType ty    = szToITy(sz);
6668    IRTemp tmpd  = newTemp(ty);
6669    IRTemp tmpt0 = newTemp(ty);
6670    IRTemp tmpt1 = newTemp(ty);
6671
6672    /* There are 3 cases to consider:
6673
6674       reg-reg: ignore any lock prefix,
6675                generate 'naive' (non-atomic) sequence
6676
6677       reg-mem, not locked: ignore any lock prefix, generate 'naive'
6678                            (non-atomic) sequence
6679
6680       reg-mem, locked: use IRCAS
6681    */
6682
6683    if (epartIsReg(rm)) {
6684       /* case 1 */
6685       assign( tmpd,  getIReg(sz, eregOfRM(rm)));
6686       assign( tmpt0, getIReg(sz, gregOfRM(rm)) );
6687       assign( tmpt1, binop(mkSizedOp(ty,Iop_Add8),
6688                            mkexpr(tmpd), mkexpr(tmpt0)) );
6689       setFlags_DEP1_DEP2( Iop_Add8, tmpd, tmpt0, ty );
6690       putIReg(sz, eregOfRM(rm), mkexpr(tmpt1));
6691       putIReg(sz, gregOfRM(rm), mkexpr(tmpd));
6692       DIP("xadd%c %s, %s\n",
6693           nameISize(sz), nameIReg(sz,gregOfRM(rm)), 
6694                                          nameIReg(sz,eregOfRM(rm)));
6695       *decodeOK = True;
6696       return 1+delta0;
6697    }
6698    else if (!epartIsReg(rm) && !locked) {
6699       /* case 2 */
6700       IRTemp addr = disAMode ( &len, sorb, delta0, dis_buf );
6701       assign( tmpd,  loadLE(ty, mkexpr(addr)) );
6702       assign( tmpt0, getIReg(sz, gregOfRM(rm)) );
6703       assign( tmpt1, binop(mkSizedOp(ty,Iop_Add8),
6704                            mkexpr(tmpd), mkexpr(tmpt0)) );
6705       storeLE( mkexpr(addr), mkexpr(tmpt1) );
6706       setFlags_DEP1_DEP2( Iop_Add8, tmpd, tmpt0, ty );
6707       putIReg(sz, gregOfRM(rm), mkexpr(tmpd));
6708       DIP("xadd%c %s, %s\n",
6709           nameISize(sz), nameIReg(sz,gregOfRM(rm)), dis_buf);
6710       *decodeOK = True;
6711       return len+delta0;
6712    }
6713    else if (!epartIsReg(rm) && locked) {
6714       /* case 3 */
6715       IRTemp addr = disAMode ( &len, sorb, delta0, dis_buf );
6716       assign( tmpd,  loadLE(ty, mkexpr(addr)) );
6717       assign( tmpt0, getIReg(sz, gregOfRM(rm)) );
6718       assign( tmpt1, binop(mkSizedOp(ty,Iop_Add8), 
6719                            mkexpr(tmpd), mkexpr(tmpt0)) );
6720       casLE( mkexpr(addr), mkexpr(tmpd)/*expVal*/,
6721                            mkexpr(tmpt1)/*newVal*/, guest_EIP_curr_instr );
6722       setFlags_DEP1_DEP2( Iop_Add8, tmpd, tmpt0, ty );
6723       putIReg(sz, gregOfRM(rm), mkexpr(tmpd));
6724       DIP("xadd%c %s, %s\n",
6725           nameISize(sz), nameIReg(sz,gregOfRM(rm)), dis_buf);
6726       *decodeOK = True;
6727       return len+delta0;
6728    }
6729    /*UNREACHED*/
6730    vassert(0);
6731 }
6732
6733 /* Move 16 bits from Ew (ireg or mem) to G (a segment register). */
6734
6735 static
6736 UInt dis_mov_Ew_Sw ( UChar sorb, Int delta0 )
6737 {
6738    Int    len;
6739    IRTemp addr;
6740    UChar  rm  = getIByte(delta0);
6741    HChar  dis_buf[50];
6742
6743    if (epartIsReg(rm)) {
6744       putSReg( gregOfRM(rm), getIReg(2, eregOfRM(rm)) );
6745       DIP("movw %s,%s\n", nameIReg(2,eregOfRM(rm)), nameSReg(gregOfRM(rm)));
6746       return 1+delta0;
6747    } else {
6748       addr = disAMode ( &len, sorb, delta0, dis_buf );
6749       putSReg( gregOfRM(rm), loadLE(Ity_I16, mkexpr(addr)) );
6750       DIP("movw %s,%s\n", dis_buf, nameSReg(gregOfRM(rm)));
6751       return len+delta0;
6752    }
6753 }
6754
6755 /* Move 16 bits from G (a segment register) to Ew (ireg or mem).  If
6756    dst is ireg and sz==4, zero out top half of it.  */
6757
6758 static
6759 UInt dis_mov_Sw_Ew ( UChar sorb,
6760                      Int   sz,
6761                      Int   delta0 )
6762 {
6763    Int    len;
6764    IRTemp addr;
6765    UChar  rm  = getIByte(delta0);
6766    HChar  dis_buf[50];
6767
6768    vassert(sz == 2 || sz == 4);
6769
6770    if (epartIsReg(rm)) {
6771       if (sz == 4)
6772          putIReg(4, eregOfRM(rm), unop(Iop_16Uto32, getSReg(gregOfRM(rm))));
6773       else
6774          putIReg(2, eregOfRM(rm), getSReg(gregOfRM(rm)));
6775
6776       DIP("mov %s,%s\n", nameSReg(gregOfRM(rm)), nameIReg(sz,eregOfRM(rm)));
6777       return 1+delta0;
6778    } else {
6779       addr = disAMode ( &len, sorb, delta0, dis_buf );
6780       storeLE( mkexpr(addr), getSReg(gregOfRM(rm)) );
6781       DIP("mov %s,%s\n", nameSReg(gregOfRM(rm)), dis_buf);
6782       return len+delta0;
6783    }
6784 }
6785
6786
6787 static 
6788 void dis_push_segreg ( UInt sreg, Int sz )
6789 {
6790     IRTemp t1 = newTemp(Ity_I16);
6791     IRTemp ta = newTemp(Ity_I32);
6792     vassert(sz == 2 || sz == 4);
6793
6794     assign( t1, getSReg(sreg) );
6795     assign( ta, binop(Iop_Sub32, getIReg(4, R_ESP), mkU32(sz)) );
6796     putIReg(4, R_ESP, mkexpr(ta));
6797     storeLE( mkexpr(ta), mkexpr(t1) );
6798
6799     DIP("push%c %s\n", sz==2 ? 'w' : 'l', nameSReg(sreg));
6800 }
6801
6802 static
6803 void dis_pop_segreg ( UInt sreg, Int sz )
6804 {
6805     IRTemp t1 = newTemp(Ity_I16);
6806     IRTemp ta = newTemp(Ity_I32);
6807     vassert(sz == 2 || sz == 4);
6808
6809     assign( ta, getIReg(4, R_ESP) );
6810     assign( t1, loadLE(Ity_I16, mkexpr(ta)) );
6811
6812     putIReg(4, R_ESP, binop(Iop_Add32, mkexpr(ta), mkU32(sz)) );
6813     putSReg( sreg, mkexpr(t1) );
6814     DIP("pop%c %s\n", sz==2 ? 'w' : 'l', nameSReg(sreg));
6815 }
6816
6817 static
6818 void dis_ret ( UInt d32 )
6819 {
6820    IRTemp t1 = newTemp(Ity_I32), t2 = newTemp(Ity_I32);
6821    assign(t1, getIReg(4,R_ESP));
6822    assign(t2, loadLE(Ity_I32,mkexpr(t1)));
6823    putIReg(4, R_ESP,binop(Iop_Add32, mkexpr(t1), mkU32(4+d32)));
6824    jmp_treg(Ijk_Ret,t2);
6825 }
6826
6827 /*------------------------------------------------------------*/
6828 /*--- SSE/SSE2/SSE3 helpers                                ---*/
6829 /*------------------------------------------------------------*/
6830
6831 /* Worker function; do not call directly. 
6832    Handles full width G = G `op` E   and   G = (not G) `op` E.
6833 */
6834
6835 static UInt dis_SSE_E_to_G_all_wrk ( 
6836                UChar sorb, Int delta, 
6837                HChar* opname, IROp op,
6838                Bool   invertG
6839             )
6840 {
6841    HChar   dis_buf[50];
6842    Int     alen;
6843    IRTemp  addr;
6844    UChar   rm = getIByte(delta);
6845    IRExpr* gpart
6846       = invertG ? unop(Iop_NotV128, getXMMReg(gregOfRM(rm)))
6847                 : getXMMReg(gregOfRM(rm));
6848    if (epartIsReg(rm)) {
6849       putXMMReg( gregOfRM(rm), 
6850                  binop(op, gpart,
6851                            getXMMReg(eregOfRM(rm))) );
6852       DIP("%s %s,%s\n", opname,
6853                         nameXMMReg(eregOfRM(rm)),
6854                         nameXMMReg(gregOfRM(rm)) );
6855       return delta+1;
6856    } else {
6857       addr = disAMode ( &alen, sorb, delta, dis_buf );
6858       putXMMReg( gregOfRM(rm), 
6859                  binop(op, gpart,
6860                            loadLE(Ity_V128, mkexpr(addr))) );
6861       DIP("%s %s,%s\n", opname,
6862                         dis_buf,
6863                         nameXMMReg(gregOfRM(rm)) );
6864       return delta+alen;
6865    }
6866 }
6867
6868
6869 /* All lanes SSE binary operation, G = G `op` E. */
6870
6871 static
6872 UInt dis_SSE_E_to_G_all ( UChar sorb, Int delta, HChar* opname, IROp op )
6873 {
6874    return dis_SSE_E_to_G_all_wrk( sorb, delta, opname, op, False );
6875 }
6876
6877 /* All lanes SSE binary operation, G = (not G) `op` E. */
6878
6879 static
6880 UInt dis_SSE_E_to_G_all_invG ( UChar sorb, Int delta, 
6881                                HChar* opname, IROp op )
6882 {
6883    return dis_SSE_E_to_G_all_wrk( sorb, delta, opname, op, True );
6884 }
6885
6886
6887 /* Lowest 32-bit lane only SSE binary operation, G = G `op` E. */
6888
6889 static UInt dis_SSE_E_to_G_lo32 ( UChar sorb, Int delta, 
6890                                   HChar* opname, IROp op )
6891 {
6892    HChar   dis_buf[50];
6893    Int     alen;
6894    IRTemp  addr;
6895    UChar   rm = getIByte(delta);
6896    IRExpr* gpart = getXMMReg(gregOfRM(rm));
6897    if (epartIsReg(rm)) {
6898       putXMMReg( gregOfRM(rm), 
6899                  binop(op, gpart,
6900                            getXMMReg(eregOfRM(rm))) );
6901       DIP("%s %s,%s\n", opname,
6902                         nameXMMReg(eregOfRM(rm)),
6903                         nameXMMReg(gregOfRM(rm)) );
6904       return delta+1;
6905    } else {
6906       /* We can only do a 32-bit memory read, so the upper 3/4 of the
6907          E operand needs to be made simply of zeroes. */
6908       IRTemp epart = newTemp(Ity_V128);
6909       addr = disAMode ( &alen, sorb, delta, dis_buf );
6910       assign( epart, unop( Iop_32UtoV128,
6911                            loadLE(Ity_I32, mkexpr(addr))) );
6912       putXMMReg( gregOfRM(rm), 
6913                  binop(op, gpart, mkexpr(epart)) );
6914       DIP("%s %s,%s\n", opname,
6915                         dis_buf,
6916                         nameXMMReg(gregOfRM(rm)) );
6917       return delta+alen;
6918    }
6919 }
6920
6921
6922 /* Lower 64-bit lane only SSE binary operation, G = G `op` E. */
6923
6924 static UInt dis_SSE_E_to_G_lo64 ( UChar sorb, Int delta, 
6925                                   HChar* opname, IROp op )
6926 {
6927    HChar   dis_buf[50];
6928    Int     alen;
6929    IRTemp  addr;
6930    UChar   rm = getIByte(delta);
6931    IRExpr* gpart = getXMMReg(gregOfRM(rm));
6932    if (epartIsReg(rm)) {
6933       putXMMReg( gregOfRM(rm), 
6934                  binop(op, gpart,
6935                            getXMMReg(eregOfRM(rm))) );
6936       DIP("%s %s,%s\n", opname,
6937                         nameXMMReg(eregOfRM(rm)),
6938                         nameXMMReg(gregOfRM(rm)) );
6939       return delta+1;
6940    } else {
6941       /* We can only do a 64-bit memory read, so the upper half of the
6942          E operand needs to be made simply of zeroes. */
6943       IRTemp epart = newTemp(Ity_V128);
6944       addr = disAMode ( &alen, sorb, delta, dis_buf );
6945       assign( epart, unop( Iop_64UtoV128,
6946                            loadLE(Ity_I64, mkexpr(addr))) );
6947       putXMMReg( gregOfRM(rm), 
6948                  binop(op, gpart, mkexpr(epart)) );
6949       DIP("%s %s,%s\n", opname,
6950                         dis_buf,
6951                         nameXMMReg(gregOfRM(rm)) );
6952       return delta+alen;
6953    }
6954 }
6955
6956
6957 /* All lanes unary SSE operation, G = op(E). */
6958
6959 static UInt dis_SSE_E_to_G_unary_all ( 
6960                UChar sorb, Int delta, 
6961                HChar* opname, IROp op
6962             )
6963 {
6964    HChar   dis_buf[50];
6965    Int     alen;
6966    IRTemp  addr;
6967    UChar   rm = getIByte(delta);
6968    if (epartIsReg(rm)) {
6969       putXMMReg( gregOfRM(rm), 
6970                  unop(op, getXMMReg(eregOfRM(rm))) );
6971       DIP("%s %s,%s\n", opname,
6972                         nameXMMReg(eregOfRM(rm)),
6973                         nameXMMReg(gregOfRM(rm)) );
6974       return delta+1;
6975    } else {
6976       addr = disAMode ( &alen, sorb, delta, dis_buf );
6977       putXMMReg( gregOfRM(rm), 
6978                  unop(op, loadLE(Ity_V128, mkexpr(addr))) );
6979       DIP("%s %s,%s\n", opname,
6980                         dis_buf,
6981                         nameXMMReg(gregOfRM(rm)) );
6982       return delta+alen;
6983    }
6984 }
6985
6986
6987 /* Lowest 32-bit lane only unary SSE operation, G = op(E). */
6988
6989 static UInt dis_SSE_E_to_G_unary_lo32 ( 
6990                UChar sorb, Int delta, 
6991                HChar* opname, IROp op
6992             )
6993 {
6994    /* First we need to get the old G value and patch the low 32 bits
6995       of the E operand into it.  Then apply op and write back to G. */
6996    HChar   dis_buf[50];
6997    Int     alen;
6998    IRTemp  addr;
6999    UChar   rm = getIByte(delta);
7000    IRTemp  oldG0 = newTemp(Ity_V128);
7001    IRTemp  oldG1 = newTemp(Ity_V128);
7002
7003    assign( oldG0, getXMMReg(gregOfRM(rm)) );
7004
7005    if (epartIsReg(rm)) {
7006       assign( oldG1, 
7007               binop( Iop_SetV128lo32,
7008                      mkexpr(oldG0),
7009                      getXMMRegLane32(eregOfRM(rm), 0)) );
7010       putXMMReg( gregOfRM(rm), unop(op, mkexpr(oldG1)) );
7011       DIP("%s %s,%s\n", opname,
7012                         nameXMMReg(eregOfRM(rm)),
7013                         nameXMMReg(gregOfRM(rm)) );
7014       return delta+1;
7015    } else {
7016       addr = disAMode ( &alen, sorb, delta, dis_buf );
7017       assign( oldG1, 
7018               binop( Iop_SetV128lo32,
7019                      mkexpr(oldG0),
7020                      loadLE(Ity_I32, mkexpr(addr)) ));
7021       putXMMReg( gregOfRM(rm), unop(op, mkexpr(oldG1)) );
7022       DIP("%s %s,%s\n", opname,
7023                         dis_buf,
7024                         nameXMMReg(gregOfRM(rm)) );
7025       return delta+alen;
7026    }
7027 }
7028
7029
7030 /* Lowest 64-bit lane only unary SSE operation, G = op(E). */
7031
7032 static UInt dis_SSE_E_to_G_unary_lo64 ( 
7033                UChar sorb, Int delta, 
7034                HChar* opname, IROp op
7035             )
7036 {
7037    /* First we need to get the old G value and patch the low 64 bits
7038       of the E operand into it.  Then apply op and write back to G. */
7039    HChar   dis_buf[50];
7040    Int     alen;
7041    IRTemp  addr;
7042    UChar   rm = getIByte(delta);
7043    IRTemp  oldG0 = newTemp(Ity_V128);
7044    IRTemp  oldG1 = newTemp(Ity_V128);
7045
7046    assign( oldG0, getXMMReg(gregOfRM(rm)) );
7047
7048    if (epartIsReg(rm)) {
7049       assign( oldG1, 
7050               binop( Iop_SetV128lo64,
7051                      mkexpr(oldG0),
7052                      getXMMRegLane64(eregOfRM(rm), 0)) );
7053       putXMMReg( gregOfRM(rm), unop(op, mkexpr(oldG1)) );
7054       DIP("%s %s,%s\n", opname,
7055                         nameXMMReg(eregOfRM(rm)),
7056                         nameXMMReg(gregOfRM(rm)) );
7057       return delta+1;
7058    } else {
7059       addr = disAMode ( &alen, sorb, delta, dis_buf );
7060       assign( oldG1, 
7061               binop( Iop_SetV128lo64,
7062                      mkexpr(oldG0),
7063                      loadLE(Ity_I64, mkexpr(addr)) ));
7064       putXMMReg( gregOfRM(rm), unop(op, mkexpr(oldG1)) );
7065       DIP("%s %s,%s\n", opname,
7066                         dis_buf,
7067                         nameXMMReg(gregOfRM(rm)) );
7068       return delta+alen;
7069    }
7070 }
7071
7072
7073 /* SSE integer binary operation:
7074       G = G `op` E   (eLeft == False)
7075       G = E `op` G   (eLeft == True)
7076 */
7077 static UInt dis_SSEint_E_to_G( 
7078                UChar sorb, Int delta, 
7079                HChar* opname, IROp op,
7080                Bool   eLeft
7081             )
7082 {
7083    HChar   dis_buf[50];
7084    Int     alen;
7085    IRTemp  addr;
7086    UChar   rm = getIByte(delta);
7087    IRExpr* gpart = getXMMReg(gregOfRM(rm));
7088    IRExpr* epart = NULL;
7089    if (epartIsReg(rm)) {
7090       epart = getXMMReg(eregOfRM(rm));
7091       DIP("%s %s,%s\n", opname,
7092                         nameXMMReg(eregOfRM(rm)),
7093                         nameXMMReg(gregOfRM(rm)) );
7094       delta += 1;
7095    } else {
7096       addr  = disAMode ( &alen, sorb, delta, dis_buf );
7097       epart = loadLE(Ity_V128, mkexpr(addr));
7098       DIP("%s %s,%s\n", opname,
7099                         dis_buf,
7100                         nameXMMReg(gregOfRM(rm)) );
7101       delta += alen;
7102    }
7103    putXMMReg( gregOfRM(rm), 
7104               eLeft ? binop(op, epart, gpart)
7105                     : binop(op, gpart, epart) );
7106    return delta;
7107 }
7108
7109
7110 /* Helper for doing SSE FP comparisons. */
7111
7112 static void findSSECmpOp ( Bool* needNot, IROp* op, 
7113                            Int imm8, Bool all_lanes, Int sz )
7114 {
7115    imm8 &= 7;
7116    *needNot = False;
7117    *op      = Iop_INVALID;
7118    if (imm8 >= 4) {
7119       *needNot = True;
7120       imm8 -= 4;
7121    }
7122
7123    if (sz == 4 && all_lanes) {
7124       switch (imm8) {
7125          case 0: *op = Iop_CmpEQ32Fx4; return;
7126          case 1: *op = Iop_CmpLT32Fx4; return;
7127          case 2: *op = Iop_CmpLE32Fx4; return;
7128          case 3: *op = Iop_CmpUN32Fx4; return;
7129          default: break;
7130       }
7131    }
7132    if (sz == 4 && !all_lanes) {
7133       switch (imm8) {
7134          case 0: *op = Iop_CmpEQ32F0x4; return;
7135          case 1: *op = Iop_CmpLT32F0x4; return;
7136          case 2: *op = Iop_CmpLE32F0x4; return;
7137          case 3: *op = Iop_CmpUN32F0x4; return;
7138          default: break;
7139       }
7140    }
7141    if (sz == 8 && all_lanes) {
7142       switch (imm8) {
7143          case 0: *op = Iop_CmpEQ64Fx2; return;
7144          case 1: *op = Iop_CmpLT64Fx2; return;
7145          case 2: *op = Iop_CmpLE64Fx2; return;
7146          case 3: *op = Iop_CmpUN64Fx2; return;
7147          default: break;
7148       }
7149    }
7150    if (sz == 8 && !all_lanes) {
7151       switch (imm8) {
7152          case 0: *op = Iop_CmpEQ64F0x2; return;
7153          case 1: *op = Iop_CmpLT64F0x2; return;
7154          case 2: *op = Iop_CmpLE64F0x2; return;
7155          case 3: *op = Iop_CmpUN64F0x2; return;
7156          default: break;
7157       }
7158    }
7159    vpanic("findSSECmpOp(x86,guest)");
7160 }
7161
7162 /* Handles SSE 32F/64F comparisons. */
7163
7164 static UInt dis_SSEcmp_E_to_G ( UChar sorb, Int delta, 
7165                                 HChar* opname, Bool all_lanes, Int sz )
7166 {
7167    HChar   dis_buf[50];
7168    Int     alen, imm8;
7169    IRTemp  addr;
7170    Bool    needNot = False;
7171    IROp    op      = Iop_INVALID;
7172    IRTemp  plain   = newTemp(Ity_V128);
7173    UChar   rm      = getIByte(delta);
7174    UShort  mask    = 0;
7175    vassert(sz == 4 || sz == 8);
7176    if (epartIsReg(rm)) {
7177       imm8 = getIByte(delta+1);
7178       findSSECmpOp(&needNot, &op, imm8, all_lanes, sz);
7179       assign( plain, binop(op, getXMMReg(gregOfRM(rm)), 
7180                                getXMMReg(eregOfRM(rm))) );
7181       delta += 2;
7182       DIP("%s $%d,%s,%s\n", opname,
7183                             (Int)imm8,
7184                             nameXMMReg(eregOfRM(rm)),
7185                             nameXMMReg(gregOfRM(rm)) );
7186    } else {
7187       addr = disAMode ( &alen, sorb, delta, dis_buf );
7188       imm8 = getIByte(delta+alen);
7189       findSSECmpOp(&needNot, &op, imm8, all_lanes, sz);
7190       assign( plain, 
7191               binop(
7192                  op,
7193                  getXMMReg(gregOfRM(rm)), 
7194                    all_lanes  ? loadLE(Ity_V128, mkexpr(addr))
7195                  : sz == 8    ? unop( Iop_64UtoV128, loadLE(Ity_I64, mkexpr(addr)))
7196                  : /*sz==4*/    unop( Iop_32UtoV128, loadLE(Ity_I32, mkexpr(addr)))
7197              ) 
7198       );
7199       delta += alen+1;
7200       DIP("%s $%d,%s,%s\n", opname,
7201                             (Int)imm8,
7202                             dis_buf,
7203                             nameXMMReg(gregOfRM(rm)) );
7204    }
7205
7206    if (needNot && all_lanes) {
7207       putXMMReg( gregOfRM(rm), 
7208                  unop(Iop_NotV128, mkexpr(plain)) );
7209    }
7210    else
7211    if (needNot && !all_lanes) {
7212       mask = toUShort( sz==4 ? 0x000F : 0x00FF );
7213       putXMMReg( gregOfRM(rm), 
7214                  binop(Iop_XorV128, mkexpr(plain), mkV128(mask)) );
7215    }
7216    else {
7217       putXMMReg( gregOfRM(rm), mkexpr(plain) );
7218    }
7219
7220    return delta;
7221 }
7222
7223
7224 /* Vector by scalar shift of G by the amount specified at the bottom
7225    of E. */
7226
7227 static UInt dis_SSE_shiftG_byE ( UChar sorb, Int delta, 
7228                                  HChar* opname, IROp op )
7229 {
7230    HChar   dis_buf[50];
7231    Int     alen, size;
7232    IRTemp  addr;
7233    Bool    shl, shr, sar;
7234    UChar   rm   = getIByte(delta);
7235    IRTemp  g0   = newTemp(Ity_V128);
7236    IRTemp  g1   = newTemp(Ity_V128);
7237    IRTemp  amt  = newTemp(Ity_I32);
7238    IRTemp  amt8 = newTemp(Ity_I8);
7239    if (epartIsReg(rm)) {
7240       assign( amt, getXMMRegLane32(eregOfRM(rm), 0) );
7241       DIP("%s %s,%s\n", opname,
7242                         nameXMMReg(eregOfRM(rm)),
7243                         nameXMMReg(gregOfRM(rm)) );
7244       delta++;
7245    } else {
7246       addr = disAMode ( &alen, sorb, delta, dis_buf );
7247       assign( amt, loadLE(Ity_I32, mkexpr(addr)) );
7248       DIP("%s %s,%s\n", opname,
7249                         dis_buf,
7250                         nameXMMReg(gregOfRM(rm)) );
7251       delta += alen;
7252    }
7253    assign( g0,   getXMMReg(gregOfRM(rm)) );
7254    assign( amt8, unop(Iop_32to8, mkexpr(amt)) );
7255
7256    shl = shr = sar = False;
7257    size = 0;
7258    switch (op) {
7259       case Iop_ShlN16x8: shl = True; size = 32; break;
7260       case Iop_ShlN32x4: shl = True; size = 32; break;
7261       case Iop_ShlN64x2: shl = True; size = 64; break;
7262       case Iop_SarN16x8: sar = True; size = 16; break;
7263       case Iop_SarN32x4: sar = True; size = 32; break;
7264       case Iop_ShrN16x8: shr = True; size = 16; break;
7265       case Iop_ShrN32x4: shr = True; size = 32; break;
7266       case Iop_ShrN64x2: shr = True; size = 64; break;
7267       default: vassert(0);
7268    }
7269
7270    if (shl || shr) {
7271      assign( 
7272         g1,
7273         IRExpr_Mux0X(
7274            unop(Iop_1Uto8,binop(Iop_CmpLT32U,mkexpr(amt),mkU32(size))),
7275            mkV128(0x0000),
7276            binop(op, mkexpr(g0), mkexpr(amt8))
7277         )
7278      );
7279    } else 
7280    if (sar) {
7281      assign( 
7282         g1,
7283         IRExpr_Mux0X(
7284            unop(Iop_1Uto8,binop(Iop_CmpLT32U,mkexpr(amt),mkU32(size))),
7285            binop(op, mkexpr(g0), mkU8(size-1)),
7286            binop(op, mkexpr(g0), mkexpr(amt8))
7287         )
7288      );
7289    } else {
7290       /*NOTREACHED*/
7291       vassert(0);
7292    }
7293
7294    putXMMReg( gregOfRM(rm), mkexpr(g1) );
7295    return delta;
7296 }
7297
7298
7299 /* Vector by scalar shift of E by an immediate byte. */
7300
7301 static 
7302 UInt dis_SSE_shiftE_imm ( Int delta, HChar* opname, IROp op )
7303 {
7304    Bool    shl, shr, sar;
7305    UChar   rm   = getIByte(delta);
7306    IRTemp  e0   = newTemp(Ity_V128);
7307    IRTemp  e1   = newTemp(Ity_V128);
7308    UChar   amt, size;
7309    vassert(epartIsReg(rm));
7310    vassert(gregOfRM(rm) == 2 
7311            || gregOfRM(rm) == 4 || gregOfRM(rm) == 6);
7312    amt = getIByte(delta+1);
7313    delta += 2;
7314    DIP("%s $%d,%s\n", opname,
7315                       (Int)amt,
7316                       nameXMMReg(eregOfRM(rm)) );
7317    assign( e0, getXMMReg(eregOfRM(rm)) );
7318
7319    shl = shr = sar = False;
7320    size = 0;
7321    switch (op) {
7322       case Iop_ShlN16x8: shl = True; size = 16; break;
7323       case Iop_ShlN32x4: shl = True; size = 32; break;
7324       case Iop_ShlN64x2: shl = True; size = 64; break;
7325       case Iop_SarN16x8: sar = True; size = 16; break;
7326       case Iop_SarN32x4: sar = True; size = 32; break;
7327       case Iop_ShrN16x8: shr = True; size = 16; break;
7328       case Iop_ShrN32x4: shr = True; size = 32; break;
7329       case Iop_ShrN64x2: shr = True; size = 64; break;
7330       default: vassert(0);
7331    }
7332
7333    if (shl || shr) {
7334       assign( e1, amt >= size 
7335                      ? mkV128(0x0000)
7336                      : binop(op, mkexpr(e0), mkU8(amt))
7337       );
7338    } else 
7339    if (sar) {
7340       assign( e1, amt >= size 
7341                      ? binop(op, mkexpr(e0), mkU8(size-1))
7342                      : binop(op, mkexpr(e0), mkU8(amt))
7343       );
7344    } else {
7345       /*NOTREACHED*/
7346       vassert(0);
7347    }
7348
7349    putXMMReg( eregOfRM(rm), mkexpr(e1) );
7350    return delta;
7351 }
7352
7353
7354 /* Get the current SSE rounding mode. */
7355
7356 static IRExpr* /* :: Ity_I32 */ get_sse_roundingmode ( void )
7357 {
7358    return binop( Iop_And32, 
7359                  IRExpr_Get( OFFB_SSEROUND, Ity_I32 ), 
7360                  mkU32(3) );
7361 }
7362
7363 static void put_sse_roundingmode ( IRExpr* sseround )
7364 {
7365    vassert(typeOfIRExpr(irsb->tyenv, sseround) == Ity_I32);
7366    stmt( IRStmt_Put( OFFB_SSEROUND, sseround ) );
7367 }
7368
7369 /* Break a 128-bit value up into four 32-bit ints. */
7370
7371 static void breakup128to32s ( IRTemp t128,
7372                               /*OUTs*/
7373                               IRTemp* t3, IRTemp* t2,
7374                               IRTemp* t1, IRTemp* t0 )
7375 {
7376    IRTemp hi64 = newTemp(Ity_I64);
7377    IRTemp lo64 = newTemp(Ity_I64);
7378    assign( hi64, unop(Iop_V128HIto64, mkexpr(t128)) );
7379    assign( lo64, unop(Iop_V128to64,   mkexpr(t128)) );
7380
7381    vassert(t0 && *t0 == IRTemp_INVALID);
7382    vassert(t1 && *t1 == IRTemp_INVALID);
7383    vassert(t2 && *t2 == IRTemp_INVALID);
7384    vassert(t3 && *t3 == IRTemp_INVALID);
7385
7386    *t0 = newTemp(Ity_I32);
7387    *t1 = newTemp(Ity_I32);
7388    *t2 = newTemp(Ity_I32);
7389    *t3 = newTemp(Ity_I32);
7390    assign( *t0, unop(Iop_64to32,   mkexpr(lo64)) );
7391    assign( *t1, unop(Iop_64HIto32, mkexpr(lo64)) );
7392    assign( *t2, unop(Iop_64to32,   mkexpr(hi64)) );
7393    assign( *t3, unop(Iop_64HIto32, mkexpr(hi64)) );
7394 }
7395
7396 /* Construct a 128-bit value from four 32-bit ints. */
7397
7398 static IRExpr* mk128from32s ( IRTemp t3, IRTemp t2,
7399                               IRTemp t1, IRTemp t0 )
7400 {
7401    return
7402       binop( Iop_64HLtoV128,
7403              binop(Iop_32HLto64, mkexpr(t3), mkexpr(t2)),
7404              binop(Iop_32HLto64, mkexpr(t1), mkexpr(t0))
7405    );
7406 }
7407
7408 /* Break a 64-bit value up into four 16-bit ints. */
7409
7410 static void breakup64to16s ( IRTemp t64,
7411                              /*OUTs*/
7412                              IRTemp* t3, IRTemp* t2,
7413                              IRTemp* t1, IRTemp* t0 )
7414 {
7415    IRTemp hi32 = newTemp(Ity_I32);
7416    IRTemp lo32 = newTemp(Ity_I32);
7417    assign( hi32, unop(Iop_64HIto32, mkexpr(t64)) );
7418    assign( lo32, unop(Iop_64to32,   mkexpr(t64)) );
7419
7420    vassert(t0 && *t0 == IRTemp_INVALID);
7421    vassert(t1 && *t1 == IRTemp_INVALID);
7422    vassert(t2 && *t2 == IRTemp_INVALID);
7423    vassert(t3 && *t3 == IRTemp_INVALID);
7424
7425    *t0 = newTemp(Ity_I16);
7426    *t1 = newTemp(Ity_I16);
7427    *t2 = newTemp(Ity_I16);
7428    *t3 = newTemp(Ity_I16);
7429    assign( *t0, unop(Iop_32to16,   mkexpr(lo32)) );
7430    assign( *t1, unop(Iop_32HIto16, mkexpr(lo32)) );
7431    assign( *t2, unop(Iop_32to16,   mkexpr(hi32)) );
7432    assign( *t3, unop(Iop_32HIto16, mkexpr(hi32)) );
7433 }
7434
7435 /* Construct a 64-bit value from four 16-bit ints. */
7436
7437 static IRExpr* mk64from16s ( IRTemp t3, IRTemp t2,
7438                              IRTemp t1, IRTemp t0 )
7439 {
7440    return
7441       binop( Iop_32HLto64,
7442              binop(Iop_16HLto32, mkexpr(t3), mkexpr(t2)),
7443              binop(Iop_16HLto32, mkexpr(t1), mkexpr(t0))
7444    );
7445 }
7446
7447 /* Generate IR to set the guest %EFLAGS from the pushfl-format image
7448    in the given 32-bit temporary.  The flags that are set are: O S Z A
7449    C P D ID AC.
7450
7451    In all cases, code to set AC is generated.  However, VEX actually
7452    ignores the AC value and so can optionally emit an emulation
7453    warning when it is enabled.  In this routine, an emulation warning
7454    is only emitted if emit_AC_emwarn is True, in which case
7455    next_insn_EIP must be correct (this allows for correct code
7456    generation for popfl/popfw).  If emit_AC_emwarn is False,
7457    next_insn_EIP is unimportant (this allows for easy if kludgey code
7458    generation for IRET.) */
7459
7460 static 
7461 void set_EFLAGS_from_value ( IRTemp t1, 
7462                              Bool   emit_AC_emwarn,
7463                              Addr32 next_insn_EIP )
7464 {
7465    vassert(typeOfIRTemp(irsb->tyenv,t1) == Ity_I32);
7466
7467    /* t1 is the flag word.  Mask out everything except OSZACP and set
7468       the flags thunk to X86G_CC_OP_COPY. */
7469    stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(X86G_CC_OP_COPY) ));
7470    stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0) ));
7471    stmt( IRStmt_Put( OFFB_CC_DEP1, 
7472                      binop(Iop_And32,
7473                            mkexpr(t1), 
7474                            mkU32( X86G_CC_MASK_C | X86G_CC_MASK_P 
7475                                   | X86G_CC_MASK_A | X86G_CC_MASK_Z 
7476                                   | X86G_CC_MASK_S| X86G_CC_MASK_O )
7477                           )
7478                     )
7479        );
7480    /* Set NDEP even though it isn't used.  This makes redundant-PUT
7481       elimination of previous stores to this field work better. */
7482    stmt( IRStmt_Put( OFFB_CC_NDEP, mkU32(0) ));
7483
7484    /* Also need to set the D flag, which is held in bit 10 of t1.
7485       If zero, put 1 in OFFB_DFLAG, else -1 in OFFB_DFLAG. */
7486    stmt( IRStmt_Put( 
7487             OFFB_DFLAG,
7488             IRExpr_Mux0X( 
7489                unop(Iop_32to8,
7490                     binop(Iop_And32, 
7491                           binop(Iop_Shr32, mkexpr(t1), mkU8(10)), 
7492                           mkU32(1))),
7493                mkU32(1), 
7494                mkU32(0xFFFFFFFF))) 
7495        );
7496
7497    /* Set the ID flag */
7498    stmt( IRStmt_Put( 
7499             OFFB_IDFLAG,
7500             IRExpr_Mux0X( 
7501                unop(Iop_32to8,
7502                     binop(Iop_And32, 
7503                           binop(Iop_Shr32, mkexpr(t1), mkU8(21)), 
7504                           mkU32(1))),
7505                mkU32(0), 
7506                mkU32(1))) 
7507        );
7508
7509    /* And set the AC flag.  If setting it 1 to, possibly emit an
7510       emulation warning. */
7511    stmt( IRStmt_Put( 
7512             OFFB_ACFLAG,
7513             IRExpr_Mux0X( 
7514                unop(Iop_32to8,
7515                     binop(Iop_And32, 
7516                           binop(Iop_Shr32, mkexpr(t1), mkU8(18)), 
7517                           mkU32(1))),
7518                mkU32(0), 
7519                mkU32(1))) 
7520        );
7521
7522    if (emit_AC_emwarn) {
7523       put_emwarn( mkU32(EmWarn_X86_acFlag) );
7524       stmt( 
7525          IRStmt_Exit(
7526             binop( Iop_CmpNE32, 
7527                    binop(Iop_And32, mkexpr(t1), mkU32(1<<18)), 
7528                    mkU32(0) ),
7529             Ijk_EmWarn,
7530             IRConst_U32( next_insn_EIP )
7531          )
7532       );
7533    }
7534 }
7535
7536
7537 /* Helper for the SSSE3 (not SSE3) PMULHRSW insns.  Given two 64-bit
7538    values (aa,bb), computes, for each of the 4 16-bit lanes:
7539
7540    (((aa_lane *s32 bb_lane) >>u 14) + 1) >>u 1
7541 */
7542 static IRExpr* dis_PMULHRSW_helper ( IRExpr* aax, IRExpr* bbx )
7543 {
7544    IRTemp aa      = newTemp(Ity_I64);
7545    IRTemp bb      = newTemp(Ity_I64);
7546    IRTemp aahi32s = newTemp(Ity_I64);
7547    IRTemp aalo32s = newTemp(Ity_I64);
7548    IRTemp bbhi32s = newTemp(Ity_I64);
7549    IRTemp bblo32s = newTemp(Ity_I64);
7550    IRTemp rHi     = newTemp(Ity_I64);
7551    IRTemp rLo     = newTemp(Ity_I64);
7552    IRTemp one32x2 = newTemp(Ity_I64);
7553    assign(aa, aax);
7554    assign(bb, bbx);
7555    assign( aahi32s,
7556            binop(Iop_SarN32x2,
7557                  binop(Iop_InterleaveHI16x4, mkexpr(aa), mkexpr(aa)),
7558                  mkU8(16) ));
7559    assign( aalo32s,
7560            binop(Iop_SarN32x2,
7561                  binop(Iop_InterleaveLO16x4, mkexpr(aa), mkexpr(aa)),
7562                  mkU8(16) ));
7563    assign( bbhi32s,
7564            binop(Iop_SarN32x2,
7565                  binop(Iop_InterleaveHI16x4, mkexpr(bb), mkexpr(bb)),
7566                  mkU8(16) ));
7567    assign( bblo32s,
7568            binop(Iop_SarN32x2,
7569                  binop(Iop_InterleaveLO16x4, mkexpr(bb), mkexpr(bb)),
7570                  mkU8(16) ));
7571    assign(one32x2, mkU64( (1ULL << 32) + 1 ));
7572    assign(
7573       rHi,
7574       binop(
7575          Iop_ShrN32x2,
7576          binop(
7577             Iop_Add32x2, 
7578             binop(
7579                Iop_ShrN32x2,
7580                binop(Iop_Mul32x2, mkexpr(aahi32s), mkexpr(bbhi32s)),
7581                mkU8(14)
7582             ),
7583             mkexpr(one32x2)
7584          ),
7585          mkU8(1)
7586       )
7587    );
7588    assign(
7589       rLo,
7590       binop(
7591          Iop_ShrN32x2,
7592          binop(
7593             Iop_Add32x2, 
7594             binop(
7595                Iop_ShrN32x2,
7596                binop(Iop_Mul32x2, mkexpr(aalo32s), mkexpr(bblo32s)),
7597                mkU8(14)
7598             ),
7599             mkexpr(one32x2)
7600          ),
7601          mkU8(1)
7602       )
7603    );
7604    return
7605       binop(Iop_CatEvenLanes16x4, mkexpr(rHi), mkexpr(rLo));
7606 }
7607
7608 /* Helper for the SSSE3 (not SSE3) PSIGN{B,W,D} insns.  Given two 64-bit
7609    values (aa,bb), computes, for each lane:
7610
7611           if aa_lane < 0 then - bb_lane
7612      else if aa_lane > 0 then bb_lane
7613      else 0
7614 */
7615 static IRExpr* dis_PSIGN_helper ( IRExpr* aax, IRExpr* bbx, Int laneszB )
7616 {
7617    IRTemp aa       = newTemp(Ity_I64);
7618    IRTemp bb       = newTemp(Ity_I64);
7619    IRTemp zero     = newTemp(Ity_I64);
7620    IRTemp bbNeg    = newTemp(Ity_I64);
7621    IRTemp negMask  = newTemp(Ity_I64);
7622    IRTemp posMask  = newTemp(Ity_I64);
7623    IROp   opSub    = Iop_INVALID;
7624    IROp   opCmpGTS = Iop_INVALID;
7625
7626    switch (laneszB) {
7627       case 1: opSub = Iop_Sub8x8;  opCmpGTS = Iop_CmpGT8Sx8;  break;
7628       case 2: opSub = Iop_Sub16x4; opCmpGTS = Iop_CmpGT16Sx4; break;
7629       case 4: opSub = Iop_Sub32x2; opCmpGTS = Iop_CmpGT32Sx2; break;
7630       default: vassert(0);
7631    }
7632
7633    assign( aa,      aax );
7634    assign( bb,      bbx );
7635    assign( zero,    mkU64(0) );
7636    assign( bbNeg,   binop(opSub,    mkexpr(zero), mkexpr(bb)) );
7637    assign( negMask, binop(opCmpGTS, mkexpr(zero), mkexpr(aa)) );
7638    assign( posMask, binop(opCmpGTS, mkexpr(aa),   mkexpr(zero)) );
7639
7640    return
7641       binop(Iop_Or64,
7642             binop(Iop_And64, mkexpr(bb),    mkexpr(posMask)),
7643             binop(Iop_And64, mkexpr(bbNeg), mkexpr(negMask)) );
7644
7645 }
7646
7647 /* Helper for the SSSE3 (not SSE3) PABS{B,W,D} insns.  Given a 64-bit
7648    value aa, computes, for each lane
7649
7650    if aa < 0 then -aa else aa
7651
7652    Note that the result is interpreted as unsigned, so that the
7653    absolute value of the most negative signed input can be
7654    represented.
7655 */
7656 static IRExpr* dis_PABS_helper ( IRExpr* aax, Int laneszB )
7657 {
7658    IRTemp aa      = newTemp(Ity_I64);
7659    IRTemp zero    = newTemp(Ity_I64);
7660    IRTemp aaNeg   = newTemp(Ity_I64);
7661    IRTemp negMask = newTemp(Ity_I64);
7662    IRTemp posMask = newTemp(Ity_I64);
7663    IROp   opSub   = Iop_INVALID;
7664    IROp   opSarN  = Iop_INVALID;
7665
7666    switch (laneszB) {
7667       case 1: opSub = Iop_Sub8x8;  opSarN = Iop_SarN8x8;  break;
7668       case 2: opSub = Iop_Sub16x4; opSarN = Iop_SarN16x4; break;
7669       case 4: opSub = Iop_Sub32x2; opSarN = Iop_SarN32x2; break;
7670       default: vassert(0);
7671    }
7672
7673    assign( aa,      aax );
7674    assign( negMask, binop(opSarN, mkexpr(aa), mkU8(8*laneszB-1)) );
7675    assign( posMask, unop(Iop_Not64, mkexpr(negMask)) );
7676    assign( zero,    mkU64(0) );
7677    assign( aaNeg,   binop(opSub, mkexpr(zero), mkexpr(aa)) );
7678    return
7679       binop(Iop_Or64,
7680             binop(Iop_And64, mkexpr(aa),    mkexpr(posMask)),
7681             binop(Iop_And64, mkexpr(aaNeg), mkexpr(negMask)) );
7682 }
7683
7684 static IRExpr* dis_PALIGNR_XMM_helper ( IRTemp hi64,
7685                                         IRTemp lo64, Int byteShift )
7686 {
7687    vassert(byteShift >= 1 && byteShift <= 7);
7688    return
7689       binop(Iop_Or64,
7690             binop(Iop_Shl64, mkexpr(hi64), mkU8(8*(8-byteShift))),
7691             binop(Iop_Shr64, mkexpr(lo64), mkU8(8*byteShift))
7692       );
7693 }
7694
7695 /* Generate a SIGSEGV followed by a restart of the current instruction
7696    if effective_addr is not 16-aligned.  This is required behaviour
7697    for some SSE3 instructions and all 128-bit SSSE3 instructions.
7698    This assumes that guest_RIP_curr_instr is set correctly! */
7699 static void gen_SEGV_if_not_16_aligned ( IRTemp effective_addr )
7700 {
7701    stmt(
7702       IRStmt_Exit(
7703          binop(Iop_CmpNE32,
7704                binop(Iop_And32,mkexpr(effective_addr),mkU32(0xF)),
7705                mkU32(0)),
7706          Ijk_SigSEGV,
7707          IRConst_U32(guest_EIP_curr_instr)
7708       )
7709    );
7710 }
7711
7712
7713 /* Helper for deciding whether a given insn (starting at the opcode
7714    byte) may validly be used with a LOCK prefix.  The following insns
7715    may be used with LOCK when their destination operand is in memory.
7716    AFAICS this is exactly the same for both 32-bit and 64-bit mode.
7717
7718    ADD        80 /0,  81 /0,  82 /0,  83 /0,  00,  01
7719    OR         80 /1,  81 /1,  82 /x,  83 /1,  08,  09
7720    ADC        80 /2,  81 /2,  82 /2,  83 /2,  10,  11
7721    SBB        81 /3,  81 /3,  82 /x,  83 /3,  18,  19
7722    AND        80 /4,  81 /4,  82 /x,  83 /4,  20,  21
7723    SUB        80 /5,  81 /5,  82 /x,  83 /5,  28,  29
7724    XOR        80 /6,  81 /6,  82 /x,  83 /6,  30,  31
7725
7726    DEC        FE /1,  FF /1
7727    INC        FE /0,  FF /0
7728
7729    NEG        F6 /3,  F7 /3
7730    NOT        F6 /2,  F7 /2
7731
7732    XCHG       86, 87
7733
7734    BTC        0F BB,  0F BA /7
7735    BTR        0F B3,  0F BA /6
7736    BTS        0F AB,  0F BA /5
7737
7738    CMPXCHG    0F B0,  0F B1
7739    CMPXCHG8B  0F C7 /1
7740
7741    XADD       0F C0,  0F C1
7742
7743    ------------------------------
7744
7745    80 /0  =  addb $imm8,  rm8
7746    81 /0  =  addl $imm32, rm32  and  addw $imm16, rm16
7747    82 /0  =  addb $imm8,  rm8
7748    83 /0  =  addl $simm8, rm32  and  addw $simm8, rm16
7749
7750    00     =  addb r8,  rm8
7751    01     =  addl r32, rm32  and  addw r16, rm16
7752
7753    Same for ADD OR ADC SBB AND SUB XOR
7754
7755    FE /1  = dec rm8
7756    FF /1  = dec rm32  and  dec rm16
7757
7758    FE /0  = inc rm8
7759    FF /0  = inc rm32  and  inc rm16
7760
7761    F6 /3  = neg rm8
7762    F7 /3  = neg rm32  and  neg rm16
7763
7764    F6 /2  = not rm8
7765    F7 /2  = not rm32  and  not rm16
7766
7767    0F BB     = btcw r16, rm16    and  btcl r32, rm32
7768    OF BA /7  = btcw $imm8, rm16  and  btcw $imm8, rm32
7769
7770    Same for BTS, BTR
7771 */
7772 static Bool can_be_used_with_LOCK_prefix ( UChar* opc )
7773 {
7774    switch (opc[0]) {
7775       case 0x00: case 0x01: case 0x08: case 0x09:
7776       case 0x10: case 0x11: case 0x18: case 0x19:
7777       case 0x20: case 0x21: case 0x28: case 0x29:
7778       case 0x30: case 0x31:
7779          if (!epartIsReg(opc[1]))
7780             return True;
7781          break;
7782
7783       case 0x80: case 0x81: case 0x82: case 0x83:
7784          if (gregOfRM(opc[1]) >= 0 && gregOfRM(opc[1]) <= 6
7785              && !epartIsReg(opc[1]))
7786             return True;
7787          break;
7788
7789       case 0xFE: case 0xFF:
7790          if (gregOfRM(opc[1]) >= 0 && gregOfRM(opc[1]) <= 1
7791              && !epartIsReg(opc[1]))
7792             return True;
7793          break;
7794
7795       case 0xF6: case 0xF7:
7796          if (gregOfRM(opc[1]) >= 2 && gregOfRM(opc[1]) <= 3
7797              && !epartIsReg(opc[1]))
7798             return True;
7799          break;
7800
7801       case 0x86: case 0x87:
7802          if (!epartIsReg(opc[1]))
7803             return True;
7804          break;
7805
7806       case 0x0F: {
7807          switch (opc[1]) {
7808             case 0xBB: case 0xB3: case 0xAB:
7809                if (!epartIsReg(opc[2]))
7810                   return True;
7811                break;
7812             case 0xBA: 
7813                if (gregOfRM(opc[2]) >= 5 && gregOfRM(opc[2]) <= 7
7814                    && !epartIsReg(opc[2]))
7815                   return True;
7816                break;
7817             case 0xB0: case 0xB1:
7818                if (!epartIsReg(opc[2]))
7819                   return True;
7820                break;
7821             case 0xC7: 
7822                if (gregOfRM(opc[2]) == 1 && !epartIsReg(opc[2]) )
7823                   return True;
7824                break;
7825             case 0xC0: case 0xC1:
7826                if (!epartIsReg(opc[2]))
7827                   return True;
7828                break;
7829             default:
7830                break;
7831          } /* switch (opc[1]) */
7832          break;
7833       }
7834
7835       default:
7836          break;
7837    } /* switch (opc[0]) */
7838
7839    return False;
7840 }
7841
7842
7843 /*------------------------------------------------------------*/
7844 /*--- Disassemble a single instruction                     ---*/
7845 /*------------------------------------------------------------*/
7846
7847 /* Disassemble a single instruction into IR.  The instruction is
7848    located in host memory at &guest_code[delta].  *expect_CAS is set
7849    to True if the resulting IR is expected to contain an IRCAS
7850    statement, and False if it's not expected to.  This makes it
7851    possible for the caller of disInstr_X86_WRK to check that
7852    LOCK-prefixed instructions are at least plausibly translated, in
7853    that it becomes possible to check that a (validly) LOCK-prefixed
7854    instruction generates a translation containing an IRCAS, and
7855    instructions without LOCK prefixes don't generate translations
7856    containing an IRCAS.
7857 */
7858 static
7859 DisResult disInstr_X86_WRK (
7860              /*OUT*/Bool* expect_CAS,
7861              Bool         put_IP,
7862              Bool         (*resteerOkFn) ( /*opaque*/void*, Addr64 ),
7863              Bool         resteerCisOk,
7864              void*        callback_opaque,
7865              Long         delta64,
7866              VexArchInfo* archinfo,
7867              VexAbiInfo*  vbi
7868           )
7869 {
7870    IRType    ty;
7871    IRTemp    addr, t0, t1, t2, t3, t4, t5, t6;
7872    Int       alen;
7873    UChar     opc, modrm, abyte, pre;
7874    UInt      d32;
7875    HChar     dis_buf[50];
7876    Int       am_sz, d_sz, n_prefixes;
7877    DisResult dres;
7878    UChar*    insn; /* used in SSE decoders */
7879
7880    /* The running delta */
7881    Int delta = (Int)delta64;
7882
7883    /* Holds eip at the start of the insn, so that we can print
7884       consistent error messages for unimplemented insns. */
7885    Int delta_start = delta;
7886
7887    /* sz denotes the nominal data-op size of the insn; we change it to
7888       2 if an 0x66 prefix is seen */
7889    Int sz = 4;
7890
7891    /* sorb holds the segment-override-prefix byte, if any.  Zero if no
7892       prefix has been seen, else one of {0x26, 0x3E, 0x64, 0x65}
7893       indicating the prefix.  */
7894    UChar sorb = 0;
7895
7896    /* Gets set to True if a LOCK prefix is seen. */
7897    Bool pfx_lock = False;
7898
7899    /* Set result defaults. */
7900    dres.whatNext   = Dis_Continue;
7901    dres.len        = 0;
7902    dres.continueAt = 0;
7903
7904    *expect_CAS = False;
7905
7906    addr = t0 = t1 = t2 = t3 = t4 = t5 = t6 = IRTemp_INVALID; 
7907
7908    vassert(guest_EIP_bbstart + delta == guest_EIP_curr_instr);
7909    DIP("\t0x%x:  ", guest_EIP_bbstart+delta);
7910
7911    /* We may be asked to update the guest EIP before going further. */
7912    if (put_IP)
7913       stmt( IRStmt_Put( OFFB_EIP, mkU32(guest_EIP_curr_instr)) );
7914
7915    /* Spot "Special" instructions (see comment at top of file). */
7916    {
7917       UChar* code = (UChar*)(guest_code + delta);
7918       /* Spot the 12-byte preamble:
7919          C1C703   roll $3,  %edi
7920          C1C70D   roll $13, %edi
7921          C1C71D   roll $29, %edi
7922          C1C713   roll $19, %edi
7923       */
7924       if (code[ 0] == 0xC1 && code[ 1] == 0xC7 && code[ 2] == 0x03 &&
7925           code[ 3] == 0xC1 && code[ 4] == 0xC7 && code[ 5] == 0x0D &&
7926           code[ 6] == 0xC1 && code[ 7] == 0xC7 && code[ 8] == 0x1D &&
7927           code[ 9] == 0xC1 && code[10] == 0xC7 && code[11] == 0x13) {
7928          /* Got a "Special" instruction preamble.  Which one is it? */
7929          if (code[12] == 0x87 && code[13] == 0xDB /* xchgl %ebx,%ebx */) {
7930             /* %EDX = client_request ( %EAX ) */
7931             DIP("%%edx = client_request ( %%eax )\n");
7932             delta += 14;
7933             jmp_lit(Ijk_ClientReq, guest_EIP_bbstart+delta);
7934             dres.whatNext = Dis_StopHere;
7935             goto decode_success;
7936          }
7937          else
7938          if (code[12] == 0x87 && code[13] == 0xC9 /* xchgl %ecx,%ecx */) {
7939             /* %EAX = guest_NRADDR */
7940             DIP("%%eax = guest_NRADDR\n");
7941             delta += 14;
7942             putIReg(4, R_EAX, IRExpr_Get( OFFB_NRADDR, Ity_I32 ));
7943             goto decode_success;
7944          }
7945          else
7946          if (code[12] == 0x87 && code[13] == 0xD2 /* xchgl %edx,%edx */) {
7947             /* call-noredir *%EAX */
7948             DIP("call-noredir *%%eax\n");
7949             delta += 14;
7950             t1 = newTemp(Ity_I32);
7951             assign(t1, getIReg(4,R_EAX));
7952             t2 = newTemp(Ity_I32);
7953             assign(t2, binop(Iop_Sub32, getIReg(4,R_ESP), mkU32(4)));
7954             putIReg(4, R_ESP, mkexpr(t2));
7955             storeLE( mkexpr(t2), mkU32(guest_EIP_bbstart+delta));
7956             jmp_treg(Ijk_NoRedir,t1);
7957             dres.whatNext = Dis_StopHere;
7958             goto decode_success;
7959          }
7960          /* We don't know what it is. */
7961          goto decode_failure;
7962          /*NOTREACHED*/
7963       }
7964 #if 1
7965       /* To make a syscall in L4Re the guest must access its UTCB.
7966        * The address of the UTCB is stored in %fs, so we look for
7967        * the following instructions:
7968        * 64 a1 00 00 00 00       mov    %fs:0x0,%eax
7969        * 64 8b 0d 00 00 00 00    mov    %fs:0x0,%ecx
7970        * 64 8b 15 00 00 00 00    mov    %fs:0x0,%edx
7971        * 64 8b 3d 00 00 00 00    mov    %fs:0x0,%edi
7972        * 64 8b 35 00 00 00 00    mov    %fs:0x0,%esi
7973        */
7974       if (code[ 0] == 0x64 && code[ 1] == 0xa1 && code[ 2] == 0x0 &&
7975           code[ 3] == 0x0  && code[ 4] == 0x0  && code[ 5] == 0x0) {
7976 //          printf("%x\n", code);
7977 //          printf("0x%x\n", guest_EIP_bbstart+delta);
7978 //          DIP("%%edx = client_request ( %%eax )\n");
7979 //          putIReg(4, R_EAX, mkexpr(0xdeadbeef));
7980 //          vg_enter_kdebug();
7981           delta += 6;
7982           jmp_lit(Ijk_l4_utcb_eax, guest_EIP_bbstart+delta);
7983           dres.whatNext = Dis_StopHere;
7984           goto decode_success;
7985       }
7986       /* utcb -> ebx */
7987       // TODO implement me
7988       /* utcb -> ecx */
7989       if (code[ 0] == 0x64 && code[ 1] == 0x8b && code[ 2] == 0x0d &&
7990           code[ 3] == 0x0  && code[ 4] == 0x0  && code[ 5] == 0x0  && code[ 6] == 0x0) {
7991           delta += 7;
7992           jmp_lit(Ijk_l4_utcb_ecx, guest_EIP_bbstart+delta);
7993           dres.whatNext = Dis_StopHere;
7994           goto decode_success;
7995       }
7996       /* utcb -> edx */
7997       if (code[ 0] == 0x64 && code[ 1] == 0x8b && code[ 2] == 0x15 &&
7998           code[ 3] == 0x0  && code[ 4] == 0x0  && code[ 5] == 0x0  && code[ 6] == 0x0) {
7999           delta += 7;
8000           jmp_lit(Ijk_l4_utcb_edx, guest_EIP_bbstart+delta);
8001           dres.whatNext = Dis_StopHere;
8002           goto decode_success;
8003       }
8004       /* utcb -> edi */
8005       if (code[ 0] == 0x64 && code[ 1] == 0x8b && code[ 2] == 0x3d &&
8006           code[ 3] == 0x0  && code[ 4] == 0x0  && code[ 5] == 0x0  && code[ 6] == 0x0) {
8007           delta += 7;
8008           jmp_lit(Ijk_l4_utcb_edi, guest_EIP_bbstart+delta);
8009           dres.whatNext = Dis_StopHere;
8010           goto decode_success;
8011       }
8012
8013       /* utcb -> esi */
8014       if (code[ 0] == 0x64 && code[ 1] == 0x8b && code[ 2] == 0x35 &&
8015           code[ 3] == 0x0  && code[ 4] == 0x0  && code[ 5] == 0x0  && code[ 6] == 0x0) {
8016           delta += 7;
8017           jmp_lit(Ijk_l4_utcb_esi, guest_EIP_bbstart+delta);
8018           dres.whatNext = Dis_StopHere;
8019           goto decode_success;
8020       }
8021
8022           /* ud2 */
8023           if (code[ 0] == 0x0F && code[ 1] == 0x0B) {
8024                   delta += 2;
8025                   jmp_lit(Ijk_l4_ud2, guest_EIP_bbstart+delta);
8026                   dres.whatNext = Dis_StopHere;
8027                   goto decode_success;
8028           }
8029
8030           /*
8031            * The L4Re artificial trap instruction:
8032            *
8033            * 0x50             push eax
8034            * 0xc1 0xc0 0x42   rol eax, 0x42
8035            * 0xc1 0xc8 0x42   ror eax, 0x42
8036            * 0x58             pop eax
8037            */
8038           if (code[ 0] == 0x50 && code[ 1] == 0xc1 &&
8039                   code[ 2] == 0xc0 && code[ 3] == 0x42 &&
8040                   code[ 4] == 0xc1 && code[ 5] == 0xc8 &&
8041                   code[ 6] == 0x42 && code[ 7] == 0x58) {
8042                   delta += 8;
8043                   jmp_lit(Ijk_l4_artificial, guest_EIP_bbstart + delta);
8044                   dres.whatNext = Dis_StopHere;
8045                   goto decode_success;
8046           }
8047 #endif // L4Re
8048    }
8049
8050    /* Handle a couple of weird-ass NOPs that have been observed in the
8051       wild. */
8052    {
8053       UChar* code = (UChar*)(guest_code + delta);
8054       /* Sun's JVM 1.5.0 uses the following as a NOP:
8055          26 2E 64 65 90  %es:%cs:%fs:%gs:nop */
8056       if (code[0] == 0x26 && code[1] == 0x2E && code[2] == 0x64 
8057           && code[3] == 0x65 && code[4] == 0x90) {
8058          DIP("%%es:%%cs:%%fs:%%gs:nop\n");
8059          delta += 5;
8060          goto decode_success;
8061       }
8062       /* Don't barf on recent binutils padding,
8063          all variants of which are: nopw %cs:0x0(%eax,%eax,1)
8064          66 2e 0f 1f 84 00 00 00 00 00
8065          66 66 2e 0f 1f 84 00 00 00 00 00
8066          66 66 66 2e 0f 1f 84 00 00 00 00 00
8067          66 66 66 66 2e 0f 1f 84 00 00 00 00 00
8068          66 66 66 66 66 2e 0f 1f 84 00 00 00 00 00
8069          66 66 66 66 66 66 2e 0f 1f 84 00 00 00 00 00
8070       */
8071       if (code[0] == 0x66) {
8072          Int data16_cnt;
8073          for (data16_cnt = 1; data16_cnt < 6; data16_cnt++)
8074             if (code[data16_cnt] != 0x66)
8075                break;
8076          if (code[data16_cnt] == 0x2E && code[data16_cnt + 1] == 0x0F
8077              && code[data16_cnt + 2] == 0x1F && code[data16_cnt + 3] == 0x84
8078              && code[data16_cnt + 4] == 0x00 && code[data16_cnt + 5] == 0x00
8079              && code[data16_cnt + 6] == 0x00 && code[data16_cnt + 7] == 0x00
8080              && code[data16_cnt + 8] == 0x00 ) {
8081             DIP("nopw %%cs:0x0(%%eax,%%eax,1)\n");
8082             delta += 9 + data16_cnt;
8083             goto decode_success;
8084          }
8085       }
8086    }       
8087
8088    /* Normal instruction handling starts here. */
8089
8090    /* Deal with some but not all prefixes: 
8091          66(oso)
8092          F0(lock)
8093          2E(cs:) 3E(ds:) 26(es:) 64(fs:) 65(gs:) 36(ss:)
8094       Not dealt with (left in place):
8095          F2 F3
8096    */
8097    n_prefixes = 0;
8098    while (True) {
8099       if (n_prefixes > 7) goto decode_failure;
8100       pre = getUChar(delta);
8101       switch (pre) {
8102          case 0x66: 
8103             sz = 2;
8104             break;
8105          case 0xF0: 
8106             pfx_lock = True; 
8107             *expect_CAS = True;
8108             break;
8109          case 0x3E: /* %DS: */
8110          case 0x26: /* %ES: */
8111          case 0x64: /* %FS: */
8112          case 0x65: /* %GS: */
8113             if (sorb != 0) 
8114                goto decode_failure; /* only one seg override allowed */
8115             sorb = pre;
8116             break;
8117          case 0x2E: { /* %CS: */
8118             /* 2E prefix on a conditional branch instruction is a
8119                branch-prediction hint, which can safely be ignored.  */
8120             UChar op1 = getIByte(delta+1);
8121             UChar op2 = getIByte(delta+2);
8122             if ((op1 >= 0x70 && op1 <= 0x7F)
8123                 || (op1 == 0xE3)
8124                 || (op1 == 0x0F && op2 >= 0x80 && op2 <= 0x8F)) {
8125                if (0) vex_printf("vex x86->IR: ignoring branch hint\n");
8126             } else {
8127                /* All other CS override cases are not handled */
8128                goto decode_failure;
8129             }
8130             break;
8131          }
8132          case 0x36: /* %SS: */
8133             /* SS override cases are not handled */
8134             goto decode_failure;
8135          default: 
8136             goto not_a_prefix;
8137       }
8138       n_prefixes++;
8139       delta++;
8140    }
8141
8142    not_a_prefix:
8143
8144    /* Now we should be looking at the primary opcode byte or the
8145       leading F2 or F3.  Check that any LOCK prefix is actually
8146       allowed. */
8147
8148    if (pfx_lock) {
8149       if (can_be_used_with_LOCK_prefix( (UChar*)&guest_code[delta] )) {
8150          DIP("lock ");
8151       } else {
8152          *expect_CAS = False;
8153          goto decode_failure;
8154       }
8155    }
8156
8157
8158    /* ---------------------------------------------------- */
8159    /* --- The SSE decoder.                             --- */
8160    /* ---------------------------------------------------- */
8161
8162    /* What did I do to deserve SSE ?  Perhaps I was really bad in a
8163       previous life? */
8164
8165    /* Note, this doesn't handle SSE2 or SSE3.  That is handled in a
8166       later section, further on. */
8167
8168    insn = (UChar*)&guest_code[delta];
8169
8170    /* Treat fxsave specially.  It should be doable even on an SSE0
8171       (Pentium-II class) CPU.  Hence be prepared to handle it on
8172       any subarchitecture variant.
8173    */
8174
8175    /* 0F AE /0 = FXSAVE m512 -- write x87 and SSE state to memory */
8176    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xAE
8177        && !epartIsReg(insn[2]) && gregOfRM(insn[2]) == 0) {
8178       IRDirty* d;
8179       modrm = getIByte(delta+2);
8180       vassert(sz == 4);
8181       vassert(!epartIsReg(modrm));
8182
8183       addr = disAMode ( &alen, sorb, delta+2, dis_buf );
8184       delta += 2+alen;
8185       gen_SEGV_if_not_16_aligned(addr);
8186
8187       DIP("fxsave %s\n", dis_buf);
8188
8189       /* Uses dirty helper: 
8190             void x86g_do_FXSAVE ( VexGuestX86State*, UInt ) */
8191       d = unsafeIRDirty_0_N ( 
8192              0/*regparms*/, 
8193              "x86g_dirtyhelper_FXSAVE", 
8194              &x86g_dirtyhelper_FXSAVE,
8195              mkIRExprVec_1( mkexpr(addr) )
8196           );
8197       d->needsBBP = True;
8198
8199       /* declare we're writing memory */
8200       d->mFx   = Ifx_Write;
8201       d->mAddr = mkexpr(addr);
8202       d->mSize = 512;
8203
8204       /* declare we're reading guest state */
8205       d->nFxState = 7;
8206
8207       d->fxState[0].fx     = Ifx_Read;
8208       d->fxState[0].offset = OFFB_FTOP;
8209       d->fxState[0].size   = sizeof(UInt);
8210
8211       d->fxState[1].fx     = Ifx_Read;
8212       d->fxState[1].offset = OFFB_FPREGS;
8213       d->fxState[1].size   = 8 * sizeof(ULong);
8214
8215       d->fxState[2].fx     = Ifx_Read;
8216       d->fxState[2].offset = OFFB_FPTAGS;
8217       d->fxState[2].size   = 8 * sizeof(UChar);
8218
8219       d->fxState[3].fx     = Ifx_Read;
8220       d->fxState[3].offset = OFFB_FPROUND;
8221       d->fxState[3].size   = sizeof(UInt);
8222
8223       d->fxState[4].fx     = Ifx_Read;
8224       d->fxState[4].offset = OFFB_FC3210;
8225       d->fxState[4].size   = sizeof(UInt);
8226
8227       d->fxState[5].fx     = Ifx_Read;
8228       d->fxState[5].offset = OFFB_XMM0;
8229       d->fxState[5].size   = 8 * sizeof(U128);
8230
8231       d->fxState[6].fx     = Ifx_Read;
8232       d->fxState[6].offset = OFFB_SSEROUND;
8233       d->fxState[6].size   = sizeof(UInt);
8234
8235       /* Be paranoid ... this assertion tries to ensure the 8 %xmm
8236          images are packed back-to-back.  If not, the value of
8237          d->fxState[5].size is wrong. */
8238       vassert(16 == sizeof(U128));
8239       vassert(OFFB_XMM7 == (OFFB_XMM0 + 7 * 16));
8240
8241       stmt( IRStmt_Dirty(d) );
8242
8243       goto decode_success;
8244    }
8245
8246    /* 0F AE /1 = FXRSTOR m512 -- read x87 and SSE state from memory */
8247    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xAE
8248        && !epartIsReg(insn[2]) && gregOfRM(insn[2]) == 1) {
8249       IRDirty* d;
8250       modrm = getIByte(delta+2);
8251       vassert(sz == 4);
8252       vassert(!epartIsReg(modrm));
8253
8254       addr = disAMode ( &alen, sorb, delta+2, dis_buf );
8255       delta += 2+alen;
8256       gen_SEGV_if_not_16_aligned(addr);
8257
8258       DIP("fxrstor %s\n", dis_buf);
8259
8260       /* Uses dirty helper: 
8261             VexEmWarn x86g_do_FXRSTOR ( VexGuestX86State*, UInt )
8262          NOTE:
8263             the VexEmWarn value is simply ignored (unlike for FRSTOR)
8264       */
8265       d = unsafeIRDirty_0_N ( 
8266              0/*regparms*/, 
8267              "x86g_dirtyhelper_FXRSTOR", 
8268              &x86g_dirtyhelper_FXRSTOR,
8269              mkIRExprVec_1( mkexpr(addr) )
8270           );
8271       d->needsBBP = True;
8272
8273       /* declare we're reading memory */
8274       d->mFx   = Ifx_Read;
8275       d->mAddr = mkexpr(addr);
8276       d->mSize = 512;
8277
8278       /* declare we're writing guest state */
8279       d->nFxState = 7;
8280
8281       d->fxState[0].fx     = Ifx_Write;
8282       d->fxState[0].offset = OFFB_FTOP;
8283       d->fxState[0].size   = sizeof(UInt);
8284
8285       d->fxState[1].fx     = Ifx_Write;
8286       d->fxState[1].offset = OFFB_FPREGS;
8287       d->fxState[1].size   = 8 * sizeof(ULong);
8288
8289       d->fxState[2].fx     = Ifx_Write;
8290       d->fxState[2].offset = OFFB_FPTAGS;
8291       d->fxState[2].size   = 8 * sizeof(UChar);
8292
8293       d->fxState[3].fx     = Ifx_Write;
8294       d->fxState[3].offset = OFFB_FPROUND;
8295       d->fxState[3].size   = sizeof(UInt);
8296
8297       d->fxState[4].fx     = Ifx_Write;
8298       d->fxState[4].offset = OFFB_FC3210;
8299       d->fxState[4].size   = sizeof(UInt);
8300
8301       d->fxState[5].fx     = Ifx_Write;
8302       d->fxState[5].offset = OFFB_XMM0;
8303       d->fxState[5].size   = 8 * sizeof(U128);
8304
8305       d->fxState[6].fx     = Ifx_Write;
8306       d->fxState[6].offset = OFFB_SSEROUND;
8307       d->fxState[6].size   = sizeof(UInt);
8308
8309       /* Be paranoid ... this assertion tries to ensure the 8 %xmm
8310          images are packed back-to-back.  If not, the value of
8311          d->fxState[5].size is wrong. */
8312       vassert(16 == sizeof(U128));
8313       vassert(OFFB_XMM7 == (OFFB_XMM0 + 7 * 16));
8314
8315       stmt( IRStmt_Dirty(d) );
8316
8317       goto decode_success;
8318    }
8319
8320    /* ------ SSE decoder main ------ */
8321
8322    /* Skip parts of the decoder which don't apply given the stated
8323       guest subarchitecture. */
8324    if (archinfo->hwcaps == 0/*baseline, no sse at all*/)
8325       goto after_sse_decoders;
8326    
8327    /* Otherwise we must be doing sse1 or sse2, so we can at least try
8328       for SSE1 here. */
8329
8330    /* 0F 58 = ADDPS -- add 32Fx4 from R/M to R */
8331    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x58) {
8332       delta = dis_SSE_E_to_G_all( sorb, delta+2, "addps", Iop_Add32Fx4 );
8333       goto decode_success;
8334    }
8335
8336    /* F3 0F 58 = ADDSS -- add 32F0x4 from R/M to R */
8337    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x58) {
8338       vassert(sz == 4);
8339       delta = dis_SSE_E_to_G_lo32( sorb, delta+3, "addss", Iop_Add32F0x4 );
8340       goto decode_success;
8341    }
8342
8343    /* 0F 55 = ANDNPS -- G = (not G) and E */
8344    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x55) {
8345       delta = dis_SSE_E_to_G_all_invG( sorb, delta+2, "andnps", Iop_AndV128 );
8346       goto decode_success;
8347    }
8348
8349    /* 0F 54 = ANDPS -- G = G and E */
8350    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x54) {
8351       delta = dis_SSE_E_to_G_all( sorb, delta+2, "andps", Iop_AndV128 );
8352       goto decode_success;
8353    }
8354
8355    /* 0F C2 = CMPPS -- 32Fx4 comparison from R/M to R */
8356    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xC2) {
8357       delta = dis_SSEcmp_E_to_G( sorb, delta+2, "cmpps", True, 4 );
8358       goto decode_success;
8359    }
8360
8361    /* F3 0F C2 = CMPSS -- 32F0x4 comparison from R/M to R */
8362    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0xC2) {
8363       vassert(sz == 4);
8364       delta = dis_SSEcmp_E_to_G( sorb, delta+3, "cmpss", False, 4 );
8365       goto decode_success;
8366    }
8367
8368    /* 0F 2F = COMISS  -- 32F0x4 comparison G,E, and set ZCP */
8369    /* 0F 2E = UCOMISS -- 32F0x4 comparison G,E, and set ZCP */
8370    if (sz == 4 && insn[0] == 0x0F && (insn[1] == 0x2F || insn[1] == 0x2E)) {
8371       IRTemp argL = newTemp(Ity_F32);
8372       IRTemp argR = newTemp(Ity_F32);
8373       modrm = getIByte(delta+2);
8374       if (epartIsReg(modrm)) {
8375          assign( argR, getXMMRegLane32F( eregOfRM(modrm), 0/*lowest lane*/ ) );
8376          delta += 2+1;
8377          DIP("[u]comiss %s,%s\n", nameXMMReg(eregOfRM(modrm)),
8378                                   nameXMMReg(gregOfRM(modrm)) );
8379       } else {
8380          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
8381          assign( argR, loadLE(Ity_F32, mkexpr(addr)) );
8382          delta += 2+alen;
8383          DIP("[u]comiss %s,%s\n", dis_buf,
8384                                   nameXMMReg(gregOfRM(modrm)) );
8385       }
8386       assign( argL, getXMMRegLane32F( gregOfRM(modrm), 0/*lowest lane*/ ) );
8387
8388       stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(X86G_CC_OP_COPY) ));
8389       stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0) ));
8390       stmt( IRStmt_Put( 
8391                OFFB_CC_DEP1,
8392                binop( Iop_And32,
8393                       binop(Iop_CmpF64, 
8394                             unop(Iop_F32toF64,mkexpr(argL)),
8395                             unop(Iop_F32toF64,mkexpr(argR))),
8396                       mkU32(0x45)
8397           )));
8398       /* Set NDEP even though it isn't used.  This makes redundant-PUT
8399          elimination of previous stores to this field work better. */
8400       stmt( IRStmt_Put( OFFB_CC_NDEP, mkU32(0) ));
8401       goto decode_success;
8402    }
8403
8404    /* 0F 2A = CVTPI2PS -- convert 2 x I32 in mem/mmx to 2 x F32 in low
8405       half xmm */
8406    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x2A) {
8407       IRTemp arg64 = newTemp(Ity_I64);
8408       IRTemp rmode = newTemp(Ity_I32);
8409       vassert(sz == 4);
8410
8411       modrm = getIByte(delta+2);
8412       do_MMX_preamble();
8413       if (epartIsReg(modrm)) {
8414          assign( arg64, getMMXReg(eregOfRM(modrm)) );
8415          delta += 2+1;
8416          DIP("cvtpi2ps %s,%s\n", nameMMXReg(eregOfRM(modrm)),
8417                                  nameXMMReg(gregOfRM(modrm)));
8418       } else {
8419          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
8420          assign( arg64, loadLE(Ity_I64, mkexpr(addr)) );
8421          delta += 2+alen;
8422          DIP("cvtpi2ps %s,%s\n", dis_buf,
8423                                  nameXMMReg(gregOfRM(modrm)) );
8424       }
8425
8426       assign( rmode, get_sse_roundingmode() );
8427
8428       putXMMRegLane32F( 
8429          gregOfRM(modrm), 0,
8430          binop(Iop_F64toF32, 
8431                mkexpr(rmode),
8432                unop(Iop_I32StoF64, 
8433                     unop(Iop_64to32, mkexpr(arg64)) )) );
8434
8435       putXMMRegLane32F(
8436          gregOfRM(modrm), 1, 
8437          binop(Iop_F64toF32, 
8438                mkexpr(rmode),
8439                unop(Iop_I32StoF64,
8440                     unop(Iop_64HIto32, mkexpr(arg64)) )) );
8441
8442       goto decode_success;
8443    }
8444
8445    /* F3 0F 2A = CVTSI2SS -- convert I32 in mem/ireg to F32 in low
8446       quarter xmm */
8447    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x2A) {
8448       IRTemp arg32 = newTemp(Ity_I32);
8449       IRTemp rmode = newTemp(Ity_I32);
8450       vassert(sz == 4);
8451
8452       modrm = getIByte(delta+3);
8453       if (epartIsReg(modrm)) {
8454          assign( arg32, getIReg(4, eregOfRM(modrm)) );
8455          delta += 3+1;
8456          DIP("cvtsi2ss %s,%s\n", nameIReg(4, eregOfRM(modrm)),
8457                                  nameXMMReg(gregOfRM(modrm)));
8458       } else {
8459          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
8460          assign( arg32, loadLE(Ity_I32, mkexpr(addr)) );
8461          delta += 3+alen;
8462          DIP("cvtsi2ss %s,%s\n", dis_buf,
8463                                  nameXMMReg(gregOfRM(modrm)) );
8464       }
8465
8466       assign( rmode, get_sse_roundingmode() );
8467
8468       putXMMRegLane32F( 
8469          gregOfRM(modrm), 0,
8470          binop(Iop_F64toF32,
8471                mkexpr(rmode),
8472                unop(Iop_I32StoF64, mkexpr(arg32)) ) );
8473
8474       goto decode_success;
8475    }
8476
8477    /* 0F 2D = CVTPS2PI -- convert 2 x F32 in mem/low half xmm to 2 x
8478       I32 in mmx, according to prevailing SSE rounding mode */
8479    /* 0F 2C = CVTTPS2PI -- convert 2 x F32 in mem/low half xmm to 2 x
8480       I32 in mmx, rounding towards zero */
8481    if (sz == 4 && insn[0] == 0x0F && (insn[1] == 0x2D || insn[1] == 0x2C)) {
8482       IRTemp dst64  = newTemp(Ity_I64);
8483       IRTemp rmode  = newTemp(Ity_I32);
8484       IRTemp f32lo  = newTemp(Ity_F32);
8485       IRTemp f32hi  = newTemp(Ity_F32);
8486       Bool   r2zero = toBool(insn[1] == 0x2C);
8487
8488       do_MMX_preamble();
8489       modrm = getIByte(delta+2);
8490
8491       if (epartIsReg(modrm)) {
8492          delta += 2+1;
8493          assign(f32lo, getXMMRegLane32F(eregOfRM(modrm), 0));
8494          assign(f32hi, getXMMRegLane32F(eregOfRM(modrm), 1));
8495          DIP("cvt%sps2pi %s,%s\n", r2zero ? "t" : "",
8496                                    nameXMMReg(eregOfRM(modrm)),
8497                                    nameMMXReg(gregOfRM(modrm)));
8498       } else {
8499          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
8500          assign(f32lo, loadLE(Ity_F32, mkexpr(addr)));
8501          assign(f32hi, loadLE(Ity_F32, binop( Iop_Add32, 
8502                                               mkexpr(addr), 
8503                                               mkU32(4) )));
8504          delta += 2+alen;
8505          DIP("cvt%sps2pi %s,%s\n", r2zero ? "t" : "",
8506                                    dis_buf,
8507                                    nameMMXReg(gregOfRM(modrm)));
8508       }
8509
8510       if (r2zero) {
8511          assign(rmode, mkU32((UInt)Irrm_ZERO) );
8512       } else {
8513          assign( rmode, get_sse_roundingmode() );
8514       }
8515
8516       assign( 
8517          dst64,
8518          binop( Iop_32HLto64,
8519                 binop( Iop_F64toI32S, 
8520                        mkexpr(rmode), 
8521                        unop( Iop_F32toF64, mkexpr(f32hi) ) ),
8522                 binop( Iop_F64toI32S, 
8523                        mkexpr(rmode), 
8524                        unop( Iop_F32toF64, mkexpr(f32lo) ) )
8525               )
8526       );
8527
8528       putMMXReg(gregOfRM(modrm), mkexpr(dst64));
8529       goto decode_success;
8530    }
8531
8532    /* F3 0F 2D = CVTSS2SI -- convert F32 in mem/low quarter xmm to
8533       I32 in ireg, according to prevailing SSE rounding mode */
8534    /* F3 0F 2C = CVTTSS2SI -- convert F32 in mem/low quarter xmm to
8535       I32 in ireg, rounding towards zero */
8536    if (insn[0] == 0xF3 && insn[1] == 0x0F 
8537        && (insn[2] == 0x2D || insn[2] == 0x2C)) {
8538       IRTemp rmode = newTemp(Ity_I32);
8539       IRTemp f32lo = newTemp(Ity_F32);
8540       Bool   r2zero = toBool(insn[2] == 0x2C);
8541       vassert(sz == 4);
8542
8543       modrm = getIByte(delta+3);
8544       if (epartIsReg(modrm)) {
8545          delta += 3+1;
8546          assign(f32lo, getXMMRegLane32F(eregOfRM(modrm), 0));
8547          DIP("cvt%sss2si %s,%s\n", r2zero ? "t" : "",
8548                                    nameXMMReg(eregOfRM(modrm)),
8549                                    nameIReg(4, gregOfRM(modrm)));
8550       } else {
8551          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
8552          assign(f32lo, loadLE(Ity_F32, mkexpr(addr)));
8553          delta += 3+alen;
8554          DIP("cvt%sss2si %s,%s\n", r2zero ? "t" : "",
8555                                    dis_buf,
8556                                    nameIReg(4, gregOfRM(modrm)));
8557       }
8558
8559       if (r2zero) {
8560          assign( rmode, mkU32((UInt)Irrm_ZERO) );
8561       } else {
8562          assign( rmode, get_sse_roundingmode() );
8563       }
8564
8565       putIReg(4, gregOfRM(modrm),
8566                  binop( Iop_F64toI32S, 
8567                         mkexpr(rmode), 
8568                         unop( Iop_F32toF64, mkexpr(f32lo) ) )
8569       );
8570
8571       goto decode_success;
8572    }
8573
8574    /* 0F 5E = DIVPS -- div 32Fx4 from R/M to R */
8575    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x5E) {
8576       delta = dis_SSE_E_to_G_all( sorb, delta+2, "divps", Iop_Div32Fx4 );
8577       goto decode_success;
8578    }
8579
8580    /* F3 0F 5E = DIVSS -- div 32F0x4 from R/M to R */
8581    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x5E) {
8582       vassert(sz == 4);
8583       delta = dis_SSE_E_to_G_lo32( sorb, delta+3, "divss", Iop_Div32F0x4 );
8584       goto decode_success;
8585    }
8586
8587    /* 0F AE /2 = LDMXCSR m32 -- load %mxcsr */
8588    if (insn[0] == 0x0F && insn[1] == 0xAE
8589        && !epartIsReg(insn[2]) && gregOfRM(insn[2]) == 2) {
8590
8591       IRTemp t64 = newTemp(Ity_I64);
8592       IRTemp ew = newTemp(Ity_I32);
8593
8594       modrm = getIByte(delta+2);
8595       vassert(!epartIsReg(modrm));
8596       vassert(sz == 4);
8597
8598       addr = disAMode ( &alen, sorb, delta+2, dis_buf );
8599       delta += 2+alen;
8600       DIP("ldmxcsr %s\n", dis_buf);
8601
8602       /* The only thing we observe in %mxcsr is the rounding mode.
8603          Therefore, pass the 32-bit value (SSE native-format control
8604          word) to a clean helper, getting back a 64-bit value, the
8605          lower half of which is the SSEROUND value to store, and the
8606          upper half of which is the emulation-warning token which may
8607          be generated.  
8608       */
8609       /* ULong x86h_check_ldmxcsr ( UInt ); */
8610       assign( t64, mkIRExprCCall(
8611                       Ity_I64, 0/*regparms*/, 
8612                       "x86g_check_ldmxcsr",
8613                       &x86g_check_ldmxcsr, 
8614                       mkIRExprVec_1( loadLE(Ity_I32, mkexpr(addr)) )
8615                    )
8616             );
8617
8618       put_sse_roundingmode( unop(Iop_64to32, mkexpr(t64)) );
8619       assign( ew, unop(Iop_64HIto32, mkexpr(t64) ) );
8620       put_emwarn( mkexpr(ew) );
8621       /* Finally, if an emulation warning was reported, side-exit to
8622          the next insn, reporting the warning, so that Valgrind's
8623          dispatcher sees the warning. */
8624       stmt( 
8625          IRStmt_Exit(
8626             binop(Iop_CmpNE32, mkexpr(ew), mkU32(0)),
8627             Ijk_EmWarn,
8628             IRConst_U32( ((Addr32)guest_EIP_bbstart)+delta)
8629          )
8630       );
8631       goto decode_success;
8632    }
8633
8634    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
8635    /* 0F F7 = MASKMOVQ -- 8x8 masked store */
8636    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xF7) {
8637       Bool ok = False;
8638       delta = dis_MMX( &ok, sorb, sz, delta+1 );
8639       if (!ok)
8640          goto decode_failure;
8641       goto decode_success;
8642    }
8643
8644    /* 0F 5F = MAXPS -- max 32Fx4 from R/M to R */
8645    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x5F) {
8646       delta = dis_SSE_E_to_G_all( sorb, delta+2, "maxps", Iop_Max32Fx4 );
8647       goto decode_success;
8648    }
8649
8650    /* F3 0F 5F = MAXSS -- max 32F0x4 from R/M to R */
8651    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x5F) {
8652       vassert(sz == 4);
8653       delta = dis_SSE_E_to_G_lo32( sorb, delta+3, "maxss", Iop_Max32F0x4 );
8654       goto decode_success;
8655    }
8656
8657    /* 0F 5D = MINPS -- min 32Fx4 from R/M to R */
8658    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x5D) {
8659       delta = dis_SSE_E_to_G_all( sorb, delta+2, "minps", Iop_Min32Fx4 );
8660       goto decode_success;
8661    }
8662
8663    /* F3 0F 5D = MINSS -- min 32F0x4 from R/M to R */
8664    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x5D) {
8665       vassert(sz == 4);
8666       delta = dis_SSE_E_to_G_lo32( sorb, delta+3, "minss", Iop_Min32F0x4 );
8667       goto decode_success;
8668    }
8669
8670    /* 0F 28 = MOVAPS -- move from E (mem or xmm) to G (xmm). */
8671    /* 0F 10 = MOVUPS -- move from E (mem or xmm) to G (xmm). */
8672    if (sz == 4 && insn[0] == 0x0F && (insn[1] == 0x28 || insn[1] == 0x10)) {
8673       modrm = getIByte(delta+2);
8674       if (epartIsReg(modrm)) {
8675          putXMMReg( gregOfRM(modrm), 
8676                     getXMMReg( eregOfRM(modrm) ));
8677          DIP("mov[ua]ps %s,%s\n", nameXMMReg(eregOfRM(modrm)),
8678                                   nameXMMReg(gregOfRM(modrm)));
8679          delta += 2+1;
8680       } else {
8681          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
8682          if (insn[1] == 0x28/*movaps*/)
8683             gen_SEGV_if_not_16_aligned( addr );
8684          putXMMReg( gregOfRM(modrm), 
8685                     loadLE(Ity_V128, mkexpr(addr)) );
8686          DIP("mov[ua]ps %s,%s\n", dis_buf,
8687                                   nameXMMReg(gregOfRM(modrm)));
8688          delta += 2+alen;
8689       }
8690       goto decode_success;
8691    }
8692
8693    /* 0F 29 = MOVAPS -- move from G (xmm) to E (mem or xmm). */
8694    /* 0F 11 = MOVUPS -- move from G (xmm) to E (mem or xmm). */
8695    if (sz == 4 && insn[0] == 0x0F 
8696        && (insn[1] == 0x29 || insn[1] == 0x11)) {
8697       modrm = getIByte(delta+2);
8698       if (epartIsReg(modrm)) {
8699          /* fall through; awaiting test case */
8700       } else {
8701          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
8702          if (insn[1] == 0x29/*movaps*/)
8703             gen_SEGV_if_not_16_aligned( addr );
8704          storeLE( mkexpr(addr), getXMMReg(gregOfRM(modrm)) );
8705          DIP("mov[ua]ps %s,%s\n", nameXMMReg(gregOfRM(modrm)),
8706                                   dis_buf );
8707          delta += 2+alen;
8708          goto decode_success;
8709       }
8710    }
8711
8712    /* 0F 16 = MOVHPS -- move from mem to high half of XMM. */
8713    /* 0F 16 = MOVLHPS -- move from lo half to hi half of XMM. */
8714    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x16) {
8715       modrm = getIByte(delta+2);
8716       if (epartIsReg(modrm)) {
8717          delta += 2+1;
8718          putXMMRegLane64( gregOfRM(modrm), 1/*upper lane*/,
8719                           getXMMRegLane64( eregOfRM(modrm), 0 ) );
8720          DIP("movhps %s,%s\n", nameXMMReg(eregOfRM(modrm)), 
8721                                nameXMMReg(gregOfRM(modrm)));
8722       } else {
8723          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
8724          delta += 2+alen;
8725          putXMMRegLane64( gregOfRM(modrm), 1/*upper lane*/,
8726                           loadLE(Ity_I64, mkexpr(addr)) );
8727          DIP("movhps %s,%s\n", dis_buf, 
8728                                nameXMMReg( gregOfRM(modrm) ));
8729       }
8730       goto decode_success;
8731    }
8732
8733    /* 0F 17 = MOVHPS -- move from high half of XMM to mem. */
8734    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x17) {
8735       if (!epartIsReg(insn[2])) {
8736          delta += 2;
8737          addr = disAMode ( &alen, sorb, delta, dis_buf );
8738          delta += alen;
8739          storeLE( mkexpr(addr), 
8740                   getXMMRegLane64( gregOfRM(insn[2]),
8741                                    1/*upper lane*/ ) );
8742          DIP("movhps %s,%s\n", nameXMMReg( gregOfRM(insn[2]) ),
8743                                dis_buf);
8744          goto decode_success;
8745       }
8746       /* else fall through */
8747    }
8748
8749    /* 0F 12 = MOVLPS -- move from mem to low half of XMM. */
8750    /* OF 12 = MOVHLPS -- from from hi half to lo half of XMM. */
8751    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x12) {
8752       modrm = getIByte(delta+2);
8753       if (epartIsReg(modrm)) {
8754          delta += 2+1;
8755          putXMMRegLane64( gregOfRM(modrm),  
8756                           0/*lower lane*/,
8757                           getXMMRegLane64( eregOfRM(modrm), 1 ));
8758          DIP("movhlps %s, %s\n", nameXMMReg(eregOfRM(modrm)), 
8759                                  nameXMMReg(gregOfRM(modrm)));
8760       } else {
8761          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
8762          delta += 2+alen;
8763          putXMMRegLane64( gregOfRM(modrm),  0/*lower lane*/,
8764                           loadLE(Ity_I64, mkexpr(addr)) );
8765          DIP("movlps %s, %s\n", 
8766              dis_buf, nameXMMReg( gregOfRM(modrm) ));
8767       }
8768       goto decode_success;
8769    }
8770
8771    /* 0F 13 = MOVLPS -- move from low half of XMM to mem. */
8772    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x13) {
8773       if (!epartIsReg(insn[2])) {
8774          delta += 2;
8775          addr = disAMode ( &alen, sorb, delta, dis_buf );
8776          delta += alen;
8777          storeLE( mkexpr(addr), 
8778                   getXMMRegLane64( gregOfRM(insn[2]), 
8779                                    0/*lower lane*/ ) );
8780          DIP("movlps %s, %s\n", nameXMMReg( gregOfRM(insn[2]) ),
8781                                 dis_buf);
8782          goto decode_success;
8783       }
8784       /* else fall through */
8785    }
8786
8787    /* 0F 50 = MOVMSKPS - move 4 sign bits from 4 x F32 in xmm(E)
8788       to 4 lowest bits of ireg(G) */
8789    if (insn[0] == 0x0F && insn[1] == 0x50) {
8790       modrm = getIByte(delta+2);
8791       if (sz == 4 && epartIsReg(modrm)) {
8792          Int src;
8793          t0 = newTemp(Ity_I32);
8794          t1 = newTemp(Ity_I32);
8795          t2 = newTemp(Ity_I32);
8796          t3 = newTemp(Ity_I32);
8797          delta += 2+1;
8798          src = eregOfRM(modrm);
8799          assign( t0, binop( Iop_And32,
8800                             binop(Iop_Shr32, getXMMRegLane32(src,0), mkU8(31)),
8801                             mkU32(1) ));
8802          assign( t1, binop( Iop_And32,
8803                             binop(Iop_Shr32, getXMMRegLane32(src,1), mkU8(30)),
8804                             mkU32(2) ));
8805          assign( t2, binop( Iop_And32,
8806                             binop(Iop_Shr32, getXMMRegLane32(src,2), mkU8(29)),
8807                             mkU32(4) ));
8808          assign( t3, binop( Iop_And32,
8809                             binop(Iop_Shr32, getXMMRegLane32(src,3), mkU8(28)),
8810                             mkU32(8) ));
8811          putIReg(4, gregOfRM(modrm),
8812                     binop(Iop_Or32,
8813                           binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
8814                           binop(Iop_Or32, mkexpr(t2), mkexpr(t3))
8815                          )
8816                  );
8817          DIP("movmskps %s,%s\n", nameXMMReg(src), 
8818                                  nameIReg(4, gregOfRM(modrm)));
8819          goto decode_success;
8820       }
8821       /* else fall through */
8822    }
8823
8824    /* 0F 2B = MOVNTPS -- for us, just a plain SSE store. */
8825    /* 66 0F 2B = MOVNTPD -- for us, just a plain SSE store. */
8826    if (insn[0] == 0x0F && insn[1] == 0x2B) {
8827       modrm = getIByte(delta+2);
8828       if (!epartIsReg(modrm)) {
8829          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
8830          gen_SEGV_if_not_16_aligned( addr );
8831          storeLE( mkexpr(addr), getXMMReg(gregOfRM(modrm)) );
8832          DIP("movntp%s %s,%s\n", sz==2 ? "d" : "s",
8833                                  dis_buf,
8834                                  nameXMMReg(gregOfRM(modrm)));
8835          delta += 2+alen;
8836          goto decode_success;
8837       }
8838       /* else fall through */
8839    }
8840
8841    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
8842    /* 0F E7 = MOVNTQ -- for us, just a plain MMX store.  Note, the
8843       Intel manual does not say anything about the usual business of
8844       the FP reg tags getting trashed whenever an MMX insn happens.
8845       So we just leave them alone. 
8846    */
8847    if (insn[0] == 0x0F && insn[1] == 0xE7) {
8848       modrm = getIByte(delta+2);
8849       if (sz == 4 && !epartIsReg(modrm)) {
8850          /* do_MMX_preamble(); Intel docs don't specify this */
8851          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
8852          storeLE( mkexpr(addr), getMMXReg(gregOfRM(modrm)) );
8853          DIP("movntq %s,%s\n", dis_buf,
8854                                nameMMXReg(gregOfRM(modrm)));
8855          delta += 2+alen;
8856          goto decode_success;
8857       }
8858       /* else fall through */
8859    }
8860
8861    /* F3 0F 10 = MOVSS -- move 32 bits from E (mem or lo 1/4 xmm) to G
8862       (lo 1/4 xmm).  If E is mem, upper 3/4 of G is zeroed out. */
8863    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x10) {
8864       vassert(sz == 4);
8865       modrm = getIByte(delta+3);
8866       if (epartIsReg(modrm)) {
8867          putXMMRegLane32( gregOfRM(modrm), 0,
8868                           getXMMRegLane32( eregOfRM(modrm), 0 ));
8869          DIP("movss %s,%s\n", nameXMMReg(eregOfRM(modrm)),
8870                               nameXMMReg(gregOfRM(modrm)));
8871          delta += 3+1;
8872       } else {
8873          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
8874          /* zero bits 127:64 */
8875          putXMMRegLane64( gregOfRM(modrm), 1, mkU64(0) ); 
8876          /* zero bits 63:32 */
8877          putXMMRegLane32( gregOfRM(modrm), 1, mkU32(0) ); 
8878          /* write bits 31:0 */
8879          putXMMRegLane32( gregOfRM(modrm), 0,
8880                           loadLE(Ity_I32, mkexpr(addr)) );
8881          DIP("movss %s,%s\n", dis_buf,
8882                               nameXMMReg(gregOfRM(modrm)));
8883          delta += 3+alen;
8884       }
8885       goto decode_success;
8886    }
8887
8888    /* F3 0F 11 = MOVSS -- move 32 bits from G (lo 1/4 xmm) to E (mem
8889       or lo 1/4 xmm). */
8890    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x11) {
8891       vassert(sz == 4);
8892       modrm = getIByte(delta+3);
8893       if (epartIsReg(modrm)) {
8894          /* fall through, we don't yet have a test case */
8895       } else {
8896          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
8897          storeLE( mkexpr(addr),
8898                   getXMMRegLane32(gregOfRM(modrm), 0) );
8899          DIP("movss %s,%s\n", nameXMMReg(gregOfRM(modrm)),
8900                               dis_buf);
8901          delta += 3+alen;
8902          goto decode_success;
8903       }
8904    }
8905
8906    /* 0F 59 = MULPS -- mul 32Fx4 from R/M to R */
8907    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x59) {
8908       delta = dis_SSE_E_to_G_all( sorb, delta+2, "mulps", Iop_Mul32Fx4 );
8909       goto decode_success;
8910    }
8911
8912    /* F3 0F 59 = MULSS -- mul 32F0x4 from R/M to R */
8913    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x59) {
8914       vassert(sz == 4);
8915       delta = dis_SSE_E_to_G_lo32( sorb, delta+3, "mulss", Iop_Mul32F0x4 );
8916       goto decode_success;
8917    }
8918
8919    /* 0F 56 = ORPS -- G = G and E */
8920    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x56) {
8921       delta = dis_SSE_E_to_G_all( sorb, delta+2, "orps", Iop_OrV128 );
8922       goto decode_success;
8923    }
8924
8925    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
8926    /* 0F E0 = PAVGB -- 8x8 unsigned Packed Average, with rounding */
8927    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xE0) {
8928       do_MMX_preamble();
8929       delta = dis_MMXop_regmem_to_reg ( 
8930                 sorb, delta+2, insn[1], "pavgb", False );
8931       goto decode_success;
8932    }
8933
8934    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
8935    /* 0F E3 = PAVGW -- 16x4 unsigned Packed Average, with rounding */
8936    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xE3) {
8937       do_MMX_preamble();
8938       delta = dis_MMXop_regmem_to_reg ( 
8939                 sorb, delta+2, insn[1], "pavgw", False );
8940       goto decode_success;
8941    }
8942
8943    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
8944    /* 0F C5 = PEXTRW -- extract 16-bit field from mmx(E) and put 
8945       zero-extend of it in ireg(G). */
8946    if (insn[0] == 0x0F && insn[1] == 0xC5) {
8947       modrm = insn[2];
8948       if (sz == 4 && epartIsReg(modrm)) {
8949          IRTemp sV = newTemp(Ity_I64);
8950          t5 = newTemp(Ity_I16);
8951          do_MMX_preamble();
8952          assign(sV, getMMXReg(eregOfRM(modrm)));
8953          breakup64to16s( sV, &t3, &t2, &t1, &t0 );
8954          switch (insn[3] & 3) {
8955             case 0:  assign(t5, mkexpr(t0)); break;
8956             case 1:  assign(t5, mkexpr(t1)); break;
8957             case 2:  assign(t5, mkexpr(t2)); break;
8958             case 3:  assign(t5, mkexpr(t3)); break;
8959             default: vassert(0); /*NOTREACHED*/
8960          }
8961          putIReg(4, gregOfRM(modrm), unop(Iop_16Uto32, mkexpr(t5)));
8962          DIP("pextrw $%d,%s,%s\n",
8963              (Int)insn[3], nameMMXReg(eregOfRM(modrm)),
8964                            nameIReg(4,gregOfRM(modrm)));
8965          delta += 4;
8966          goto decode_success;
8967       } 
8968       /* else fall through */
8969    }
8970
8971    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
8972    /* 0F C4 = PINSRW -- get 16 bits from E(mem or low half ireg) and
8973       put it into the specified lane of mmx(G). */
8974    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xC4) {
8975       /* Use t0 .. t3 to hold the 4 original 16-bit lanes of the
8976          mmx reg.  t4 is the new lane value.  t5 is the original
8977          mmx value. t6 is the new mmx value. */
8978       Int lane;
8979       t4 = newTemp(Ity_I16);
8980       t5 = newTemp(Ity_I64);
8981       t6 = newTemp(Ity_I64);
8982       modrm = insn[2];
8983       do_MMX_preamble();
8984
8985       assign(t5, getMMXReg(gregOfRM(modrm)));
8986       breakup64to16s( t5, &t3, &t2, &t1, &t0 );
8987
8988       if (epartIsReg(modrm)) {
8989          assign(t4, getIReg(2, eregOfRM(modrm)));
8990          delta += 3+1;
8991          lane = insn[3+1-1];
8992          DIP("pinsrw $%d,%s,%s\n", (Int)lane, 
8993                                    nameIReg(2,eregOfRM(modrm)),
8994                                    nameMMXReg(gregOfRM(modrm)));
8995       } else {
8996          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
8997          delta += 3+alen;
8998          lane = insn[3+alen-1];
8999          assign(t4, loadLE(Ity_I16, mkexpr(addr)));
9000          DIP("pinsrw $%d,%s,%s\n", (Int)lane, 
9001                                    dis_buf,
9002                                    nameMMXReg(gregOfRM(modrm)));
9003       }
9004
9005       switch (lane & 3) {
9006          case 0:  assign(t6, mk64from16s(t3,t2,t1,t4)); break;
9007          case 1:  assign(t6, mk64from16s(t3,t2,t4,t0)); break;
9008          case 2:  assign(t6, mk64from16s(t3,t4,t1,t0)); break;
9009          case 3:  assign(t6, mk64from16s(t4,t2,t1,t0)); break;
9010          default: vassert(0); /*NOTREACHED*/
9011       }
9012       putMMXReg(gregOfRM(modrm), mkexpr(t6));
9013       goto decode_success;
9014    }
9015
9016    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
9017    /* 0F EE = PMAXSW -- 16x4 signed max */
9018    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xEE) {
9019       do_MMX_preamble();
9020       delta = dis_MMXop_regmem_to_reg ( 
9021                 sorb, delta+2, insn[1], "pmaxsw", False );
9022       goto decode_success;
9023    }
9024
9025    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
9026    /* 0F DE = PMAXUB -- 8x8 unsigned max */
9027    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xDE) {
9028       do_MMX_preamble();
9029       delta = dis_MMXop_regmem_to_reg ( 
9030                 sorb, delta+2, insn[1], "pmaxub", False );
9031       goto decode_success;
9032    }
9033
9034    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
9035    /* 0F EA = PMINSW -- 16x4 signed min */
9036    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xEA) {
9037       do_MMX_preamble();
9038       delta = dis_MMXop_regmem_to_reg ( 
9039                 sorb, delta+2, insn[1], "pminsw", False );
9040       goto decode_success;
9041    }
9042
9043    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
9044    /* 0F DA = PMINUB -- 8x8 unsigned min */
9045    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xDA) {
9046       do_MMX_preamble();
9047       delta = dis_MMXop_regmem_to_reg ( 
9048                 sorb, delta+2, insn[1], "pminub", False );
9049       goto decode_success;
9050    }
9051
9052    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
9053    /* 0F D7 = PMOVMSKB -- extract sign bits from each of 8 lanes in
9054       mmx(G), turn them into a byte, and put zero-extend of it in
9055       ireg(G). */
9056    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xD7) {
9057       modrm = insn[2];
9058       if (epartIsReg(modrm)) {
9059          do_MMX_preamble();
9060          t0 = newTemp(Ity_I64);
9061          t1 = newTemp(Ity_I32);
9062          assign(t0, getMMXReg(eregOfRM(modrm)));
9063          assign(t1, mkIRExprCCall(
9064                        Ity_I32, 0/*regparms*/, 
9065                        "x86g_calculate_mmx_pmovmskb",
9066                        &x86g_calculate_mmx_pmovmskb,
9067                        mkIRExprVec_1(mkexpr(t0))));
9068          putIReg(4, gregOfRM(modrm), mkexpr(t1));
9069          DIP("pmovmskb %s,%s\n", nameMMXReg(eregOfRM(modrm)),
9070                                  nameIReg(4,gregOfRM(modrm)));
9071          delta += 3;
9072          goto decode_success;
9073       } 
9074       /* else fall through */
9075    }
9076
9077    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
9078    /* 0F E4 = PMULUH -- 16x4 hi-half of unsigned widening multiply */
9079    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xE4) {
9080       do_MMX_preamble();
9081       delta = dis_MMXop_regmem_to_reg ( 
9082                 sorb, delta+2, insn[1], "pmuluh", False );
9083       goto decode_success;
9084    }
9085
9086    /* 0F 18 /0 = PREFETCHNTA -- prefetch into caches, */
9087    /* 0F 18 /1 = PREFETCH0   -- with various different hints */
9088    /* 0F 18 /2 = PREFETCH1 */
9089    /* 0F 18 /3 = PREFETCH2 */
9090    if (insn[0] == 0x0F && insn[1] == 0x18
9091        && !epartIsReg(insn[2]) 
9092        && gregOfRM(insn[2]) >= 0 && gregOfRM(insn[2]) <= 3) {
9093       HChar* hintstr = "??";
9094
9095       modrm = getIByte(delta+2);
9096       vassert(!epartIsReg(modrm));
9097
9098       addr = disAMode ( &alen, sorb, delta+2, dis_buf );
9099       delta += 2+alen;
9100
9101       switch (gregOfRM(modrm)) {
9102          case 0: hintstr = "nta"; break;
9103          case 1: hintstr = "t0"; break;
9104          case 2: hintstr = "t1"; break;
9105          case 3: hintstr = "t2"; break;
9106          default: vassert(0); /*NOTREACHED*/
9107       }
9108
9109       DIP("prefetch%s %s\n", hintstr, dis_buf);
9110       goto decode_success;
9111    }
9112
9113    /* 0F 0D /0 = PREFETCH  m8 -- 3DNow! prefetch */
9114    /* 0F 0D /1 = PREFETCHW m8 -- ditto, with some other hint */
9115    if (insn[0] == 0x0F && insn[1] == 0x0D
9116        && !epartIsReg(insn[2]) 
9117        && gregOfRM(insn[2]) >= 0 && gregOfRM(insn[2]) <= 1) {
9118       HChar* hintstr = "??";
9119
9120       modrm = getIByte(delta+2);
9121       vassert(!epartIsReg(modrm));
9122
9123       addr = disAMode ( &alen, sorb, delta+2, dis_buf );
9124       delta += 2+alen;
9125
9126       switch (gregOfRM(modrm)) {
9127          case 0: hintstr = ""; break;
9128          case 1: hintstr = "w"; break;
9129          default: vassert(0); /*NOTREACHED*/
9130       }
9131
9132       DIP("prefetch%s %s\n", hintstr, dis_buf);
9133       goto decode_success;
9134    }
9135
9136    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
9137    /* 0F F6 = PSADBW -- sum of 8Ux8 absolute differences */
9138    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xF6) {
9139       do_MMX_preamble();
9140       delta = dis_MMXop_regmem_to_reg ( 
9141                  sorb, delta+2, insn[1], "psadbw", False );
9142       goto decode_success;
9143    }
9144
9145    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
9146    /* 0F 70 = PSHUFW -- rearrange 4x16 from E(mmx or mem) to G(mmx) */
9147    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x70) {
9148       Int order;
9149       IRTemp sV, dV, s3, s2, s1, s0;
9150       s3 = s2 = s1 = s0 = IRTemp_INVALID;
9151       sV = newTemp(Ity_I64);
9152       dV = newTemp(Ity_I64);
9153       do_MMX_preamble();
9154       modrm = insn[2];
9155       if (epartIsReg(modrm)) {
9156          assign( sV, getMMXReg(eregOfRM(modrm)) );
9157          order = (Int)insn[3];
9158          delta += 2+2;
9159          DIP("pshufw $%d,%s,%s\n", order, 
9160                                    nameMMXReg(eregOfRM(modrm)),
9161                                    nameMMXReg(gregOfRM(modrm)));
9162       } else {
9163          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
9164          assign( sV, loadLE(Ity_I64, mkexpr(addr)) );
9165          order = (Int)insn[2+alen];
9166          delta += 3+alen;
9167          DIP("pshufw $%d,%s,%s\n", order, 
9168                                    dis_buf,
9169                                    nameMMXReg(gregOfRM(modrm)));
9170       }
9171       breakup64to16s( sV, &s3, &s2, &s1, &s0 );
9172
9173 #     define SEL(n) \
9174                 ((n)==0 ? s0 : ((n)==1 ? s1 : ((n)==2 ? s2 : s3)))
9175       assign(dV,
9176              mk64from16s( SEL((order>>6)&3), SEL((order>>4)&3),
9177                           SEL((order>>2)&3), SEL((order>>0)&3) )
9178       );
9179       putMMXReg(gregOfRM(modrm), mkexpr(dV));
9180 #     undef SEL
9181       goto decode_success;
9182    }
9183
9184    /* 0F 53 = RCPPS -- approx reciprocal 32Fx4 from R/M to R */
9185    if (insn[0] == 0x0F && insn[1] == 0x53) {
9186       vassert(sz == 4);
9187       delta = dis_SSE_E_to_G_unary_all( sorb, delta+2, 
9188                                         "rcpps", Iop_Recip32Fx4 );
9189       goto decode_success;
9190    }
9191
9192    /* F3 0F 53 = RCPSS -- approx reciprocal 32F0x4 from R/M to R */
9193    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x53) {
9194       vassert(sz == 4);
9195       delta = dis_SSE_E_to_G_unary_lo32( sorb, delta+3, 
9196                                          "rcpss", Iop_Recip32F0x4 );
9197       goto decode_success;
9198    }
9199
9200    /* 0F 52 = RSQRTPS -- approx reciprocal sqrt 32Fx4 from R/M to R */
9201    if (insn[0] == 0x0F && insn[1] == 0x52) {
9202       vassert(sz == 4);
9203       delta = dis_SSE_E_to_G_unary_all( sorb, delta+2, 
9204                                         "rsqrtps", Iop_RSqrt32Fx4 );
9205       goto decode_success;
9206    }
9207
9208    /* F3 0F 52 = RSQRTSS -- approx reciprocal sqrt 32F0x4 from R/M to R */
9209    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x52) {
9210       vassert(sz == 4);
9211       delta = dis_SSE_E_to_G_unary_lo32( sorb, delta+3, 
9212                                          "rsqrtss", Iop_RSqrt32F0x4 );
9213       goto decode_success;
9214    }
9215
9216    /* 0F AE /7 = SFENCE -- flush pending operations to memory */
9217    if (insn[0] == 0x0F && insn[1] == 0xAE
9218        && epartIsReg(insn[2]) && gregOfRM(insn[2]) == 7) {
9219       vassert(sz == 4);
9220       delta += 3;
9221       /* Insert a memory fence.  It's sometimes important that these
9222          are carried through to the generated code. */
9223       stmt( IRStmt_MBE(Imbe_Fence) );
9224       DIP("sfence\n");
9225       goto decode_success;
9226    }
9227
9228    /* 0F C6 /r ib = SHUFPS -- shuffle packed F32s */
9229    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xC6) {
9230       Int    select;
9231       IRTemp sV, dV;
9232       IRTemp s3, s2, s1, s0, d3, d2, d1, d0;
9233       sV = newTemp(Ity_V128);
9234       dV = newTemp(Ity_V128);
9235       s3 = s2 = s1 = s0 = d3 = d2 = d1 = d0 = IRTemp_INVALID;
9236       modrm = insn[2];
9237       assign( dV, getXMMReg(gregOfRM(modrm)) );
9238
9239       if (epartIsReg(modrm)) {
9240          assign( sV, getXMMReg(eregOfRM(modrm)) );
9241          select = (Int)insn[3];
9242          delta += 2+2;
9243          DIP("shufps $%d,%s,%s\n", select, 
9244                                    nameXMMReg(eregOfRM(modrm)),
9245                                    nameXMMReg(gregOfRM(modrm)));
9246       } else {
9247          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
9248          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
9249          select = (Int)insn[2+alen];
9250          delta += 3+alen;
9251          DIP("shufps $%d,%s,%s\n", select, 
9252                                    dis_buf,
9253                                    nameXMMReg(gregOfRM(modrm)));
9254       }
9255
9256       breakup128to32s( dV, &d3, &d2, &d1, &d0 );
9257       breakup128to32s( sV, &s3, &s2, &s1, &s0 );
9258
9259 #     define SELD(n) ((n)==0 ? d0 : ((n)==1 ? d1 : ((n)==2 ? d2 : d3)))
9260 #     define SELS(n) ((n)==0 ? s0 : ((n)==1 ? s1 : ((n)==2 ? s2 : s3)))
9261
9262       putXMMReg(
9263          gregOfRM(modrm), 
9264          mk128from32s( SELS((select>>6)&3), SELS((select>>4)&3), 
9265                        SELD((select>>2)&3), SELD((select>>0)&3) )
9266       );
9267
9268 #     undef SELD
9269 #     undef SELS
9270
9271       goto decode_success;
9272    }
9273
9274    /* 0F 51 = SQRTPS -- approx sqrt 32Fx4 from R/M to R */
9275    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x51) {
9276       delta = dis_SSE_E_to_G_unary_all( sorb, delta+2, 
9277                                         "sqrtps", Iop_Sqrt32Fx4 );
9278       goto decode_success;
9279    }
9280
9281    /* F3 0F 51 = SQRTSS -- approx sqrt 32F0x4 from R/M to R */
9282    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x51) {
9283       vassert(sz == 4);
9284       delta = dis_SSE_E_to_G_unary_lo32( sorb, delta+3, 
9285                                          "sqrtss", Iop_Sqrt32F0x4 );
9286       goto decode_success;
9287    }
9288
9289    /* 0F AE /3 = STMXCSR m32 -- store %mxcsr */
9290    if (insn[0] == 0x0F && insn[1] == 0xAE
9291        && !epartIsReg(insn[2]) && gregOfRM(insn[2]) == 3) {
9292       modrm = getIByte(delta+2);
9293       vassert(sz == 4);
9294       vassert(!epartIsReg(modrm));
9295
9296       addr = disAMode ( &alen, sorb, delta+2, dis_buf );
9297       delta += 2+alen;
9298
9299       /* Fake up a native SSE mxcsr word.  The only thing it depends
9300          on is SSEROUND[1:0], so call a clean helper to cook it up. 
9301       */
9302       /* UInt x86h_create_mxcsr ( UInt sseround ) */
9303       DIP("stmxcsr %s\n", dis_buf);
9304       storeLE( mkexpr(addr), 
9305                mkIRExprCCall(
9306                   Ity_I32, 0/*regp*/,
9307                   "x86g_create_mxcsr", &x86g_create_mxcsr, 
9308                   mkIRExprVec_1( get_sse_roundingmode() ) 
9309                ) 
9310              );
9311       goto decode_success;
9312    }
9313
9314    /* 0F 5C = SUBPS -- sub 32Fx4 from R/M to R */
9315    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x5C) {
9316       delta = dis_SSE_E_to_G_all( sorb, delta+2, "subps", Iop_Sub32Fx4 );
9317       goto decode_success;
9318    }
9319
9320    /* F3 0F 5C = SUBSS -- sub 32F0x4 from R/M to R */
9321    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x5C) {
9322       vassert(sz == 4);
9323       delta = dis_SSE_E_to_G_lo32( sorb, delta+3, "subss", Iop_Sub32F0x4 );
9324       goto decode_success;
9325    }
9326
9327    /* 0F 15 = UNPCKHPS -- unpack and interleave high part F32s */
9328    /* 0F 14 = UNPCKLPS -- unpack and interleave low part F32s */
9329    /* These just appear to be special cases of SHUFPS */
9330    if (sz == 4 && insn[0] == 0x0F && (insn[1] == 0x15 || insn[1] == 0x14)) {
9331       IRTemp sV, dV;
9332       IRTemp s3, s2, s1, s0, d3, d2, d1, d0;
9333       Bool hi = toBool(insn[1] == 0x15);
9334       sV = newTemp(Ity_V128);
9335       dV = newTemp(Ity_V128);
9336       s3 = s2 = s1 = s0 = d3 = d2 = d1 = d0 = IRTemp_INVALID;
9337       modrm = insn[2];
9338       assign( dV, getXMMReg(gregOfRM(modrm)) );
9339
9340       if (epartIsReg(modrm)) {
9341          assign( sV, getXMMReg(eregOfRM(modrm)) );
9342          delta += 2+1;
9343          DIP("unpck%sps %s,%s\n", hi ? "h" : "l",
9344                                   nameXMMReg(eregOfRM(modrm)),
9345                                   nameXMMReg(gregOfRM(modrm)));
9346       } else {
9347          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
9348          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
9349          delta += 2+alen;
9350          DIP("unpck%sps %s,%s\n", hi ? "h" : "l",
9351                                   dis_buf,
9352                                   nameXMMReg(gregOfRM(modrm)));
9353       }
9354
9355       breakup128to32s( dV, &d3, &d2, &d1, &d0 );
9356       breakup128to32s( sV, &s3, &s2, &s1, &s0 );
9357
9358       if (hi) {
9359          putXMMReg( gregOfRM(modrm), mk128from32s( s3, d3, s2, d2 ) );
9360       } else {
9361          putXMMReg( gregOfRM(modrm), mk128from32s( s1, d1, s0, d0 ) );
9362       }
9363
9364       goto decode_success;
9365    }
9366
9367    /* 0F 57 = XORPS -- G = G and E */
9368    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x57) {
9369       delta = dis_SSE_E_to_G_all( sorb, delta+2, "xorps", Iop_XorV128 );
9370       goto decode_success;
9371    }
9372
9373    /* ---------------------------------------------------- */
9374    /* --- end of the SSE decoder.                      --- */
9375    /* ---------------------------------------------------- */
9376
9377    /* ---------------------------------------------------- */
9378    /* --- start of the SSE2 decoder.                   --- */
9379    /* ---------------------------------------------------- */
9380
9381    /* Skip parts of the decoder which don't apply given the stated
9382       guest subarchitecture. */
9383    if (0 == (archinfo->hwcaps & VEX_HWCAPS_X86_SSE2))
9384       goto after_sse_decoders; /* no SSE2 capabilities */
9385
9386    insn = (UChar*)&guest_code[delta];
9387
9388    /* 66 0F 58 = ADDPD -- add 32Fx4 from R/M to R */
9389    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x58) {
9390       delta = dis_SSE_E_to_G_all( sorb, delta+2, "addpd", Iop_Add64Fx2 );
9391       goto decode_success;
9392    }
9393  
9394    /* F2 0F 58 = ADDSD -- add 64F0x2 from R/M to R */
9395    if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x58) {
9396       vassert(sz == 4);
9397       delta = dis_SSE_E_to_G_lo64( sorb, delta+3, "addsd", Iop_Add64F0x2 );
9398       goto decode_success;
9399    }
9400
9401    /* 66 0F 55 = ANDNPD -- G = (not G) and E */
9402    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x55) {
9403       delta = dis_SSE_E_to_G_all_invG( sorb, delta+2, "andnpd", Iop_AndV128 );
9404       goto decode_success;
9405    }
9406
9407    /* 66 0F 54 = ANDPD -- G = G and E */
9408    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x54) {
9409       delta = dis_SSE_E_to_G_all( sorb, delta+2, "andpd", Iop_AndV128 );
9410       goto decode_success;
9411    }
9412
9413    /* 66 0F C2 = CMPPD -- 64Fx2 comparison from R/M to R */
9414    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xC2) {
9415       delta = dis_SSEcmp_E_to_G( sorb, delta+2, "cmppd", True, 8 );
9416       goto decode_success;
9417    }
9418
9419    /* F2 0F C2 = CMPSD -- 64F0x2 comparison from R/M to R */
9420    if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0xC2) {
9421       vassert(sz == 4);
9422       delta = dis_SSEcmp_E_to_G( sorb, delta+3, "cmpsd", False, 8 );
9423       goto decode_success;
9424    }
9425
9426    /* 66 0F 2F = COMISD  -- 64F0x2 comparison G,E, and set ZCP */
9427    /* 66 0F 2E = UCOMISD -- 64F0x2 comparison G,E, and set ZCP */
9428    if (sz == 2 && insn[0] == 0x0F && (insn[1] == 0x2F || insn[1] == 0x2E)) {
9429       IRTemp argL = newTemp(Ity_F64);
9430       IRTemp argR = newTemp(Ity_F64);
9431       modrm = getIByte(delta+2);
9432       if (epartIsReg(modrm)) {
9433          assign( argR, getXMMRegLane64F( eregOfRM(modrm), 0/*lowest lane*/ ) );
9434          delta += 2+1;
9435          DIP("[u]comisd %s,%s\n", nameXMMReg(eregOfRM(modrm)),
9436                                   nameXMMReg(gregOfRM(modrm)) );
9437       } else {
9438          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
9439          assign( argR, loadLE(Ity_F64, mkexpr(addr)) );
9440          delta += 2+alen;
9441          DIP("[u]comisd %s,%s\n", dis_buf,
9442                                   nameXMMReg(gregOfRM(modrm)) );
9443       }
9444       assign( argL, getXMMRegLane64F( gregOfRM(modrm), 0/*lowest lane*/ ) );
9445
9446       stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(X86G_CC_OP_COPY) ));
9447       stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0) ));
9448       stmt( IRStmt_Put( 
9449                OFFB_CC_DEP1,
9450                binop( Iop_And32,
9451                       binop(Iop_CmpF64, mkexpr(argL), mkexpr(argR)),
9452                       mkU32(0x45)
9453           )));
9454       /* Set NDEP even though it isn't used.  This makes redundant-PUT
9455          elimination of previous stores to this field work better. */
9456       stmt( IRStmt_Put( OFFB_CC_NDEP, mkU32(0) ));
9457       goto decode_success;
9458    }
9459
9460    /* F3 0F E6 = CVTDQ2PD -- convert 2 x I32 in mem/lo half xmm to 2 x
9461       F64 in xmm(G) */
9462    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0xE6) {
9463       IRTemp arg64 = newTemp(Ity_I64);
9464       vassert(sz == 4);
9465
9466       modrm = getIByte(delta+3);
9467       if (epartIsReg(modrm)) {
9468          assign( arg64, getXMMRegLane64(eregOfRM(modrm), 0) );
9469          delta += 3+1;
9470          DIP("cvtdq2pd %s,%s\n", nameXMMReg(eregOfRM(modrm)),
9471                                  nameXMMReg(gregOfRM(modrm)));
9472       } else {
9473          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
9474          assign( arg64, loadLE(Ity_I64, mkexpr(addr)) );
9475          delta += 3+alen;
9476          DIP("cvtdq2pd %s,%s\n", dis_buf,
9477                                  nameXMMReg(gregOfRM(modrm)) );
9478       }
9479
9480       putXMMRegLane64F( 
9481          gregOfRM(modrm), 0,
9482          unop(Iop_I32StoF64, unop(Iop_64to32, mkexpr(arg64)))
9483       );
9484
9485       putXMMRegLane64F(
9486          gregOfRM(modrm), 1, 
9487          unop(Iop_I32StoF64, unop(Iop_64HIto32, mkexpr(arg64)))
9488       );
9489
9490       goto decode_success;
9491    }
9492
9493    /* 0F 5B = CVTDQ2PS -- convert 4 x I32 in mem/xmm to 4 x F32 in
9494       xmm(G) */
9495    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x5B) {
9496       IRTemp argV  = newTemp(Ity_V128);
9497       IRTemp rmode = newTemp(Ity_I32);
9498
9499       modrm = getIByte(delta+2);
9500       if (epartIsReg(modrm)) {
9501          assign( argV, getXMMReg(eregOfRM(modrm)) );
9502          delta += 2+1;
9503          DIP("cvtdq2ps %s,%s\n", nameXMMReg(eregOfRM(modrm)),
9504                                  nameXMMReg(gregOfRM(modrm)));
9505       } else {
9506          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
9507          assign( argV, loadLE(Ity_V128, mkexpr(addr)) );
9508          delta += 2+alen;
9509          DIP("cvtdq2ps %s,%s\n", dis_buf,
9510                                  nameXMMReg(gregOfRM(modrm)) );
9511       }
9512          
9513       assign( rmode, get_sse_roundingmode() );
9514       breakup128to32s( argV, &t3, &t2, &t1, &t0 );
9515
9516 #     define CVT(_t)  binop( Iop_F64toF32,                    \
9517                              mkexpr(rmode),                   \
9518                              unop(Iop_I32StoF64,mkexpr(_t)))
9519       
9520       putXMMRegLane32F( gregOfRM(modrm), 3, CVT(t3) );
9521       putXMMRegLane32F( gregOfRM(modrm), 2, CVT(t2) );
9522       putXMMRegLane32F( gregOfRM(modrm), 1, CVT(t1) );
9523       putXMMRegLane32F( gregOfRM(modrm), 0, CVT(t0) );
9524
9525 #     undef CVT
9526
9527       goto decode_success;
9528    }
9529
9530    /* F2 0F E6 = CVTPD2DQ -- convert 2 x F64 in mem/xmm to 2 x I32 in
9531       lo half xmm(G), and zero upper half */
9532    if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0xE6) {
9533       IRTemp argV  = newTemp(Ity_V128);
9534       IRTemp rmode = newTemp(Ity_I32);
9535       vassert(sz == 4);
9536
9537       modrm = getIByte(delta+3);
9538       if (epartIsReg(modrm)) {
9539          assign( argV, getXMMReg(eregOfRM(modrm)) );
9540          delta += 3+1;
9541          DIP("cvtpd2dq %s,%s\n", nameXMMReg(eregOfRM(modrm)),
9542                                  nameXMMReg(gregOfRM(modrm)));
9543       } else {
9544          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
9545          assign( argV, loadLE(Ity_V128, mkexpr(addr)) );
9546          delta += 3+alen;
9547          DIP("cvtpd2dq %s,%s\n", dis_buf,
9548                                  nameXMMReg(gregOfRM(modrm)) );
9549       }
9550          
9551       assign( rmode, get_sse_roundingmode() );
9552       t0 = newTemp(Ity_F64);
9553       t1 = newTemp(Ity_F64);
9554       assign( t0, unop(Iop_ReinterpI64asF64, 
9555                        unop(Iop_V128to64, mkexpr(argV))) );
9556       assign( t1, unop(Iop_ReinterpI64asF64, 
9557                        unop(Iop_V128HIto64, mkexpr(argV))) );
9558       
9559 #     define CVT(_t)  binop( Iop_F64toI32S,                   \
9560                              mkexpr(rmode),                   \
9561                              mkexpr(_t) )
9562       
9563       putXMMRegLane32( gregOfRM(modrm), 3, mkU32(0) );
9564       putXMMRegLane32( gregOfRM(modrm), 2, mkU32(0) );
9565       putXMMRegLane32( gregOfRM(modrm), 1, CVT(t1) );
9566       putXMMRegLane32( gregOfRM(modrm), 0, CVT(t0) );
9567
9568 #     undef CVT
9569
9570       goto decode_success;
9571    }
9572
9573    /* 66 0F 2D = CVTPD2PI -- convert 2 x F64 in mem/xmm to 2 x
9574       I32 in mmx, according to prevailing SSE rounding mode */
9575    /* 66 0F 2C = CVTTPD2PI -- convert 2 x F64 in mem/xmm to 2 x
9576       I32 in mmx, rounding towards zero */
9577    if (sz == 2 && insn[0] == 0x0F && (insn[1] == 0x2D || insn[1] == 0x2C)) {
9578       IRTemp dst64  = newTemp(Ity_I64);
9579       IRTemp rmode  = newTemp(Ity_I32);
9580       IRTemp f64lo  = newTemp(Ity_F64);
9581       IRTemp f64hi  = newTemp(Ity_F64);
9582       Bool   r2zero = toBool(insn[1] == 0x2C);
9583
9584       do_MMX_preamble();
9585       modrm = getIByte(delta+2);
9586
9587       if (epartIsReg(modrm)) {
9588          delta += 2+1;
9589          assign(f64lo, getXMMRegLane64F(eregOfRM(modrm), 0));
9590          assign(f64hi, getXMMRegLane64F(eregOfRM(modrm), 1));
9591          DIP("cvt%spd2pi %s,%s\n", r2zero ? "t" : "",
9592                                    nameXMMReg(eregOfRM(modrm)),
9593                                    nameMMXReg(gregOfRM(modrm)));
9594       } else {
9595          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
9596          assign(f64lo, loadLE(Ity_F64, mkexpr(addr)));
9597          assign(f64hi, loadLE(Ity_F64, binop( Iop_Add32, 
9598                                               mkexpr(addr), 
9599                                               mkU32(8) )));
9600          delta += 2+alen;
9601          DIP("cvt%spf2pi %s,%s\n", r2zero ? "t" : "",
9602                                    dis_buf,
9603                                    nameMMXReg(gregOfRM(modrm)));
9604       }
9605
9606       if (r2zero) {
9607          assign(rmode, mkU32((UInt)Irrm_ZERO) );
9608       } else {
9609          assign( rmode, get_sse_roundingmode() );
9610       }
9611
9612       assign( 
9613          dst64,
9614          binop( Iop_32HLto64,
9615                 binop( Iop_F64toI32S, mkexpr(rmode), mkexpr(f64hi) ),
9616                 binop( Iop_F64toI32S, mkexpr(rmode), mkexpr(f64lo) )
9617               )
9618       );
9619
9620       putMMXReg(gregOfRM(modrm), mkexpr(dst64));
9621       goto decode_success;
9622    }
9623
9624    /* 66 0F 5A = CVTPD2PS -- convert 2 x F64 in mem/xmm to 2 x F32 in
9625       lo half xmm(G), and zero upper half */
9626    /* Note, this is practically identical to CVTPD2DQ.  It would have
9627       been nicer to merge them together, but the insn[] offsets differ
9628       by one. */
9629    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x5A) {
9630       IRTemp argV  = newTemp(Ity_V128);
9631       IRTemp rmode = newTemp(Ity_I32);
9632
9633       modrm = getIByte(delta+2);
9634       if (epartIsReg(modrm)) {
9635          assign( argV, getXMMReg(eregOfRM(modrm)) );
9636          delta += 2+1;
9637          DIP("cvtpd2ps %s,%s\n", nameXMMReg(eregOfRM(modrm)),
9638                                  nameXMMReg(gregOfRM(modrm)));
9639       } else {
9640          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
9641          assign( argV, loadLE(Ity_V128, mkexpr(addr)) );
9642          delta += 2+alen;
9643          DIP("cvtpd2ps %s,%s\n", dis_buf,
9644                                  nameXMMReg(gregOfRM(modrm)) );
9645       }
9646          
9647       assign( rmode, get_sse_roundingmode() );
9648       t0 = newTemp(Ity_F64);
9649       t1 = newTemp(Ity_F64);
9650       assign( t0, unop(Iop_ReinterpI64asF64, 
9651                        unop(Iop_V128to64, mkexpr(argV))) );
9652       assign( t1, unop(Iop_ReinterpI64asF64, 
9653                        unop(Iop_V128HIto64, mkexpr(argV))) );
9654       
9655 #     define CVT(_t)  binop( Iop_F64toF32,                    \
9656                              mkexpr(rmode),                   \
9657                              mkexpr(_t) )
9658       
9659       putXMMRegLane32(  gregOfRM(modrm), 3, mkU32(0) );
9660       putXMMRegLane32(  gregOfRM(modrm), 2, mkU32(0) );
9661       putXMMRegLane32F( gregOfRM(modrm), 1, CVT(t1) );
9662       putXMMRegLane32F( gregOfRM(modrm), 0, CVT(t0) );
9663
9664 #     undef CVT
9665
9666       goto decode_success;
9667    }
9668
9669    /* 66 0F 2A = CVTPI2PD -- convert 2 x I32 in mem/mmx to 2 x F64 in
9670       xmm(G) */
9671    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x2A) {
9672       IRTemp arg64 = newTemp(Ity_I64);
9673
9674       modrm = getIByte(delta+2);
9675       if (epartIsReg(modrm)) {
9676          /* Only switch to MMX mode if the source is a MMX register.
9677             This is inconsistent with all other instructions which
9678             convert between XMM and (M64 or MMX), which always switch
9679             to MMX mode even if 64-bit operand is M64 and not MMX.  At
9680             least, that's what the Intel docs seem to me to say.
9681             Fixes #210264. */
9682          do_MMX_preamble();
9683          assign( arg64, getMMXReg(eregOfRM(modrm)) );
9684          delta += 2+1;
9685          DIP("cvtpi2pd %s,%s\n", nameMMXReg(eregOfRM(modrm)),
9686                                  nameXMMReg(gregOfRM(modrm)));
9687       } else {
9688          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
9689          assign( arg64, loadLE(Ity_I64, mkexpr(addr)) );
9690          delta += 2+alen;
9691          DIP("cvtpi2pd %s,%s\n", dis_buf,
9692                                  nameXMMReg(gregOfRM(modrm)) );
9693       }
9694
9695       putXMMRegLane64F( 
9696          gregOfRM(modrm), 0,
9697          unop(Iop_I32StoF64, unop(Iop_64to32, mkexpr(arg64)) )
9698       );
9699
9700       putXMMRegLane64F( 
9701          gregOfRM(modrm), 1,
9702          unop(Iop_I32StoF64, unop(Iop_64HIto32, mkexpr(arg64)) )
9703       );
9704
9705       goto decode_success;
9706    }
9707
9708    /* 66 0F 5B = CVTPS2DQ -- convert 4 x F32 in mem/xmm to 4 x I32 in
9709       xmm(G) */
9710    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x5B) {
9711       IRTemp argV  = newTemp(Ity_V128);
9712       IRTemp rmode = newTemp(Ity_I32);
9713
9714       modrm = getIByte(delta+2);
9715       if (epartIsReg(modrm)) {
9716          assign( argV, getXMMReg(eregOfRM(modrm)) );
9717          delta += 2+1;
9718          DIP("cvtps2dq %s,%s\n", nameXMMReg(eregOfRM(modrm)),
9719                                  nameXMMReg(gregOfRM(modrm)));
9720       } else {
9721          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
9722          assign( argV, loadLE(Ity_V128, mkexpr(addr)) );
9723          delta += 2+alen;
9724          DIP("cvtps2dq %s,%s\n", dis_buf,
9725                                  nameXMMReg(gregOfRM(modrm)) );
9726       }
9727          
9728       assign( rmode, get_sse_roundingmode() );
9729       breakup128to32s( argV, &t3, &t2, &t1, &t0 );
9730
9731       /* This is less than ideal.  If it turns out to be a performance
9732          bottleneck it can be improved. */
9733 #     define CVT(_t)                            \
9734         binop( Iop_F64toI32S,                   \
9735                mkexpr(rmode),                   \
9736                unop( Iop_F32toF64,              \
9737                      unop( Iop_ReinterpI32asF32, mkexpr(_t))) )
9738       
9739       putXMMRegLane32( gregOfRM(modrm), 3, CVT(t3) );
9740       putXMMRegLane32( gregOfRM(modrm), 2, CVT(t2) );
9741       putXMMRegLane32( gregOfRM(modrm), 1, CVT(t1) );
9742       putXMMRegLane32( gregOfRM(modrm), 0, CVT(t0) );
9743
9744 #     undef CVT
9745
9746       goto decode_success;
9747    }
9748
9749    /* 0F 5A = CVTPS2PD -- convert 2 x F32 in low half mem/xmm to 2 x
9750       F64 in xmm(G). */
9751    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x5A) {
9752       IRTemp f32lo = newTemp(Ity_F32);
9753       IRTemp f32hi = newTemp(Ity_F32);
9754
9755       modrm = getIByte(delta+2);
9756       if (epartIsReg(modrm)) {
9757          assign( f32lo, getXMMRegLane32F(eregOfRM(modrm), 0) );
9758          assign( f32hi, getXMMRegLane32F(eregOfRM(modrm), 1) );
9759          delta += 2+1;
9760          DIP("cvtps2pd %s,%s\n", nameXMMReg(eregOfRM(modrm)),
9761                                  nameXMMReg(gregOfRM(modrm)));
9762       } else {
9763          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
9764          assign( f32lo, loadLE(Ity_F32, mkexpr(addr)) );
9765          assign( f32hi, loadLE(Ity_F32, 
9766                                binop(Iop_Add32,mkexpr(addr),mkU32(4))) );
9767          delta += 2+alen;
9768          DIP("cvtps2pd %s,%s\n", dis_buf,
9769                                  nameXMMReg(gregOfRM(modrm)) );
9770       }
9771
9772       putXMMRegLane64F( gregOfRM(modrm), 1,
9773                         unop(Iop_F32toF64, mkexpr(f32hi)) );
9774       putXMMRegLane64F( gregOfRM(modrm), 0,
9775                         unop(Iop_F32toF64, mkexpr(f32lo)) );
9776
9777       goto decode_success;
9778    }
9779
9780    /* F2 0F 2D = CVTSD2SI -- convert F64 in mem/low half xmm to
9781       I32 in ireg, according to prevailing SSE rounding mode */
9782    /* F2 0F 2C = CVTTSD2SI -- convert F64 in mem/low half xmm to
9783       I32 in ireg, rounding towards zero */
9784    if (insn[0] == 0xF2 && insn[1] == 0x0F 
9785        && (insn[2] == 0x2D || insn[2] == 0x2C)) {
9786       IRTemp rmode = newTemp(Ity_I32);
9787       IRTemp f64lo = newTemp(Ity_F64);
9788       Bool   r2zero = toBool(insn[2] == 0x2C);
9789       vassert(sz == 4);
9790
9791       modrm = getIByte(delta+3);
9792       if (epartIsReg(modrm)) {
9793          delta += 3+1;
9794          assign(f64lo, getXMMRegLane64F(eregOfRM(modrm), 0));
9795          DIP("cvt%ssd2si %s,%s\n", r2zero ? "t" : "",
9796                                    nameXMMReg(eregOfRM(modrm)),
9797                                    nameIReg(4, gregOfRM(modrm)));
9798       } else {
9799          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
9800          assign(f64lo, loadLE(Ity_F64, mkexpr(addr)));
9801          delta += 3+alen;
9802          DIP("cvt%ssd2si %s,%s\n", r2zero ? "t" : "",
9803                                    dis_buf,
9804                                    nameIReg(4, gregOfRM(modrm)));
9805       }
9806
9807       if (r2zero) {
9808          assign( rmode, mkU32((UInt)Irrm_ZERO) );
9809       } else {
9810          assign( rmode, get_sse_roundingmode() );
9811       }
9812
9813       putIReg(4, gregOfRM(modrm),
9814                  binop( Iop_F64toI32S, mkexpr(rmode), mkexpr(f64lo)) );
9815
9816       goto decode_success;
9817    }
9818
9819    /* F2 0F 5A = CVTSD2SS -- convert F64 in mem/low half xmm to F32 in
9820       low 1/4 xmm(G), according to prevailing SSE rounding mode */
9821    if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x5A) {
9822       IRTemp rmode = newTemp(Ity_I32);
9823       IRTemp f64lo = newTemp(Ity_F64);
9824       vassert(sz == 4);
9825
9826       modrm = getIByte(delta+3);
9827       if (epartIsReg(modrm)) {
9828          delta += 3+1;
9829          assign(f64lo, getXMMRegLane64F(eregOfRM(modrm), 0));
9830          DIP("cvtsd2ss %s,%s\n", nameXMMReg(eregOfRM(modrm)),
9831                                  nameXMMReg(gregOfRM(modrm)));
9832       } else {
9833          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
9834          assign(f64lo, loadLE(Ity_F64, mkexpr(addr)));
9835          delta += 3+alen;
9836          DIP("cvtsd2ss %s,%s\n", dis_buf,
9837                                  nameXMMReg(gregOfRM(modrm)));
9838       }
9839
9840       assign( rmode, get_sse_roundingmode() );
9841       putXMMRegLane32F( 
9842          gregOfRM(modrm), 0, 
9843          binop( Iop_F64toF32, mkexpr(rmode), mkexpr(f64lo) )
9844       );
9845
9846       goto decode_success;
9847    }
9848
9849    /* F2 0F 2A = CVTSI2SD -- convert I32 in mem/ireg to F64 in low
9850       half xmm */
9851    if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x2A) {
9852       IRTemp arg32 = newTemp(Ity_I32);
9853       vassert(sz == 4);
9854
9855       modrm = getIByte(delta+3);
9856       if (epartIsReg(modrm)) {
9857          assign( arg32, getIReg(4, eregOfRM(modrm)) );
9858          delta += 3+1;
9859          DIP("cvtsi2sd %s,%s\n", nameIReg(4, eregOfRM(modrm)),
9860                                  nameXMMReg(gregOfRM(modrm)));
9861       } else {
9862          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
9863          assign( arg32, loadLE(Ity_I32, mkexpr(addr)) );
9864          delta += 3+alen;
9865          DIP("cvtsi2sd %s,%s\n", dis_buf,
9866                                  nameXMMReg(gregOfRM(modrm)) );
9867       }
9868
9869       putXMMRegLane64F( 
9870          gregOfRM(modrm), 0,
9871          unop(Iop_I32StoF64, mkexpr(arg32)) );
9872
9873       goto decode_success;
9874    }
9875
9876    /* F3 0F 5A = CVTSS2SD -- convert F32 in mem/low 1/4 xmm to F64 in
9877       low half xmm(G) */
9878    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x5A) {
9879       IRTemp f32lo = newTemp(Ity_F32);
9880       vassert(sz == 4);
9881
9882       modrm = getIByte(delta+3);
9883       if (epartIsReg(modrm)) {
9884          delta += 3+1;
9885          assign(f32lo, getXMMRegLane32F(eregOfRM(modrm), 0));
9886          DIP("cvtss2sd %s,%s\n", nameXMMReg(eregOfRM(modrm)),
9887                                  nameXMMReg(gregOfRM(modrm)));
9888       } else {
9889          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
9890          assign(f32lo, loadLE(Ity_F32, mkexpr(addr)));
9891          delta += 3+alen;
9892          DIP("cvtss2sd %s,%s\n", dis_buf,
9893                                  nameXMMReg(gregOfRM(modrm)));
9894       }
9895
9896       putXMMRegLane64F( gregOfRM(modrm), 0, 
9897                         unop( Iop_F32toF64, mkexpr(f32lo) ) );
9898
9899       goto decode_success;
9900    }
9901
9902    /* 66 0F E6 = CVTTPD2DQ -- convert 2 x F64 in mem/xmm to 2 x I32 in
9903       lo half xmm(G), and zero upper half, rounding towards zero */
9904    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xE6) {
9905       IRTemp argV  = newTemp(Ity_V128);
9906       IRTemp rmode = newTemp(Ity_I32);
9907
9908       modrm = getIByte(delta+2);
9909       if (epartIsReg(modrm)) {
9910          assign( argV, getXMMReg(eregOfRM(modrm)) );
9911          delta += 2+1;
9912          DIP("cvttpd2dq %s,%s\n", nameXMMReg(eregOfRM(modrm)),
9913                                   nameXMMReg(gregOfRM(modrm)));
9914       } else {
9915          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
9916          assign( argV, loadLE(Ity_V128, mkexpr(addr)) );
9917          delta += 2+alen;
9918          DIP("cvttpd2dq %s,%s\n", dis_buf,
9919                                   nameXMMReg(gregOfRM(modrm)) );
9920       }
9921
9922       assign( rmode, mkU32((UInt)Irrm_ZERO) );
9923
9924       t0 = newTemp(Ity_F64);
9925       t1 = newTemp(Ity_F64);
9926       assign( t0, unop(Iop_ReinterpI64asF64, 
9927                        unop(Iop_V128to64, mkexpr(argV))) );
9928       assign( t1, unop(Iop_ReinterpI64asF64, 
9929                        unop(Iop_V128HIto64, mkexpr(argV))) );
9930       
9931 #     define CVT(_t)  binop( Iop_F64toI32S,                   \
9932                              mkexpr(rmode),                   \
9933                              mkexpr(_t) )
9934       
9935       putXMMRegLane32( gregOfRM(modrm), 3, mkU32(0) );
9936       putXMMRegLane32( gregOfRM(modrm), 2, mkU32(0) );
9937       putXMMRegLane32( gregOfRM(modrm), 1, CVT(t1) );
9938       putXMMRegLane32( gregOfRM(modrm), 0, CVT(t0) );
9939
9940 #     undef CVT
9941
9942       goto decode_success;
9943    }
9944
9945    /* F3 0F 5B = CVTTPS2DQ -- convert 4 x F32 in mem/xmm to 4 x I32 in
9946       xmm(G), rounding towards zero */
9947    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x5B) {
9948       IRTemp argV  = newTemp(Ity_V128);
9949       IRTemp rmode = newTemp(Ity_I32);
9950       vassert(sz == 4);
9951
9952       modrm = getIByte(delta+3);
9953       if (epartIsReg(modrm)) {
9954          assign( argV, getXMMReg(eregOfRM(modrm)) );
9955          delta += 3+1;
9956          DIP("cvttps2dq %s,%s\n", nameXMMReg(eregOfRM(modrm)),
9957                                   nameXMMReg(gregOfRM(modrm)));
9958       } else {
9959          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
9960          assign( argV, loadLE(Ity_V128, mkexpr(addr)) );
9961          delta += 3+alen;
9962          DIP("cvttps2dq %s,%s\n", dis_buf,
9963                                   nameXMMReg(gregOfRM(modrm)) );
9964       }
9965          
9966       assign( rmode, mkU32((UInt)Irrm_ZERO) );
9967       breakup128to32s( argV, &t3, &t2, &t1, &t0 );
9968
9969       /* This is less than ideal.  If it turns out to be a performance
9970          bottleneck it can be improved. */
9971 #     define CVT(_t)                            \
9972         binop( Iop_F64toI32S,                   \
9973                mkexpr(rmode),                   \
9974                unop( Iop_F32toF64,              \
9975                      unop( Iop_ReinterpI32asF32, mkexpr(_t))) )
9976       
9977       putXMMRegLane32( gregOfRM(modrm), 3, CVT(t3) );
9978       putXMMRegLane32( gregOfRM(modrm), 2, CVT(t2) );
9979       putXMMRegLane32( gregOfRM(modrm), 1, CVT(t1) );
9980       putXMMRegLane32( gregOfRM(modrm), 0, CVT(t0) );
9981
9982 #     undef CVT
9983
9984       goto decode_success;
9985    }
9986
9987    /* 66 0F 5E = DIVPD -- div 64Fx2 from R/M to R */
9988    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x5E) {
9989       delta = dis_SSE_E_to_G_all( sorb, delta+2, "divpd", Iop_Div64Fx2 );
9990       goto decode_success;
9991    }
9992
9993    /* F2 0F 5E = DIVSD -- div 64F0x2 from R/M to R */
9994    if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x5E) {
9995       vassert(sz == 4);
9996       delta = dis_SSE_E_to_G_lo64( sorb, delta+3, "divsd", Iop_Div64F0x2 );
9997       goto decode_success;
9998    }
9999
10000    /* 0F AE /5 = LFENCE -- flush pending operations to memory */
10001    /* 0F AE /6 = MFENCE -- flush pending operations to memory */
10002    if (insn[0] == 0x0F && insn[1] == 0xAE
10003        && epartIsReg(insn[2]) 
10004        && (gregOfRM(insn[2]) == 5 || gregOfRM(insn[2]) == 6)) {
10005       vassert(sz == 4);
10006       delta += 3;
10007       /* Insert a memory fence.  It's sometimes important that these
10008          are carried through to the generated code. */
10009       stmt( IRStmt_MBE(Imbe_Fence) );
10010       DIP("%sfence\n", gregOfRM(insn[2])==5 ? "l" : "m");
10011       goto decode_success;
10012    }
10013
10014    /* 66 0F 5F = MAXPD -- max 64Fx2 from R/M to R */
10015    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x5F) {
10016       delta = dis_SSE_E_to_G_all( sorb, delta+2, "maxpd", Iop_Max64Fx2 );
10017       goto decode_success;
10018    }
10019
10020    /* F2 0F 5F = MAXSD -- max 64F0x2 from R/M to R */
10021    if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x5F) {
10022       vassert(sz == 4);
10023       delta = dis_SSE_E_to_G_lo64( sorb, delta+3, "maxsd", Iop_Max64F0x2 );
10024       goto decode_success;
10025    }
10026
10027    /* 66 0F 5D = MINPD -- min 64Fx2 from R/M to R */
10028    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x5D) {
10029       delta = dis_SSE_E_to_G_all( sorb, delta+2, "minpd", Iop_Min64Fx2 );
10030       goto decode_success;
10031    }
10032
10033    /* F2 0F 5D = MINSD -- min 64F0x2 from R/M to R */
10034    if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x5D) {
10035       vassert(sz == 4);
10036       delta = dis_SSE_E_to_G_lo64( sorb, delta+3, "minsd", Iop_Min64F0x2 );
10037       goto decode_success;
10038    }
10039
10040    /* 66 0F 28 = MOVAPD -- move from E (mem or xmm) to G (xmm). */
10041    /* 66 0F 10 = MOVUPD -- move from E (mem or xmm) to G (xmm). */
10042    /* 66 0F 6F = MOVDQA -- move from E (mem or xmm) to G (xmm). */
10043    if (sz == 2 && insn[0] == 0x0F 
10044        && (insn[1] == 0x28 || insn[1] == 0x10 || insn[1] == 0x6F)) {
10045       HChar* wot = insn[1]==0x28 ? "apd" :
10046                    insn[1]==0x10 ? "upd" : "dqa";
10047       modrm = getIByte(delta+2);
10048       if (epartIsReg(modrm)) {
10049          putXMMReg( gregOfRM(modrm), 
10050                     getXMMReg( eregOfRM(modrm) ));
10051          DIP("mov%s %s,%s\n", wot, nameXMMReg(eregOfRM(modrm)),
10052                                    nameXMMReg(gregOfRM(modrm)));
10053          delta += 2+1;
10054       } else {
10055          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
10056          if (insn[1] == 0x28/*movapd*/ || insn[1] == 0x6F/*movdqa*/)
10057             gen_SEGV_if_not_16_aligned( addr );
10058          putXMMReg( gregOfRM(modrm), 
10059                     loadLE(Ity_V128, mkexpr(addr)) );
10060          DIP("mov%s %s,%s\n", wot, dis_buf,
10061                                    nameXMMReg(gregOfRM(modrm)));
10062          delta += 2+alen;
10063       }
10064       goto decode_success;
10065    }
10066
10067    /* 66 0F 29 = MOVAPD -- move from G (xmm) to E (mem or xmm). */
10068    /* 66 0F 11 = MOVUPD -- move from G (xmm) to E (mem or xmm). */
10069    if (sz == 2 && insn[0] == 0x0F 
10070        && (insn[1] == 0x29 || insn[1] == 0x11)) {
10071       HChar* wot = insn[1]==0x29 ? "apd" : "upd";
10072       modrm = getIByte(delta+2);
10073       if (epartIsReg(modrm)) {
10074          /* fall through; awaiting test case */
10075       } else {
10076          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
10077          if (insn[1] == 0x29/*movapd*/)
10078             gen_SEGV_if_not_16_aligned( addr );
10079          storeLE( mkexpr(addr), getXMMReg(gregOfRM(modrm)) );
10080          DIP("mov%s %s,%s\n", wot, nameXMMReg(gregOfRM(modrm)),
10081                                    dis_buf );
10082          delta += 2+alen;
10083          goto decode_success;
10084       }
10085    }
10086
10087    /* 66 0F 6E = MOVD from r/m32 to xmm, zeroing high 3/4 of xmm. */
10088    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x6E) {
10089       modrm = getIByte(delta+2);
10090       if (epartIsReg(modrm)) {
10091          delta += 2+1;
10092          putXMMReg(
10093             gregOfRM(modrm),
10094             unop( Iop_32UtoV128, getIReg(4, eregOfRM(modrm)) ) 
10095          );
10096          DIP("movd %s, %s\n", 
10097              nameIReg(4,eregOfRM(modrm)), nameXMMReg(gregOfRM(modrm)));
10098       } else {
10099          addr = disAMode( &alen, sorb, delta+2, dis_buf );
10100          delta += 2+alen;
10101          putXMMReg(
10102             gregOfRM(modrm),
10103             unop( Iop_32UtoV128,loadLE(Ity_I32, mkexpr(addr)) ) 
10104          );
10105          DIP("movd %s, %s\n", dis_buf, nameXMMReg(gregOfRM(modrm)));
10106       }
10107       goto decode_success;
10108    }
10109
10110    /* 66 0F 7E = MOVD from xmm low 1/4 to r/m32. */
10111    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x7E) {
10112       modrm = getIByte(delta+2);
10113       if (epartIsReg(modrm)) {
10114          delta += 2+1;
10115          putIReg( 4, eregOfRM(modrm),
10116                   getXMMRegLane32(gregOfRM(modrm), 0) );
10117          DIP("movd %s, %s\n", 
10118              nameXMMReg(gregOfRM(modrm)), nameIReg(4,eregOfRM(modrm)));
10119       } else {
10120          addr = disAMode( &alen, sorb, delta+2, dis_buf );
10121          delta += 2+alen;
10122          storeLE( mkexpr(addr),
10123                   getXMMRegLane32(gregOfRM(modrm), 0) );
10124          DIP("movd %s, %s\n", nameXMMReg(gregOfRM(modrm)), dis_buf);
10125       }
10126       goto decode_success;
10127    }
10128
10129    /* 66 0F 7F = MOVDQA -- move from G (xmm) to E (mem or xmm). */
10130    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x7F) {
10131       modrm = getIByte(delta+2);
10132       if (epartIsReg(modrm)) {
10133          delta += 2+1;
10134          putXMMReg( eregOfRM(modrm),
10135                     getXMMReg(gregOfRM(modrm)) );
10136          DIP("movdqa %s, %s\n", nameXMMReg(gregOfRM(modrm)), 
10137                                 nameXMMReg(eregOfRM(modrm)));
10138       } else {
10139          addr = disAMode( &alen, sorb, delta+2, dis_buf );
10140          delta += 2+alen;
10141          gen_SEGV_if_not_16_aligned( addr );
10142          storeLE( mkexpr(addr), getXMMReg(gregOfRM(modrm)) );
10143          DIP("movdqa %s, %s\n", nameXMMReg(gregOfRM(modrm)), dis_buf);
10144       }
10145       goto decode_success;
10146    }
10147
10148    /* F3 0F 6F = MOVDQU -- move from E (mem or xmm) to G (xmm). */
10149    /* Unfortunately can't simply use the MOVDQA case since the
10150       prefix lengths are different (66 vs F3) */
10151    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x6F) {
10152       vassert(sz == 4);
10153       modrm = getIByte(delta+3);
10154       if (epartIsReg(modrm)) {
10155          putXMMReg( gregOfRM(modrm), 
10156                     getXMMReg( eregOfRM(modrm) ));
10157          DIP("movdqu %s,%s\n", nameXMMReg(eregOfRM(modrm)),
10158                                nameXMMReg(gregOfRM(modrm)));
10159          delta += 3+1;
10160       } else {
10161          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
10162          putXMMReg( gregOfRM(modrm), 
10163                     loadLE(Ity_V128, mkexpr(addr)) );
10164          DIP("movdqu %s,%s\n", dis_buf,
10165                                nameXMMReg(gregOfRM(modrm)));
10166          delta += 3+alen;
10167       }
10168       goto decode_success;
10169    }
10170
10171    /* F3 0F 7F = MOVDQU -- move from G (xmm) to E (mem or xmm). */
10172    /* Unfortunately can't simply use the MOVDQA case since the
10173       prefix lengths are different (66 vs F3) */
10174    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x7F) {
10175       vassert(sz == 4);
10176       modrm = getIByte(delta+3);
10177       if (epartIsReg(modrm)) {
10178          delta += 3+1;
10179          putXMMReg( eregOfRM(modrm),
10180                     getXMMReg(gregOfRM(modrm)) );
10181          DIP("movdqu %s, %s\n", nameXMMReg(gregOfRM(modrm)), 
10182                                 nameXMMReg(eregOfRM(modrm)));
10183       } else {
10184          addr = disAMode( &alen, sorb, delta+3, dis_buf );
10185          delta += 3+alen;
10186          storeLE( mkexpr(addr), getXMMReg(gregOfRM(modrm)) );
10187          DIP("movdqu %s, %s\n", nameXMMReg(gregOfRM(modrm)), dis_buf);
10188       }
10189       goto decode_success;
10190    }
10191
10192    /* F2 0F D6 = MOVDQ2Q -- move from E (lo half xmm, not mem) to G (mmx). */
10193    if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0xD6) {
10194       vassert(sz == 4);
10195       modrm = getIByte(delta+3);
10196       if (epartIsReg(modrm)) {
10197          do_MMX_preamble();
10198          putMMXReg( gregOfRM(modrm), 
10199                     getXMMRegLane64( eregOfRM(modrm), 0 ));
10200          DIP("movdq2q %s,%s\n", nameXMMReg(eregOfRM(modrm)),
10201                                 nameMMXReg(gregOfRM(modrm)));
10202          delta += 3+1;
10203          goto decode_success;
10204       } else {
10205          /* fall through, apparently no mem case for this insn */
10206       }
10207    }
10208
10209    /* 66 0F 16 = MOVHPD -- move from mem to high half of XMM. */
10210    /* These seems identical to MOVHPS.  This instruction encoding is
10211       completely crazy. */
10212    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x16) {
10213       modrm = getIByte(delta+2);
10214       if (epartIsReg(modrm)) {
10215          /* fall through; apparently reg-reg is not possible */
10216       } else {
10217          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
10218          delta += 2+alen;
10219          putXMMRegLane64( gregOfRM(modrm), 1/*upper lane*/,
10220                           loadLE(Ity_I64, mkexpr(addr)) );
10221          DIP("movhpd %s,%s\n", dis_buf, 
10222                                nameXMMReg( gregOfRM(modrm) ));
10223          goto decode_success;
10224       }
10225    }
10226
10227    /* 66 0F 17 = MOVHPD -- move from high half of XMM to mem. */
10228    /* Again, this seems identical to MOVHPS. */
10229    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x17) {
10230       if (!epartIsReg(insn[2])) {
10231          delta += 2;
10232          addr = disAMode ( &alen, sorb, delta, dis_buf );
10233          delta += alen;
10234          storeLE( mkexpr(addr), 
10235                   getXMMRegLane64( gregOfRM(insn[2]),
10236                                    1/*upper lane*/ ) );
10237          DIP("movhpd %s,%s\n", nameXMMReg( gregOfRM(insn[2]) ),
10238                                dis_buf);
10239          goto decode_success;
10240       }
10241       /* else fall through */
10242    }
10243
10244    /* 66 0F 12 = MOVLPD -- move from mem to low half of XMM. */
10245    /* Identical to MOVLPS ? */
10246    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x12) {
10247       modrm = getIByte(delta+2);
10248       if (epartIsReg(modrm)) {
10249          /* fall through; apparently reg-reg is not possible */
10250       } else {
10251          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
10252          delta += 2+alen;
10253          putXMMRegLane64( gregOfRM(modrm),  0/*lower lane*/,
10254                           loadLE(Ity_I64, mkexpr(addr)) );
10255          DIP("movlpd %s, %s\n", 
10256              dis_buf, nameXMMReg( gregOfRM(modrm) ));
10257          goto decode_success;
10258       }
10259    }
10260
10261    /* 66 0F 13 = MOVLPD -- move from low half of XMM to mem. */
10262    /* Identical to MOVLPS ? */
10263    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x13) {
10264       if (!epartIsReg(insn[2])) {
10265          delta += 2;
10266          addr = disAMode ( &alen, sorb, delta, dis_buf );
10267          delta += alen;
10268          storeLE( mkexpr(addr), 
10269                   getXMMRegLane64( gregOfRM(insn[2]), 
10270                                    0/*lower lane*/ ) );
10271          DIP("movlpd %s, %s\n", nameXMMReg( gregOfRM(insn[2]) ),
10272                                 dis_buf);
10273          goto decode_success;
10274       }
10275       /* else fall through */
10276    }
10277
10278    /* 66 0F 50 = MOVMSKPD - move 2 sign bits from 2 x F64 in xmm(E) to
10279       2 lowest bits of ireg(G) */
10280    if (insn[0] == 0x0F && insn[1] == 0x50) {
10281       modrm = getIByte(delta+2);
10282       if (sz == 2 && epartIsReg(modrm)) {
10283          Int src;
10284          t0 = newTemp(Ity_I32);
10285          t1 = newTemp(Ity_I32);
10286          delta += 2+1;
10287          src = eregOfRM(modrm);
10288          assign( t0, binop( Iop_And32,
10289                             binop(Iop_Shr32, getXMMRegLane32(src,1), mkU8(31)),
10290                             mkU32(1) ));
10291          assign( t1, binop( Iop_And32,
10292                             binop(Iop_Shr32, getXMMRegLane32(src,3), mkU8(30)),
10293                             mkU32(2) ));
10294          putIReg(4, gregOfRM(modrm),
10295                     binop(Iop_Or32, mkexpr(t0), mkexpr(t1))
10296                  );
10297          DIP("movmskpd %s,%s\n", nameXMMReg(src), 
10298                                  nameIReg(4, gregOfRM(modrm)));
10299          goto decode_success;
10300       }
10301       /* else fall through */
10302    }
10303
10304    /* 66 0F F7 = MASKMOVDQU -- store selected bytes of double quadword */
10305    if (insn[0] == 0x0F && insn[1] == 0xF7) {
10306       modrm = getIByte(delta+2);
10307       if (sz == 2 && epartIsReg(modrm)) {
10308          IRTemp regD    = newTemp(Ity_V128);
10309          IRTemp mask    = newTemp(Ity_V128);
10310          IRTemp olddata = newTemp(Ity_V128);
10311          IRTemp newdata = newTemp(Ity_V128);
10312                 addr    = newTemp(Ity_I32);
10313
10314          assign( addr, handleSegOverride( sorb, getIReg(4, R_EDI) ));
10315          assign( regD, getXMMReg( gregOfRM(modrm) ));
10316
10317          /* Unfortunately can't do the obvious thing with SarN8x16
10318             here since that can't be re-emitted as SSE2 code - no such
10319             insn. */
10320          assign( 
10321             mask, 
10322             binop(Iop_64HLtoV128,
10323                   binop(Iop_SarN8x8, 
10324                         getXMMRegLane64( eregOfRM(modrm), 1 ), 
10325                         mkU8(7) ),
10326                   binop(Iop_SarN8x8, 
10327                         getXMMRegLane64( eregOfRM(modrm), 0 ), 
10328                         mkU8(7) ) ));
10329          assign( olddata, loadLE( Ity_V128, mkexpr(addr) ));
10330          assign( newdata, 
10331                  binop(Iop_OrV128, 
10332                        binop(Iop_AndV128, 
10333                              mkexpr(regD), 
10334                              mkexpr(mask) ),
10335                        binop(Iop_AndV128, 
10336                              mkexpr(olddata),
10337                              unop(Iop_NotV128, mkexpr(mask)))) );
10338          storeLE( mkexpr(addr), mkexpr(newdata) );
10339
10340          delta += 2+1;
10341          DIP("maskmovdqu %s,%s\n", nameXMMReg( eregOfRM(modrm) ),
10342                                    nameXMMReg( gregOfRM(modrm) ) );
10343          goto decode_success;
10344       }
10345       /* else fall through */
10346    }
10347
10348    /* 66 0F E7 = MOVNTDQ -- for us, just a plain SSE store. */
10349    if (insn[0] == 0x0F && insn[1] == 0xE7) {
10350       modrm = getIByte(delta+2);
10351       if (sz == 2 && !epartIsReg(modrm)) {
10352          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
10353          gen_SEGV_if_not_16_aligned( addr );
10354          storeLE( mkexpr(addr), getXMMReg(gregOfRM(modrm)) );
10355          DIP("movntdq %s,%s\n", dis_buf,
10356                                 nameXMMReg(gregOfRM(modrm)));
10357          delta += 2+alen;
10358          goto decode_success;
10359       }
10360       /* else fall through */
10361    }
10362
10363    /* 0F C3 = MOVNTI -- for us, just a plain ireg store. */
10364    if (insn[0] == 0x0F && insn[1] == 0xC3) {
10365       vassert(sz == 4);
10366       modrm = getIByte(delta+2);
10367       if (!epartIsReg(modrm)) {
10368          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
10369          storeLE( mkexpr(addr), getIReg(4, gregOfRM(modrm)) );
10370          DIP("movnti %s,%s\n", dis_buf,
10371                                nameIReg(4, gregOfRM(modrm)));
10372          delta += 2+alen;
10373          goto decode_success;
10374       }
10375       /* else fall through */
10376    }
10377
10378    /* 66 0F D6 = MOVQ -- move 64 bits from G (lo half xmm) to E (mem
10379       or lo half xmm).  */
10380    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xD6) {
10381       modrm = getIByte(delta+2);
10382       if (epartIsReg(modrm)) {
10383          /* fall through, awaiting test case */
10384          /* dst: lo half copied, hi half zeroed */
10385       } else {
10386          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
10387          storeLE( mkexpr(addr), 
10388                   getXMMRegLane64( gregOfRM(modrm), 0 ));
10389          DIP("movq %s,%s\n", nameXMMReg(gregOfRM(modrm)), dis_buf );
10390          delta += 2+alen;
10391          goto decode_success;
10392       }
10393    }
10394
10395    /* F3 0F D6 = MOVQ2DQ -- move from E (mmx) to G (lo half xmm, zero
10396       hi half). */
10397    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0xD6) {
10398       vassert(sz == 4);
10399       modrm = getIByte(delta+3);
10400       if (epartIsReg(modrm)) {
10401          do_MMX_preamble();
10402          putXMMReg( gregOfRM(modrm), 
10403                     unop(Iop_64UtoV128, getMMXReg( eregOfRM(modrm) )) );
10404          DIP("movq2dq %s,%s\n", nameMMXReg(eregOfRM(modrm)),
10405                                 nameXMMReg(gregOfRM(modrm)));
10406          delta += 3+1;
10407          goto decode_success;
10408       } else {
10409          /* fall through, apparently no mem case for this insn */
10410       }
10411    }
10412
10413    /* F3 0F 7E = MOVQ -- move 64 bits from E (mem or lo half xmm) to
10414       G (lo half xmm).  Upper half of G is zeroed out. */
10415    /* F2 0F 10 = MOVSD -- move 64 bits from E (mem or lo half xmm) to
10416       G (lo half xmm).  If E is mem, upper half of G is zeroed out.
10417       If E is reg, upper half of G is unchanged. */
10418    if ((insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x10)
10419        || (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x7E)) {
10420       vassert(sz == 4);
10421       modrm = getIByte(delta+3);
10422       if (epartIsReg(modrm)) {
10423          putXMMRegLane64( gregOfRM(modrm), 0,
10424                           getXMMRegLane64( eregOfRM(modrm), 0 ));
10425          if (insn[0] == 0xF3/*MOVQ*/) {
10426             /* zero bits 127:64 */
10427             putXMMRegLane64( gregOfRM(modrm), 1, mkU64(0) );
10428          }
10429          DIP("movsd %s,%s\n", nameXMMReg(eregOfRM(modrm)),
10430                               nameXMMReg(gregOfRM(modrm)));
10431          delta += 3+1;
10432       } else {
10433          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
10434          /* zero bits 127:64 */
10435          putXMMRegLane64( gregOfRM(modrm), 1, mkU64(0) );
10436          /* write bits 63:0 */
10437          putXMMRegLane64( gregOfRM(modrm), 0,
10438                           loadLE(Ity_I64, mkexpr(addr)) );
10439          DIP("movsd %s,%s\n", dis_buf,
10440                               nameXMMReg(gregOfRM(modrm)));
10441          delta += 3+alen;
10442       }
10443       goto decode_success;
10444    }
10445
10446    /* F2 0F 11 = MOVSD -- move 64 bits from G (lo half xmm) to E (mem
10447       or lo half xmm). */
10448    if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x11) {
10449       vassert(sz == 4);
10450       modrm = getIByte(delta+3);
10451       if (epartIsReg(modrm)) {
10452          putXMMRegLane64( eregOfRM(modrm), 0,
10453                           getXMMRegLane64( gregOfRM(modrm), 0 ));
10454          DIP("movsd %s,%s\n", nameXMMReg(gregOfRM(modrm)),
10455                               nameXMMReg(eregOfRM(modrm)));
10456          delta += 3+1;
10457       } else {
10458          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
10459          storeLE( mkexpr(addr),
10460                   getXMMRegLane64(gregOfRM(modrm), 0) );
10461          DIP("movsd %s,%s\n", nameXMMReg(gregOfRM(modrm)),
10462                               dis_buf);
10463          delta += 3+alen;
10464       }
10465       goto decode_success;
10466    }
10467
10468    /* 66 0F 59 = MULPD -- mul 64Fx2 from R/M to R */
10469    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x59) {
10470       delta = dis_SSE_E_to_G_all( sorb, delta+2, "mulpd", Iop_Mul64Fx2 );
10471       goto decode_success;
10472    }
10473
10474    /* F2 0F 59 = MULSD -- mul 64F0x2 from R/M to R */
10475    if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x59) {
10476       vassert(sz == 4);
10477       delta = dis_SSE_E_to_G_lo64( sorb, delta+3, "mulsd", Iop_Mul64F0x2 );
10478       goto decode_success;
10479    }
10480
10481    /* 66 0F 56 = ORPD -- G = G and E */
10482    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x56) {
10483       delta = dis_SSE_E_to_G_all( sorb, delta+2, "orpd", Iop_OrV128 );
10484       goto decode_success;
10485    }
10486
10487    /* 66 0F C6 /r ib = SHUFPD -- shuffle packed F64s */
10488    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xC6) {
10489       Int    select;
10490       IRTemp sV = newTemp(Ity_V128);
10491       IRTemp dV = newTemp(Ity_V128);
10492       IRTemp s1 = newTemp(Ity_I64);
10493       IRTemp s0 = newTemp(Ity_I64);
10494       IRTemp d1 = newTemp(Ity_I64);
10495       IRTemp d0 = newTemp(Ity_I64);
10496
10497       modrm = insn[2];
10498       assign( dV, getXMMReg(gregOfRM(modrm)) );
10499
10500       if (epartIsReg(modrm)) {
10501          assign( sV, getXMMReg(eregOfRM(modrm)) );
10502          select = (Int)insn[3];
10503          delta += 2+2;
10504          DIP("shufpd $%d,%s,%s\n", select, 
10505                                    nameXMMReg(eregOfRM(modrm)),
10506                                    nameXMMReg(gregOfRM(modrm)));
10507       } else {
10508          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
10509          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
10510          select = (Int)insn[2+alen];
10511          delta += 3+alen;
10512          DIP("shufpd $%d,%s,%s\n", select, 
10513                                    dis_buf,
10514                                    nameXMMReg(gregOfRM(modrm)));
10515       }
10516
10517       assign( d1, unop(Iop_V128HIto64, mkexpr(dV)) );
10518       assign( d0, unop(Iop_V128to64,   mkexpr(dV)) );
10519       assign( s1, unop(Iop_V128HIto64, mkexpr(sV)) );
10520       assign( s0, unop(Iop_V128to64,   mkexpr(sV)) );
10521
10522 #     define SELD(n) mkexpr((n)==0 ? d0 : d1)
10523 #     define SELS(n) mkexpr((n)==0 ? s0 : s1)
10524
10525       putXMMReg(
10526          gregOfRM(modrm), 
10527          binop(Iop_64HLtoV128, SELS((select>>1)&1), SELD((select>>0)&1) )
10528       );
10529
10530 #     undef SELD
10531 #     undef SELS
10532
10533       goto decode_success;
10534    }
10535
10536    /* 66 0F 51 = SQRTPD -- approx sqrt 64Fx2 from R/M to R */
10537    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x51) {
10538       delta = dis_SSE_E_to_G_unary_all( sorb, delta+2, 
10539                                         "sqrtpd", Iop_Sqrt64Fx2 );
10540       goto decode_success;
10541    }
10542
10543    /* F2 0F 51 = SQRTSD -- approx sqrt 64F0x2 from R/M to R */
10544    if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x51) {
10545       vassert(sz == 4);
10546       delta = dis_SSE_E_to_G_unary_lo64( sorb, delta+3, 
10547                                          "sqrtsd", Iop_Sqrt64F0x2 );
10548       goto decode_success;
10549    }
10550
10551    /* 66 0F 5C = SUBPD -- sub 64Fx2 from R/M to R */
10552    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x5C) {
10553       delta = dis_SSE_E_to_G_all( sorb, delta+2, "subpd", Iop_Sub64Fx2 );
10554       goto decode_success;
10555    }
10556
10557    /* F2 0F 5C = SUBSD -- sub 64F0x2 from R/M to R */
10558    if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x5C) {
10559       vassert(sz == 4);
10560       delta = dis_SSE_E_to_G_lo64( sorb, delta+3, "subsd", Iop_Sub64F0x2 );
10561       goto decode_success;
10562    }
10563
10564    /* 66 0F 15 = UNPCKHPD -- unpack and interleave high part F64s */
10565    /* 66 0F 14 = UNPCKLPD -- unpack and interleave low part F64s */
10566    /* These just appear to be special cases of SHUFPS */
10567    if (sz == 2 && insn[0] == 0x0F && (insn[1] == 0x15 || insn[1] == 0x14)) {
10568       IRTemp s1 = newTemp(Ity_I64);
10569       IRTemp s0 = newTemp(Ity_I64);
10570       IRTemp d1 = newTemp(Ity_I64);
10571       IRTemp d0 = newTemp(Ity_I64);
10572       IRTemp sV = newTemp(Ity_V128);
10573       IRTemp dV = newTemp(Ity_V128);
10574       Bool   hi = toBool(insn[1] == 0x15);
10575
10576       modrm = insn[2];
10577       assign( dV, getXMMReg(gregOfRM(modrm)) );
10578
10579       if (epartIsReg(modrm)) {
10580          assign( sV, getXMMReg(eregOfRM(modrm)) );
10581          delta += 2+1;
10582          DIP("unpck%sps %s,%s\n", hi ? "h" : "l",
10583                                   nameXMMReg(eregOfRM(modrm)),
10584                                   nameXMMReg(gregOfRM(modrm)));
10585       } else {
10586          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
10587          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
10588          delta += 2+alen;
10589          DIP("unpck%sps %s,%s\n", hi ? "h" : "l",
10590                                   dis_buf,
10591                                   nameXMMReg(gregOfRM(modrm)));
10592       }
10593
10594       assign( d1, unop(Iop_V128HIto64, mkexpr(dV)) );
10595       assign( d0, unop(Iop_V128to64,   mkexpr(dV)) );
10596       assign( s1, unop(Iop_V128HIto64, mkexpr(sV)) );
10597       assign( s0, unop(Iop_V128to64,   mkexpr(sV)) );
10598
10599       if (hi) {
10600          putXMMReg( gregOfRM(modrm), 
10601                     binop(Iop_64HLtoV128, mkexpr(s1), mkexpr(d1)) );
10602       } else {
10603          putXMMReg( gregOfRM(modrm), 
10604                     binop(Iop_64HLtoV128, mkexpr(s0), mkexpr(d0)) );
10605       }
10606
10607       goto decode_success;
10608    }
10609
10610    /* 66 0F 57 = XORPD -- G = G and E */
10611    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x57) {
10612       delta = dis_SSE_E_to_G_all( sorb, delta+2, "xorpd", Iop_XorV128 );
10613       goto decode_success;
10614    }
10615
10616    /* 66 0F 6B = PACKSSDW */
10617    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x6B) {
10618       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10619                                  "packssdw", Iop_QNarrow32Sx4, True );
10620       goto decode_success;
10621    }
10622
10623    /* 66 0F 63 = PACKSSWB */
10624    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x63) {
10625       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10626                                  "packsswb", Iop_QNarrow16Sx8, True );
10627       goto decode_success;
10628    }
10629
10630    /* 66 0F 67 = PACKUSWB */
10631    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x67) {
10632       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10633                                  "packuswb", Iop_QNarrow16Ux8, True );
10634       goto decode_success;
10635    }
10636
10637    /* 66 0F FC = PADDB */
10638    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xFC) {
10639       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10640                                  "paddb", Iop_Add8x16, False );
10641       goto decode_success;
10642    }
10643
10644    /* 66 0F FE = PADDD */
10645    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xFE) {
10646       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10647                                  "paddd", Iop_Add32x4, False );
10648       goto decode_success;
10649    }
10650
10651    /* ***--- this is an MMX class insn introduced in SSE2 ---*** */
10652    /* 0F D4 = PADDQ -- add 64x1 */
10653    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xD4) {
10654       do_MMX_preamble();
10655       delta = dis_MMXop_regmem_to_reg ( 
10656                 sorb, delta+2, insn[1], "paddq", False );
10657       goto decode_success;
10658    }
10659
10660    /* 66 0F D4 = PADDQ */
10661    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xD4) {
10662       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10663                                  "paddq", Iop_Add64x2, False );
10664       goto decode_success;
10665    }
10666
10667    /* 66 0F FD = PADDW */
10668    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xFD) {
10669       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10670                                  "paddw", Iop_Add16x8, False );
10671       goto decode_success;
10672    }
10673
10674    /* 66 0F EC = PADDSB */
10675    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xEC) {
10676       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10677                                  "paddsb", Iop_QAdd8Sx16, False );
10678       goto decode_success;
10679    }
10680
10681    /* 66 0F ED = PADDSW */
10682    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xED) {
10683       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10684                                  "paddsw", Iop_QAdd16Sx8, False );
10685       goto decode_success;
10686    }
10687
10688    /* 66 0F DC = PADDUSB */
10689    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xDC) {
10690       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10691                                  "paddusb", Iop_QAdd8Ux16, False );
10692       goto decode_success;
10693    }
10694
10695    /* 66 0F DD = PADDUSW */
10696    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xDD) {
10697       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10698                                  "paddusw", Iop_QAdd16Ux8, False );
10699       goto decode_success;
10700    }
10701
10702    /* 66 0F DB = PAND */
10703    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xDB) {
10704       delta = dis_SSE_E_to_G_all( sorb, delta+2, "pand", Iop_AndV128 );
10705       goto decode_success;
10706    }
10707
10708    /* 66 0F DF = PANDN */
10709    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xDF) {
10710       delta = dis_SSE_E_to_G_all_invG( sorb, delta+2, "pandn", Iop_AndV128 );
10711       goto decode_success;
10712    }
10713
10714    /* 66 0F E0 = PAVGB */
10715    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xE0) {
10716       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10717                                  "pavgb", Iop_Avg8Ux16, False );
10718       goto decode_success;
10719    }
10720
10721    /* 66 0F E3 = PAVGW */
10722    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xE3) {
10723       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10724                                  "pavgw", Iop_Avg16Ux8, False );
10725       goto decode_success;
10726    }
10727
10728    /* 66 0F 74 = PCMPEQB */
10729    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x74) {
10730       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10731                                  "pcmpeqb", Iop_CmpEQ8x16, False );
10732       goto decode_success;
10733    }
10734
10735    /* 66 0F 76 = PCMPEQD */
10736    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x76) {
10737       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10738                                  "pcmpeqd", Iop_CmpEQ32x4, False );
10739       goto decode_success;
10740    }
10741
10742    /* 66 0F 75 = PCMPEQW */
10743    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x75) {
10744       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10745                                  "pcmpeqw", Iop_CmpEQ16x8, False );
10746       goto decode_success;
10747    }
10748
10749    /* 66 0F 64 = PCMPGTB */
10750    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x64) {
10751       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10752                                  "pcmpgtb", Iop_CmpGT8Sx16, False );
10753       goto decode_success;
10754    }
10755
10756    /* 66 0F 66 = PCMPGTD */
10757    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x66) {
10758       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10759                                  "pcmpgtd", Iop_CmpGT32Sx4, False );
10760       goto decode_success;
10761    }
10762
10763    /* 66 0F 65 = PCMPGTW */
10764    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x65) {
10765       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10766                                  "pcmpgtw", Iop_CmpGT16Sx8, False );
10767       goto decode_success;
10768    }
10769
10770    /* 66 0F C5 = PEXTRW -- extract 16-bit field from xmm(E) and put 
10771       zero-extend of it in ireg(G). */
10772    if (insn[0] == 0x0F && insn[1] == 0xC5) {
10773       modrm = insn[2];
10774       if (sz == 2 && epartIsReg(modrm)) {
10775          t5 = newTemp(Ity_V128);
10776          t4 = newTemp(Ity_I16);
10777          assign(t5, getXMMReg(eregOfRM(modrm)));
10778          breakup128to32s( t5, &t3, &t2, &t1, &t0 );
10779          switch (insn[3] & 7) {
10780             case 0:  assign(t4, unop(Iop_32to16,   mkexpr(t0))); break;
10781             case 1:  assign(t4, unop(Iop_32HIto16, mkexpr(t0))); break;
10782             case 2:  assign(t4, unop(Iop_32to16,   mkexpr(t1))); break;
10783             case 3:  assign(t4, unop(Iop_32HIto16, mkexpr(t1))); break;
10784             case 4:  assign(t4, unop(Iop_32to16,   mkexpr(t2))); break;
10785             case 5:  assign(t4, unop(Iop_32HIto16, mkexpr(t2))); break;
10786             case 6:  assign(t4, unop(Iop_32to16,   mkexpr(t3))); break;
10787             case 7:  assign(t4, unop(Iop_32HIto16, mkexpr(t3))); break;
10788             default: vassert(0); /*NOTREACHED*/
10789          }
10790          putIReg(4, gregOfRM(modrm), unop(Iop_16Uto32, mkexpr(t4)));
10791          DIP("pextrw $%d,%s,%s\n",
10792              (Int)insn[3], nameXMMReg(eregOfRM(modrm)),
10793                            nameIReg(4,gregOfRM(modrm)));
10794          delta += 4;
10795          goto decode_success;
10796       } 
10797       /* else fall through */
10798    }
10799
10800    /* 66 0F C4 = PINSRW -- get 16 bits from E(mem or low half ireg) and
10801       put it into the specified lane of xmm(G). */
10802    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xC4) {
10803       Int lane;
10804       t4 = newTemp(Ity_I16);
10805       modrm = insn[2];
10806
10807       if (epartIsReg(modrm)) {
10808          assign(t4, getIReg(2, eregOfRM(modrm)));
10809          delta += 3+1;
10810          lane = insn[3+1-1];
10811          DIP("pinsrw $%d,%s,%s\n", (Int)lane, 
10812                                    nameIReg(2,eregOfRM(modrm)),
10813                                    nameXMMReg(gregOfRM(modrm)));
10814       } else {
10815          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
10816          delta += 3+alen;
10817          lane = insn[3+alen-1];
10818          assign(t4, loadLE(Ity_I16, mkexpr(addr)));
10819          DIP("pinsrw $%d,%s,%s\n", (Int)lane, 
10820                                    dis_buf,
10821                                    nameXMMReg(gregOfRM(modrm)));
10822       }
10823
10824       putXMMRegLane16( gregOfRM(modrm), lane & 7, mkexpr(t4) );
10825       goto decode_success;
10826    }
10827
10828    /* 66 0F F5 = PMADDWD -- Multiply and add packed integers from
10829       E(xmm or mem) to G(xmm) */
10830    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xF5) {
10831       IRTemp s1V  = newTemp(Ity_V128);
10832       IRTemp s2V  = newTemp(Ity_V128);
10833       IRTemp dV   = newTemp(Ity_V128);
10834       IRTemp s1Hi = newTemp(Ity_I64);
10835       IRTemp s1Lo = newTemp(Ity_I64);
10836       IRTemp s2Hi = newTemp(Ity_I64);
10837       IRTemp s2Lo = newTemp(Ity_I64);
10838       IRTemp dHi  = newTemp(Ity_I64);
10839       IRTemp dLo  = newTemp(Ity_I64);
10840       modrm = insn[2];
10841       if (epartIsReg(modrm)) {
10842          assign( s1V, getXMMReg(eregOfRM(modrm)) );
10843          delta += 2+1;
10844          DIP("pmaddwd %s,%s\n", nameXMMReg(eregOfRM(modrm)),
10845                                 nameXMMReg(gregOfRM(modrm)));
10846       } else {
10847          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
10848          assign( s1V, loadLE(Ity_V128, mkexpr(addr)) );
10849          delta += 2+alen;
10850          DIP("pmaddwd %s,%s\n", dis_buf,
10851                                 nameXMMReg(gregOfRM(modrm)));
10852       }
10853       assign( s2V, getXMMReg(gregOfRM(modrm)) );
10854       assign( s1Hi, unop(Iop_V128HIto64, mkexpr(s1V)) );
10855       assign( s1Lo, unop(Iop_V128to64,   mkexpr(s1V)) );
10856       assign( s2Hi, unop(Iop_V128HIto64, mkexpr(s2V)) );
10857       assign( s2Lo, unop(Iop_V128to64,   mkexpr(s2V)) );
10858       assign( dHi, mkIRExprCCall(
10859                       Ity_I64, 0/*regparms*/,
10860                       "x86g_calculate_mmx_pmaddwd", 
10861                       &x86g_calculate_mmx_pmaddwd,
10862                       mkIRExprVec_2( mkexpr(s1Hi), mkexpr(s2Hi))
10863                    ));
10864       assign( dLo, mkIRExprCCall(
10865                       Ity_I64, 0/*regparms*/,
10866                       "x86g_calculate_mmx_pmaddwd", 
10867                       &x86g_calculate_mmx_pmaddwd,
10868                       mkIRExprVec_2( mkexpr(s1Lo), mkexpr(s2Lo))
10869                    ));
10870       assign( dV, binop(Iop_64HLtoV128, mkexpr(dHi), mkexpr(dLo))) ;
10871       putXMMReg(gregOfRM(modrm), mkexpr(dV));
10872       goto decode_success;
10873    }
10874
10875    /* 66 0F EE = PMAXSW -- 16x8 signed max */
10876    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xEE) {
10877       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10878                                  "pmaxsw", Iop_Max16Sx8, False );
10879       goto decode_success;
10880    }
10881
10882    /* 66 0F DE = PMAXUB -- 8x16 unsigned max */
10883    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xDE) {
10884       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10885                                  "pmaxub", Iop_Max8Ux16, False );
10886       goto decode_success;
10887    }
10888
10889    /* 66 0F EA = PMINSW -- 16x8 signed min */
10890    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xEA) {
10891       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10892                                  "pminsw", Iop_Min16Sx8, False );
10893       goto decode_success;
10894    }
10895
10896    /* 66 0F DA = PMINUB -- 8x16 unsigned min */
10897    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xDA) {
10898       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10899                                  "pminub", Iop_Min8Ux16, False );
10900       goto decode_success;
10901    }
10902
10903    /* 66 0F D7 = PMOVMSKB -- extract sign bits from each of 16 lanes in
10904       xmm(G), turn them into a byte, and put zero-extend of it in
10905       ireg(G).  Doing this directly is just too cumbersome; give up
10906       therefore and call a helper. */
10907    /* UInt x86g_calculate_sse_pmovmskb ( ULong w64hi, ULong w64lo ); */
10908    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xD7) {
10909       modrm = insn[2];
10910       if (epartIsReg(modrm)) {
10911          t0 = newTemp(Ity_I64);
10912          t1 = newTemp(Ity_I64);
10913          assign(t0, getXMMRegLane64(eregOfRM(modrm), 0));
10914          assign(t1, getXMMRegLane64(eregOfRM(modrm), 1));
10915          t5 = newTemp(Ity_I32);
10916          assign(t5, mkIRExprCCall(
10917                        Ity_I32, 0/*regparms*/, 
10918                        "x86g_calculate_sse_pmovmskb",
10919                        &x86g_calculate_sse_pmovmskb,
10920                        mkIRExprVec_2( mkexpr(t1), mkexpr(t0) )));
10921          putIReg(4, gregOfRM(modrm), mkexpr(t5));
10922          DIP("pmovmskb %s,%s\n", nameXMMReg(eregOfRM(modrm)),
10923                                  nameIReg(4,gregOfRM(modrm)));
10924          delta += 3;
10925          goto decode_success;
10926       } 
10927       /* else fall through */
10928    }
10929
10930    /* 66 0F E4 = PMULHUW -- 16x8 hi-half of unsigned widening multiply */
10931    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xE4) {
10932       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10933                                  "pmulhuw", Iop_MulHi16Ux8, False );
10934       goto decode_success;
10935    }
10936
10937    /* 66 0F E5 = PMULHW -- 16x8 hi-half of signed widening multiply */
10938    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xE5) {
10939       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10940                                  "pmulhw", Iop_MulHi16Sx8, False );
10941       goto decode_success;
10942    }
10943
10944    /* 66 0F D5 = PMULHL -- 16x8 multiply */
10945    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xD5) {
10946       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10947                                  "pmullw", Iop_Mul16x8, False );
10948       goto decode_success;
10949    }
10950
10951    /* ***--- this is an MMX class insn introduced in SSE2 ---*** */
10952    /* 0F F4 = PMULUDQ -- unsigned widening multiply of 32-lanes 0 x
10953       0 to form 64-bit result */
10954    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xF4) {
10955       IRTemp sV = newTemp(Ity_I64);
10956       IRTemp dV = newTemp(Ity_I64);
10957       t1 = newTemp(Ity_I32);
10958       t0 = newTemp(Ity_I32);
10959       modrm = insn[2];
10960
10961       do_MMX_preamble();
10962       assign( dV, getMMXReg(gregOfRM(modrm)) );
10963
10964       if (epartIsReg(modrm)) {
10965          assign( sV, getMMXReg(eregOfRM(modrm)) );
10966          delta += 2+1;
10967          DIP("pmuludq %s,%s\n", nameMMXReg(eregOfRM(modrm)),
10968                                 nameMMXReg(gregOfRM(modrm)));
10969       } else {
10970          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
10971          assign( sV, loadLE(Ity_I64, mkexpr(addr)) );
10972          delta += 2+alen;
10973          DIP("pmuludq %s,%s\n", dis_buf,
10974                                 nameMMXReg(gregOfRM(modrm)));
10975       }
10976
10977       assign( t0, unop(Iop_64to32, mkexpr(dV)) );
10978       assign( t1, unop(Iop_64to32, mkexpr(sV)) );
10979       putMMXReg( gregOfRM(modrm),
10980                  binop( Iop_MullU32, mkexpr(t0), mkexpr(t1) ) );
10981       goto decode_success;
10982    }
10983
10984    /* 66 0F F4 = PMULUDQ -- unsigned widening multiply of 32-lanes 0 x
10985       0 to form lower 64-bit half and lanes 2 x 2 to form upper 64-bit
10986       half */
10987    /* This is a really poor translation -- could be improved if
10988       performance critical */
10989    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xF4) {
10990       IRTemp sV, dV;
10991       IRTemp s3, s2, s1, s0, d3, d2, d1, d0;
10992       sV = newTemp(Ity_V128);
10993       dV = newTemp(Ity_V128);
10994       s3 = s2 = s1 = s0 = d3 = d2 = d1 = d0 = IRTemp_INVALID;
10995       t1 = newTemp(Ity_I64);
10996       t0 = newTemp(Ity_I64);
10997       modrm = insn[2];
10998       assign( dV, getXMMReg(gregOfRM(modrm)) );
10999
11000       if (epartIsReg(modrm)) {
11001          assign( sV, getXMMReg(eregOfRM(modrm)) );
11002          delta += 2+1;
11003          DIP("pmuludq %s,%s\n", nameXMMReg(eregOfRM(modrm)),
11004                                 nameXMMReg(gregOfRM(modrm)));
11005       } else {
11006          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
11007          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
11008          delta += 2+alen;
11009          DIP("pmuludq %s,%s\n", dis_buf,
11010                                 nameXMMReg(gregOfRM(modrm)));
11011       }
11012
11013       breakup128to32s( dV, &d3, &d2, &d1, &d0 );
11014       breakup128to32s( sV, &s3, &s2, &s1, &s0 );
11015
11016       assign( t0, binop( Iop_MullU32, mkexpr(d0), mkexpr(s0)) );
11017       putXMMRegLane64( gregOfRM(modrm), 0, mkexpr(t0) );
11018       assign( t1, binop( Iop_MullU32, mkexpr(d2), mkexpr(s2)) );
11019       putXMMRegLane64( gregOfRM(modrm), 1, mkexpr(t1) );
11020       goto decode_success;
11021    }
11022
11023    /* 66 0F EB = POR */
11024    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xEB) {
11025       delta = dis_SSE_E_to_G_all( sorb, delta+2, "por", Iop_OrV128 );
11026       goto decode_success;
11027    }
11028
11029    /* 66 0F F6 = PSADBW -- 2 x (8x8 -> 48 zeroes ++ u16) Sum Abs Diffs
11030       from E(xmm or mem) to G(xmm) */
11031    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xF6) {
11032       IRTemp s1V  = newTemp(Ity_V128);
11033       IRTemp s2V  = newTemp(Ity_V128);
11034       IRTemp dV   = newTemp(Ity_V128);
11035       IRTemp s1Hi = newTemp(Ity_I64);
11036       IRTemp s1Lo = newTemp(Ity_I64);
11037       IRTemp s2Hi = newTemp(Ity_I64);
11038       IRTemp s2Lo = newTemp(Ity_I64);
11039       IRTemp dHi  = newTemp(Ity_I64);
11040       IRTemp dLo  = newTemp(Ity_I64);
11041       modrm = insn[2];
11042       if (epartIsReg(modrm)) {
11043          assign( s1V, getXMMReg(eregOfRM(modrm)) );
11044          delta += 2+1;
11045          DIP("psadbw %s,%s\n", nameXMMReg(eregOfRM(modrm)),
11046                                nameXMMReg(gregOfRM(modrm)));
11047       } else {
11048          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
11049          assign( s1V, loadLE(Ity_V128, mkexpr(addr)) );
11050          delta += 2+alen;
11051          DIP("psadbw %s,%s\n", dis_buf,
11052                                nameXMMReg(gregOfRM(modrm)));
11053       }
11054       assign( s2V, getXMMReg(gregOfRM(modrm)) );
11055       assign( s1Hi, unop(Iop_V128HIto64, mkexpr(s1V)) );
11056       assign( s1Lo, unop(Iop_V128to64,   mkexpr(s1V)) );
11057       assign( s2Hi, unop(Iop_V128HIto64, mkexpr(s2V)) );
11058       assign( s2Lo, unop(Iop_V128to64,   mkexpr(s2V)) );
11059       assign( dHi, mkIRExprCCall(
11060                       Ity_I64, 0/*regparms*/,
11061                       "x86g_calculate_mmx_psadbw", 
11062                       &x86g_calculate_mmx_psadbw,
11063                       mkIRExprVec_2( mkexpr(s1Hi), mkexpr(s2Hi))
11064                    ));
11065       assign( dLo, mkIRExprCCall(
11066                       Ity_I64, 0/*regparms*/,
11067                       "x86g_calculate_mmx_psadbw", 
11068                       &x86g_calculate_mmx_psadbw,
11069                       mkIRExprVec_2( mkexpr(s1Lo), mkexpr(s2Lo))
11070                    ));
11071       assign( dV, binop(Iop_64HLtoV128, mkexpr(dHi), mkexpr(dLo))) ;
11072       putXMMReg(gregOfRM(modrm), mkexpr(dV));
11073       goto decode_success;
11074    }
11075
11076    /* 66 0F 70 = PSHUFD -- rearrange 4x32 from E(xmm or mem) to G(xmm) */
11077    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x70) {
11078       Int order;
11079       IRTemp sV, dV, s3, s2, s1, s0;
11080       s3 = s2 = s1 = s0 = IRTemp_INVALID;
11081       sV = newTemp(Ity_V128);
11082       dV = newTemp(Ity_V128);
11083       modrm = insn[2];
11084       if (epartIsReg(modrm)) {
11085          assign( sV, getXMMReg(eregOfRM(modrm)) );
11086          order = (Int)insn[3];
11087          delta += 2+2;
11088          DIP("pshufd $%d,%s,%s\n", order, 
11089                                    nameXMMReg(eregOfRM(modrm)),
11090                                    nameXMMReg(gregOfRM(modrm)));
11091       } else {
11092          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
11093          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
11094          order = (Int)insn[2+alen];
11095          delta += 3+alen;
11096          DIP("pshufd $%d,%s,%s\n", order, 
11097                                    dis_buf,
11098                                    nameXMMReg(gregOfRM(modrm)));
11099       }
11100       breakup128to32s( sV, &s3, &s2, &s1, &s0 );
11101
11102 #     define SEL(n) \
11103                 ((n)==0 ? s0 : ((n)==1 ? s1 : ((n)==2 ? s2 : s3)))
11104       assign(dV,
11105              mk128from32s( SEL((order>>6)&3), SEL((order>>4)&3),
11106                            SEL((order>>2)&3), SEL((order>>0)&3) )
11107       );
11108       putXMMReg(gregOfRM(modrm), mkexpr(dV));
11109 #     undef SEL
11110       goto decode_success;
11111    }
11112
11113    /* F3 0F 70 = PSHUFHW -- rearrange upper half 4x16 from E(xmm or
11114       mem) to G(xmm), and copy lower half */
11115    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x70) {
11116       Int order;
11117       IRTemp sVhi, dVhi, sV, dV, s3, s2, s1, s0;
11118       s3 = s2 = s1 = s0 = IRTemp_INVALID;
11119       sV   = newTemp(Ity_V128);
11120       dV   = newTemp(Ity_V128);
11121       sVhi = newTemp(Ity_I64);
11122       dVhi = newTemp(Ity_I64);
11123       modrm = insn[3];
11124       if (epartIsReg(modrm)) {
11125          assign( sV, getXMMReg(eregOfRM(modrm)) );
11126          order = (Int)insn[4];
11127          delta += 4+1;
11128          DIP("pshufhw $%d,%s,%s\n", order, 
11129                                     nameXMMReg(eregOfRM(modrm)),
11130                                     nameXMMReg(gregOfRM(modrm)));
11131       } else {
11132          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
11133          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
11134          order = (Int)insn[3+alen];
11135          delta += 4+alen;
11136          DIP("pshufhw $%d,%s,%s\n", order, 
11137                                     dis_buf,
11138                                     nameXMMReg(gregOfRM(modrm)));
11139       }
11140       assign( sVhi, unop(Iop_V128HIto64, mkexpr(sV)) );
11141       breakup64to16s( sVhi, &s3, &s2, &s1, &s0 );
11142
11143 #     define SEL(n) \
11144                 ((n)==0 ? s0 : ((n)==1 ? s1 : ((n)==2 ? s2 : s3)))
11145       assign(dVhi,
11146              mk64from16s( SEL((order>>6)&3), SEL((order>>4)&3),
11147                           SEL((order>>2)&3), SEL((order>>0)&3) )
11148       );
11149       assign(dV, binop( Iop_64HLtoV128, 
11150                         mkexpr(dVhi),
11151                         unop(Iop_V128to64, mkexpr(sV))) );
11152       putXMMReg(gregOfRM(modrm), mkexpr(dV));
11153 #     undef SEL
11154       goto decode_success;
11155    }
11156
11157    /* F2 0F 70 = PSHUFLW -- rearrange lower half 4x16 from E(xmm or
11158       mem) to G(xmm), and copy upper half */
11159    if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x70) {
11160       Int order;
11161       IRTemp sVlo, dVlo, sV, dV, s3, s2, s1, s0;
11162       s3 = s2 = s1 = s0 = IRTemp_INVALID;
11163       sV   = newTemp(Ity_V128);
11164       dV   = newTemp(Ity_V128);
11165       sVlo = newTemp(Ity_I64);
11166       dVlo = newTemp(Ity_I64);
11167       modrm = insn[3];
11168       if (epartIsReg(modrm)) {
11169          assign( sV, getXMMReg(eregOfRM(modrm)) );
11170          order = (Int)insn[4];
11171          delta += 4+1;
11172          DIP("pshuflw $%d,%s,%s\n", order, 
11173                                     nameXMMReg(eregOfRM(modrm)),
11174                                     nameXMMReg(gregOfRM(modrm)));
11175       } else {
11176          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
11177          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
11178          order = (Int)insn[3+alen];
11179          delta += 4+alen;
11180          DIP("pshuflw $%d,%s,%s\n", order, 
11181                                     dis_buf,
11182                                     nameXMMReg(gregOfRM(modrm)));
11183       }
11184       assign( sVlo, unop(Iop_V128to64, mkexpr(sV)) );
11185       breakup64to16s( sVlo, &s3, &s2, &s1, &s0 );
11186
11187 #     define SEL(n) \
11188                 ((n)==0 ? s0 : ((n)==1 ? s1 : ((n)==2 ? s2 : s3)))
11189       assign(dVlo,
11190              mk64from16s( SEL((order>>6)&3), SEL((order>>4)&3),
11191                           SEL((order>>2)&3), SEL((order>>0)&3) )
11192       );
11193       assign(dV, binop( Iop_64HLtoV128,
11194                         unop(Iop_V128HIto64, mkexpr(sV)),
11195                         mkexpr(dVlo) ) );
11196       putXMMReg(gregOfRM(modrm), mkexpr(dV));
11197 #     undef SEL
11198       goto decode_success;
11199    }
11200
11201    /* 66 0F 72 /6 ib = PSLLD by immediate */
11202    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x72
11203        && epartIsReg(insn[2])
11204        && gregOfRM(insn[2]) == 6) {
11205       delta = dis_SSE_shiftE_imm( delta+2, "pslld", Iop_ShlN32x4 );
11206       goto decode_success;
11207    }
11208
11209    /* 66 0F F2 = PSLLD by E */
11210    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xF2) {
11211       delta = dis_SSE_shiftG_byE( sorb, delta+2, "pslld", Iop_ShlN32x4 );
11212       goto decode_success;
11213    }
11214
11215    /* 66 0F 73 /7 ib = PSLLDQ by immediate */
11216    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x73
11217        && epartIsReg(insn[2])
11218        && gregOfRM(insn[2]) == 7) {
11219       IRTemp sV, dV, hi64, lo64, hi64r, lo64r;
11220       Int    imm = (Int)insn[3];
11221       Int    reg = eregOfRM(insn[2]);
11222       DIP("pslldq $%d,%s\n", imm, nameXMMReg(reg));
11223       vassert(imm >= 0 && imm <= 255);
11224       delta += 4;
11225
11226       sV    = newTemp(Ity_V128);
11227       dV    = newTemp(Ity_V128);
11228       hi64  = newTemp(Ity_I64);
11229       lo64  = newTemp(Ity_I64);
11230       hi64r = newTemp(Ity_I64);
11231       lo64r = newTemp(Ity_I64);
11232
11233       if (imm >= 16) {
11234          putXMMReg(reg, mkV128(0x0000));
11235          goto decode_success;
11236       }
11237
11238       assign( sV, getXMMReg(reg) );
11239       assign( hi64, unop(Iop_V128HIto64, mkexpr(sV)) );
11240       assign( lo64, unop(Iop_V128to64, mkexpr(sV)) );
11241
11242       if (imm == 0) {
11243          assign( lo64r, mkexpr(lo64) );
11244          assign( hi64r, mkexpr(hi64) );
11245       }
11246       else
11247       if (imm == 8) {
11248          assign( lo64r, mkU64(0) );
11249          assign( hi64r, mkexpr(lo64) );
11250       }
11251       else
11252       if (imm > 8) {
11253          assign( lo64r, mkU64(0) );
11254          assign( hi64r, binop( Iop_Shl64, 
11255                                mkexpr(lo64),
11256                                mkU8( 8*(imm-8) ) ));
11257       } else {
11258          assign( lo64r, binop( Iop_Shl64, 
11259                                mkexpr(lo64),
11260                                mkU8(8 * imm) ));
11261          assign( hi64r, 
11262                  binop( Iop_Or64,
11263                         binop(Iop_Shl64, mkexpr(hi64), 
11264                                          mkU8(8 * imm)),
11265                         binop(Iop_Shr64, mkexpr(lo64),
11266                                          mkU8(8 * (8 - imm)) )
11267                       )
11268                );
11269       }
11270       assign( dV, binop(Iop_64HLtoV128, mkexpr(hi64r), mkexpr(lo64r)) );
11271       putXMMReg(reg, mkexpr(dV));
11272       goto decode_success;
11273    }
11274
11275    /* 66 0F 73 /6 ib = PSLLQ by immediate */
11276    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x73
11277        && epartIsReg(insn[2])
11278        && gregOfRM(insn[2]) == 6) {
11279       delta = dis_SSE_shiftE_imm( delta+2, "psllq", Iop_ShlN64x2 );
11280       goto decode_success;
11281    }
11282
11283    /* 66 0F F3 = PSLLQ by E */
11284    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xF3) {
11285       delta = dis_SSE_shiftG_byE( sorb, delta+2, "psllq", Iop_ShlN64x2 );
11286       goto decode_success;
11287    }
11288
11289    /* 66 0F 71 /6 ib = PSLLW by immediate */
11290    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x71
11291        && epartIsReg(insn[2])
11292        && gregOfRM(insn[2]) == 6) {
11293       delta = dis_SSE_shiftE_imm( delta+2, "psllw", Iop_ShlN16x8 );
11294       goto decode_success;
11295    }
11296
11297    /* 66 0F F1 = PSLLW by E */
11298    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xF1) {
11299       delta = dis_SSE_shiftG_byE( sorb, delta+2, "psllw", Iop_ShlN16x8 );
11300       goto decode_success;
11301    }
11302
11303    /* 66 0F 72 /4 ib = PSRAD by immediate */
11304    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x72
11305        && epartIsReg(insn[2])
11306        && gregOfRM(insn[2]) == 4) {
11307       delta = dis_SSE_shiftE_imm( delta+2, "psrad", Iop_SarN32x4 );
11308       goto decode_success;
11309    }
11310
11311    /* 66 0F E2 = PSRAD by E */
11312    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xE2) {
11313       delta = dis_SSE_shiftG_byE( sorb, delta+2, "psrad", Iop_SarN32x4 );
11314       goto decode_success;
11315    }
11316
11317    /* 66 0F 71 /4 ib = PSRAW by immediate */
11318    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x71
11319        && epartIsReg(insn[2])
11320        && gregOfRM(insn[2]) == 4) {
11321       delta = dis_SSE_shiftE_imm( delta+2, "psraw", Iop_SarN16x8 );
11322       goto decode_success;
11323    }
11324
11325    /* 66 0F E1 = PSRAW by E */
11326    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xE1) {
11327       delta = dis_SSE_shiftG_byE( sorb, delta+2, "psraw", Iop_SarN16x8 );
11328       goto decode_success;
11329    }
11330
11331    /* 66 0F 72 /2 ib = PSRLD by immediate */
11332    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x72
11333        && epartIsReg(insn[2])
11334        && gregOfRM(insn[2]) == 2) {
11335       delta = dis_SSE_shiftE_imm( delta+2, "psrld", Iop_ShrN32x4 );
11336       goto decode_success;
11337    }
11338
11339    /* 66 0F D2 = PSRLD by E */
11340    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xD2) {
11341       delta = dis_SSE_shiftG_byE( sorb, delta+2, "psrld", Iop_ShrN32x4 );
11342       goto decode_success;
11343    }
11344
11345    /* 66 0F 73 /3 ib = PSRLDQ by immediate */
11346    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x73
11347        && epartIsReg(insn[2])
11348        && gregOfRM(insn[2]) == 3) {
11349       IRTemp sV, dV, hi64, lo64, hi64r, lo64r;
11350       Int    imm = (Int)insn[3];
11351       Int    reg = eregOfRM(insn[2]);
11352       DIP("psrldq $%d,%s\n", imm, nameXMMReg(reg));
11353       vassert(imm >= 0 && imm <= 255);
11354       delta += 4;
11355
11356       sV    = newTemp(Ity_V128);
11357       dV    = newTemp(Ity_V128);
11358       hi64  = newTemp(Ity_I64);
11359       lo64  = newTemp(Ity_I64);
11360       hi64r = newTemp(Ity_I64);
11361       lo64r = newTemp(Ity_I64);
11362
11363       if (imm >= 16) {
11364          putXMMReg(reg, mkV128(0x0000));
11365          goto decode_success;
11366       }
11367
11368       assign( sV, getXMMReg(reg) );
11369       assign( hi64, unop(Iop_V128HIto64, mkexpr(sV)) );
11370       assign( lo64, unop(Iop_V128to64, mkexpr(sV)) );
11371
11372       if (imm == 0) {
11373          assign( lo64r, mkexpr(lo64) );
11374          assign( hi64r, mkexpr(hi64) );
11375       }
11376       else
11377       if (imm == 8) {
11378          assign( hi64r, mkU64(0) );
11379          assign( lo64r, mkexpr(hi64) );
11380       }
11381       else 
11382       if (imm > 8) {
11383          assign( hi64r, mkU64(0) );
11384          assign( lo64r, binop( Iop_Shr64, 
11385                                mkexpr(hi64),
11386                                mkU8( 8*(imm-8) ) ));
11387       } else {
11388          assign( hi64r, binop( Iop_Shr64, 
11389                                mkexpr(hi64),
11390                                mkU8(8 * imm) ));
11391          assign( lo64r, 
11392                  binop( Iop_Or64,
11393                         binop(Iop_Shr64, mkexpr(lo64), 
11394                                          mkU8(8 * imm)),
11395                         binop(Iop_Shl64, mkexpr(hi64),
11396                                          mkU8(8 * (8 - imm)) )
11397                       )
11398                );
11399       }
11400
11401       assign( dV, binop(Iop_64HLtoV128, mkexpr(hi64r), mkexpr(lo64r)) );
11402       putXMMReg(reg, mkexpr(dV));
11403       goto decode_success;
11404    }
11405
11406    /* 66 0F 73 /2 ib = PSRLQ by immediate */
11407    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x73
11408        && epartIsReg(insn[2])
11409        && gregOfRM(insn[2]) == 2) {
11410       delta = dis_SSE_shiftE_imm( delta+2, "psrlq", Iop_ShrN64x2 );
11411       goto decode_success;
11412    }
11413
11414    /* 66 0F D3 = PSRLQ by E */
11415    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xD3) {
11416       delta = dis_SSE_shiftG_byE( sorb, delta+2, "psrlq", Iop_ShrN64x2 );
11417       goto decode_success;
11418    }
11419
11420    /* 66 0F 71 /2 ib = PSRLW by immediate */
11421    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x71
11422        && epartIsReg(insn[2])
11423        && gregOfRM(insn[2]) == 2) {
11424       delta = dis_SSE_shiftE_imm( delta+2, "psrlw", Iop_ShrN16x8 );
11425       goto decode_success;
11426    }
11427
11428    /* 66 0F D1 = PSRLW by E */
11429    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xD1) {
11430       delta = dis_SSE_shiftG_byE( sorb, delta+2, "psrlw", Iop_ShrN16x8 );
11431       goto decode_success;
11432    }
11433
11434    /* 66 0F F8 = PSUBB */
11435    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xF8) {
11436       delta = dis_SSEint_E_to_G( sorb, delta+2, 
11437                                  "psubb", Iop_Sub8x16, False );
11438       goto decode_success;
11439    }
11440
11441    /* 66 0F FA = PSUBD */
11442    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xFA) {
11443       delta = dis_SSEint_E_to_G( sorb, delta+2, 
11444                                  "psubd", Iop_Sub32x4, False );
11445       goto decode_success;
11446    }
11447
11448    /* ***--- this is an MMX class insn introduced in SSE2 ---*** */
11449    /* 0F FB = PSUBQ -- sub 64x1 */
11450    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xFB) {
11451       do_MMX_preamble();
11452       delta = dis_MMXop_regmem_to_reg ( 
11453                 sorb, delta+2, insn[1], "psubq", False );
11454       goto decode_success;
11455    }
11456
11457    /* 66 0F FB = PSUBQ */
11458    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xFB) {
11459       delta = dis_SSEint_E_to_G( sorb, delta+2, 
11460                                  "psubq", Iop_Sub64x2, False );
11461       goto decode_success;
11462    }
11463
11464    /* 66 0F F9 = PSUBW */
11465    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xF9) {
11466       delta = dis_SSEint_E_to_G( sorb, delta+2, 
11467                                  "psubw", Iop_Sub16x8, False );
11468       goto decode_success;
11469    }
11470
11471    /* 66 0F E8 = PSUBSB */
11472    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xE8) {
11473       delta = dis_SSEint_E_to_G( sorb, delta+2, 
11474                                  "psubsb", Iop_QSub8Sx16, False );
11475       goto decode_success;
11476    }
11477
11478    /* 66 0F E9 = PSUBSW */
11479    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xE9) {
11480       delta = dis_SSEint_E_to_G( sorb, delta+2, 
11481                                  "psubsw", Iop_QSub16Sx8, False );
11482       goto decode_success;
11483    }
11484
11485    /* 66 0F D8 = PSUBSB */
11486    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xD8) {
11487       delta = dis_SSEint_E_to_G( sorb, delta+2, 
11488                                  "psubusb", Iop_QSub8Ux16, False );
11489       goto decode_success;
11490    }
11491
11492    /* 66 0F D9 = PSUBSW */
11493    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xD9) {
11494       delta = dis_SSEint_E_to_G( sorb, delta+2, 
11495                                  "psubusw", Iop_QSub16Ux8, False );
11496       goto decode_success;
11497    }
11498
11499    /* 66 0F 68 = PUNPCKHBW */
11500    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x68) {
11501       delta = dis_SSEint_E_to_G( sorb, delta+2, 
11502                                  "punpckhbw",
11503                                  Iop_InterleaveHI8x16, True );
11504       goto decode_success;
11505    }
11506
11507    /* 66 0F 6A = PUNPCKHDQ */
11508    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x6A) {
11509       delta = dis_SSEint_E_to_G( sorb, delta+2, 
11510                                  "punpckhdq",
11511                                  Iop_InterleaveHI32x4, True );
11512       goto decode_success;
11513    }
11514
11515    /* 66 0F 6D = PUNPCKHQDQ */
11516    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x6D) {
11517       delta = dis_SSEint_E_to_G( sorb, delta+2, 
11518                                  "punpckhqdq",
11519                                  Iop_InterleaveHI64x2, True );
11520       goto decode_success;
11521    }
11522
11523    /* 66 0F 69 = PUNPCKHWD */
11524    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x69) {
11525       delta = dis_SSEint_E_to_G( sorb, delta+2, 
11526                                  "punpckhwd",
11527                                  Iop_InterleaveHI16x8, True );
11528       goto decode_success;
11529    }
11530
11531    /* 66 0F 60 = PUNPCKLBW */
11532    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x60) {
11533       delta = dis_SSEint_E_to_G( sorb, delta+2, 
11534                                  "punpcklbw",
11535                                  Iop_InterleaveLO8x16, True );
11536       goto decode_success;
11537    }
11538
11539    /* 66 0F 62 = PUNPCKLDQ */
11540    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x62) {
11541       delta = dis_SSEint_E_to_G( sorb, delta+2, 
11542                                  "punpckldq",
11543                                  Iop_InterleaveLO32x4, True );
11544       goto decode_success;
11545    }
11546
11547    /* 66 0F 6C = PUNPCKLQDQ */
11548    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x6C) {
11549       delta = dis_SSEint_E_to_G( sorb, delta+2, 
11550                                  "punpcklqdq",
11551                                  Iop_InterleaveLO64x2, True );
11552       goto decode_success;
11553    }
11554
11555    /* 66 0F 61 = PUNPCKLWD */
11556    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x61) {
11557       delta = dis_SSEint_E_to_G( sorb, delta+2, 
11558                                  "punpcklwd",
11559                                  Iop_InterleaveLO16x8, True );
11560       goto decode_success;
11561    }
11562
11563    /* 66 0F EF = PXOR */
11564    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xEF) {
11565       delta = dis_SSE_E_to_G_all( sorb, delta+2, "pxor", Iop_XorV128 );
11566       goto decode_success;
11567    }
11568
11569 //--    /* FXSAVE/FXRSTOR m32 -- load/store the FPU/MMX/SSE state. */
11570 //--    if (insn[0] == 0x0F && insn[1] == 0xAE 
11571 //--        && (!epartIsReg(insn[2]))
11572 //--        && (gregOfRM(insn[2]) == 1 || gregOfRM(insn[2]) == 0) ) {
11573 //--       Bool store = gregOfRM(insn[2]) == 0;
11574 //--       vg_assert(sz == 4);
11575 //--       pair = disAMode ( cb, sorb, eip+2, dis_buf );
11576 //--       t1   = LOW24(pair);
11577 //--       eip += 2+HI8(pair);
11578 //--       uInstr3(cb, store ? SSE2a_MemWr : SSE2a_MemRd, 512,
11579 //--                   Lit16, (((UShort)insn[0]) << 8) | (UShort)insn[1],
11580 //--                   Lit16, (UShort)insn[2],
11581 //--                   TempReg, t1 );
11582 //--       DIP("fx%s %s\n", store ? "save" : "rstor", dis_buf );
11583 //--       goto decode_success;
11584 //--    }
11585
11586    /* 0F AE /7 = CLFLUSH -- flush cache line */
11587    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xAE
11588        && !epartIsReg(insn[2]) && gregOfRM(insn[2]) == 7) {
11589
11590       /* This is something of a hack.  We need to know the size of the
11591          cache line containing addr.  Since we don't (easily), assume
11592          256 on the basis that no real cache would have a line that
11593          big.  It's safe to invalidate more stuff than we need, just
11594          inefficient. */
11595       UInt lineszB = 256;
11596
11597       addr = disAMode ( &alen, sorb, delta+2, dis_buf );
11598       delta += 2+alen;
11599
11600       /* Round addr down to the start of the containing block. */
11601       stmt( IRStmt_Put(
11602                OFFB_TISTART,
11603                binop( Iop_And32, 
11604                       mkexpr(addr), 
11605                       mkU32( ~(lineszB-1) ))) );
11606
11607       stmt( IRStmt_Put(OFFB_TILEN, mkU32(lineszB) ) );
11608
11609       irsb->jumpkind = Ijk_TInval;
11610       irsb->next     = mkU32(guest_EIP_bbstart+delta);
11611       dres.whatNext  = Dis_StopHere;
11612
11613       DIP("clflush %s\n", dis_buf);
11614       goto decode_success;
11615    }
11616
11617    /* ---------------------------------------------------- */
11618    /* --- end of the SSE2 decoder.                     --- */
11619    /* ---------------------------------------------------- */
11620
11621    /* ---------------------------------------------------- */
11622    /* --- start of the SSE3 decoder.                   --- */
11623    /* ---------------------------------------------------- */
11624
11625    /* Skip parts of the decoder which don't apply given the stated
11626       guest subarchitecture. */
11627    /* if (0 == (archinfo->hwcaps & VEX_HWCAPS_X86_SSE3)) */
11628    /* In fact this is highly bogus; we accept SSE3 insns even on a
11629       SSE2-only guest since they turn into IR which can be re-emitted
11630       successfully on an SSE2 host. */
11631    if (0 == (archinfo->hwcaps & VEX_HWCAPS_X86_SSE2))
11632       goto after_sse_decoders; /* no SSE3 capabilities */
11633
11634    insn = (UChar*)&guest_code[delta];
11635
11636    /* F3 0F 12 = MOVSLDUP -- move from E (mem or xmm) to G (xmm),
11637       duplicating some lanes (2:2:0:0). */
11638    /* F3 0F 16 = MOVSHDUP -- move from E (mem or xmm) to G (xmm),
11639       duplicating some lanes (3:3:1:1). */
11640    if (sz == 4 && insn[0] == 0xF3 && insn[1] == 0x0F 
11641        && (insn[2] == 0x12 || insn[2] == 0x16)) {
11642       IRTemp s3, s2, s1, s0;
11643       IRTemp sV  = newTemp(Ity_V128);
11644       Bool   isH = insn[2] == 0x16;
11645       s3 = s2 = s1 = s0 = IRTemp_INVALID;
11646
11647       modrm = insn[3];
11648       if (epartIsReg(modrm)) {
11649          assign( sV, getXMMReg( eregOfRM(modrm)) );
11650          DIP("movs%cdup %s,%s\n", isH ? 'h' : 'l',
11651                                   nameXMMReg(eregOfRM(modrm)),
11652                                   nameXMMReg(gregOfRM(modrm)));
11653          delta += 3+1;
11654       } else {
11655          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
11656          gen_SEGV_if_not_16_aligned( addr );
11657          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
11658          DIP("movs%cdup %s,%s\n", isH ? 'h' : 'l',
11659              dis_buf,
11660              nameXMMReg(gregOfRM(modrm)));
11661          delta += 3+alen;
11662       }
11663
11664       breakup128to32s( sV, &s3, &s2, &s1, &s0 );
11665       putXMMReg( gregOfRM(modrm), 
11666                  isH ? mk128from32s( s3, s3, s1, s1 )
11667                      : mk128from32s( s2, s2, s0, s0 ) );
11668       goto decode_success;
11669    }
11670
11671    /* F2 0F 12 = MOVDDUP -- move from E (mem or xmm) to G (xmm),
11672       duplicating some lanes (0:1:0:1). */
11673    if (sz == 4 && insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x12) {
11674       IRTemp sV = newTemp(Ity_V128);
11675       IRTemp d0 = newTemp(Ity_I64);
11676
11677       modrm = insn[3];
11678       if (epartIsReg(modrm)) {
11679          assign( sV, getXMMReg( eregOfRM(modrm)) );
11680          DIP("movddup %s,%s\n", nameXMMReg(eregOfRM(modrm)),
11681                                 nameXMMReg(gregOfRM(modrm)));
11682          delta += 3+1;
11683          assign ( d0, unop(Iop_V128to64, mkexpr(sV)) );
11684       } else {
11685          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
11686          assign( d0, loadLE(Ity_I64, mkexpr(addr)) );
11687          DIP("movddup %s,%s\n", dis_buf,
11688                                 nameXMMReg(gregOfRM(modrm)));
11689          delta += 3+alen;
11690       }
11691
11692       putXMMReg( gregOfRM(modrm), binop(Iop_64HLtoV128,mkexpr(d0),mkexpr(d0)) );
11693       goto decode_success;
11694    }
11695
11696    /* F2 0F D0 = ADDSUBPS -- 32x4 +/-/+/- from E (mem or xmm) to G (xmm). */
11697    if (sz == 4 && insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0xD0) {
11698       IRTemp a3, a2, a1, a0, s3, s2, s1, s0;
11699       IRTemp eV   = newTemp(Ity_V128);
11700       IRTemp gV   = newTemp(Ity_V128);
11701       IRTemp addV = newTemp(Ity_V128);
11702       IRTemp subV = newTemp(Ity_V128);
11703       a3 = a2 = a1 = a0 = s3 = s2 = s1 = s0 = IRTemp_INVALID;
11704
11705       modrm = insn[3];
11706       if (epartIsReg(modrm)) {
11707          assign( eV, getXMMReg( eregOfRM(modrm)) );
11708          DIP("addsubps %s,%s\n", nameXMMReg(eregOfRM(modrm)),
11709                                  nameXMMReg(gregOfRM(modrm)));
11710          delta += 3+1;
11711       } else {
11712          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
11713          assign( eV, loadLE(Ity_V128, mkexpr(addr)) );
11714          DIP("addsubps %s,%s\n", dis_buf,
11715                                  nameXMMReg(gregOfRM(modrm)));
11716          delta += 3+alen;
11717       }
11718
11719       assign( gV, getXMMReg(gregOfRM(modrm)) );
11720
11721       assign( addV, binop(Iop_Add32Fx4, mkexpr(gV), mkexpr(eV)) );
11722       assign( subV, binop(Iop_Sub32Fx4, mkexpr(gV), mkexpr(eV)) );
11723
11724       breakup128to32s( addV, &a3, &a2, &a1, &a0 );
11725       breakup128to32s( subV, &s3, &s2, &s1, &s0 );
11726
11727       putXMMReg( gregOfRM(modrm), mk128from32s( a3, s2, a1, s0 ));
11728       goto decode_success;
11729    }
11730
11731    /* 66 0F D0 = ADDSUBPD -- 64x4 +/- from E (mem or xmm) to G (xmm). */
11732    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xD0) {
11733       IRTemp eV   = newTemp(Ity_V128);
11734       IRTemp gV   = newTemp(Ity_V128);
11735       IRTemp addV = newTemp(Ity_V128);
11736       IRTemp subV = newTemp(Ity_V128);
11737       IRTemp a1     = newTemp(Ity_I64);
11738       IRTemp s0     = newTemp(Ity_I64);
11739
11740       modrm = insn[2];
11741       if (epartIsReg(modrm)) {
11742          assign( eV, getXMMReg( eregOfRM(modrm)) );
11743          DIP("addsubpd %s,%s\n", nameXMMReg(eregOfRM(modrm)),
11744                                  nameXMMReg(gregOfRM(modrm)));
11745          delta += 2+1;
11746       } else {
11747          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
11748          assign( eV, loadLE(Ity_V128, mkexpr(addr)) );
11749          DIP("addsubpd %s,%s\n", dis_buf,
11750                                  nameXMMReg(gregOfRM(modrm)));
11751          delta += 2+alen;
11752       }
11753
11754       assign( gV, getXMMReg(gregOfRM(modrm)) );
11755
11756       assign( addV, binop(Iop_Add64Fx2, mkexpr(gV), mkexpr(eV)) );
11757       assign( subV, binop(Iop_Sub64Fx2, mkexpr(gV), mkexpr(eV)) );
11758
11759       assign( a1, unop(Iop_V128HIto64, mkexpr(addV) ));
11760       assign( s0, unop(Iop_V128to64,   mkexpr(subV) ));
11761
11762       putXMMReg( gregOfRM(modrm), 
11763                  binop(Iop_64HLtoV128, mkexpr(a1), mkexpr(s0)) );
11764       goto decode_success;
11765    }
11766
11767    /* F2 0F 7D = HSUBPS -- 32x4 sub across from E (mem or xmm) to G (xmm). */
11768    /* F2 0F 7C = HADDPS -- 32x4 add across from E (mem or xmm) to G (xmm). */
11769    if (sz == 4 && insn[0] == 0xF2 && insn[1] == 0x0F 
11770        && (insn[2] == 0x7C || insn[2] == 0x7D)) {
11771       IRTemp e3, e2, e1, e0, g3, g2, g1, g0;
11772       IRTemp eV     = newTemp(Ity_V128);
11773       IRTemp gV     = newTemp(Ity_V128);
11774       IRTemp leftV  = newTemp(Ity_V128);
11775       IRTemp rightV = newTemp(Ity_V128);
11776       Bool   isAdd  = insn[2] == 0x7C;
11777       HChar* str    = isAdd ? "add" : "sub";
11778       e3 = e2 = e1 = e0 = g3 = g2 = g1 = g0 = IRTemp_INVALID;
11779
11780       modrm = insn[3];
11781       if (epartIsReg(modrm)) {
11782          assign( eV, getXMMReg( eregOfRM(modrm)) );
11783          DIP("h%sps %s,%s\n", str, nameXMMReg(eregOfRM(modrm)),
11784                                    nameXMMReg(gregOfRM(modrm)));
11785          delta += 3+1;
11786       } else {
11787          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
11788          assign( eV, loadLE(Ity_V128, mkexpr(addr)) );
11789          DIP("h%sps %s,%s\n", str, dis_buf,
11790                                    nameXMMReg(gregOfRM(modrm)));
11791          delta += 3+alen;
11792       }
11793
11794       assign( gV, getXMMReg(gregOfRM(modrm)) );
11795
11796       breakup128to32s( eV, &e3, &e2, &e1, &e0 );
11797       breakup128to32s( gV, &g3, &g2, &g1, &g0 );
11798
11799       assign( leftV,  mk128from32s( e2, e0, g2, g0 ) );
11800       assign( rightV, mk128from32s( e3, e1, g3, g1 ) );
11801
11802       putXMMReg( gregOfRM(modrm), 
11803                  binop(isAdd ? Iop_Add32Fx4 : Iop_Sub32Fx4, 
11804                        mkexpr(leftV), mkexpr(rightV) ) );
11805       goto decode_success;
11806    }
11807
11808    /* 66 0F 7D = HSUBPD -- 64x2 sub across from E (mem or xmm) to G (xmm). */
11809    /* 66 0F 7C = HADDPD -- 64x2 add across from E (mem or xmm) to G (xmm). */
11810    if (sz == 2 && insn[0] == 0x0F && (insn[1] == 0x7C || insn[1] == 0x7D)) {
11811       IRTemp e1     = newTemp(Ity_I64);
11812       IRTemp e0     = newTemp(Ity_I64);
11813       IRTemp g1     = newTemp(Ity_I64);
11814       IRTemp g0     = newTemp(Ity_I64);
11815       IRTemp eV     = newTemp(Ity_V128);
11816       IRTemp gV     = newTemp(Ity_V128);
11817       IRTemp leftV  = newTemp(Ity_V128);
11818       IRTemp rightV = newTemp(Ity_V128);
11819       Bool   isAdd  = insn[1] == 0x7C;
11820       HChar* str    = isAdd ? "add" : "sub";
11821
11822       modrm = insn[2];
11823       if (epartIsReg(modrm)) {
11824          assign( eV, getXMMReg( eregOfRM(modrm)) );
11825          DIP("h%spd %s,%s\n", str, nameXMMReg(eregOfRM(modrm)),
11826                                    nameXMMReg(gregOfRM(modrm)));
11827          delta += 2+1;
11828       } else {
11829          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
11830          assign( eV, loadLE(Ity_V128, mkexpr(addr)) );
11831          DIP("h%spd %s,%s\n", str, dis_buf,
11832                               nameXMMReg(gregOfRM(modrm)));
11833          delta += 2+alen;
11834       }
11835
11836       assign( gV, getXMMReg(gregOfRM(modrm)) );
11837
11838       assign( e1, unop(Iop_V128HIto64, mkexpr(eV) ));
11839       assign( e0, unop(Iop_V128to64, mkexpr(eV) ));
11840       assign( g1, unop(Iop_V128HIto64, mkexpr(gV) ));
11841       assign( g0, unop(Iop_V128to64, mkexpr(gV) ));
11842
11843       assign( leftV,  binop(Iop_64HLtoV128, mkexpr(e0),mkexpr(g0)) );
11844       assign( rightV, binop(Iop_64HLtoV128, mkexpr(e1),mkexpr(g1)) );
11845
11846       putXMMReg( gregOfRM(modrm), 
11847                  binop(isAdd ? Iop_Add64Fx2 : Iop_Sub64Fx2, 
11848                        mkexpr(leftV), mkexpr(rightV) ) );
11849       goto decode_success;
11850    }
11851
11852    /* F2 0F F0 = LDDQU -- move from E (mem or xmm) to G (xmm). */
11853    if (sz == 4 && insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0xF0) {
11854       modrm = getIByte(delta+3);
11855       if (epartIsReg(modrm)) {
11856          goto decode_failure;
11857       } else {
11858          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
11859          putXMMReg( gregOfRM(modrm), 
11860                     loadLE(Ity_V128, mkexpr(addr)) );
11861          DIP("lddqu %s,%s\n", dis_buf,
11862                               nameXMMReg(gregOfRM(modrm)));
11863          delta += 3+alen;
11864       }
11865       goto decode_success;
11866    }
11867
11868    /* ---------------------------------------------------- */
11869    /* --- end of the SSE3 decoder.                     --- */
11870    /* ---------------------------------------------------- */
11871
11872    /* ---------------------------------------------------- */
11873    /* --- start of the SSSE3 decoder.                  --- */
11874    /* ---------------------------------------------------- */
11875
11876    /* 0F 38 04 = PMADDUBSW -- Multiply and Add Packed Signed and
11877       Unsigned Bytes (MMX) */
11878    if (sz == 4
11879        && insn[0] == 0x0F && insn[1] == 0x38 && insn[2] == 0x04) {
11880       IRTemp sV        = newTemp(Ity_I64);
11881       IRTemp dV        = newTemp(Ity_I64);
11882       IRTemp sVoddsSX  = newTemp(Ity_I64);
11883       IRTemp sVevensSX = newTemp(Ity_I64);
11884       IRTemp dVoddsZX  = newTemp(Ity_I64);
11885       IRTemp dVevensZX = newTemp(Ity_I64);
11886
11887       modrm = insn[3];
11888       do_MMX_preamble();
11889       assign( dV, getMMXReg(gregOfRM(modrm)) );
11890
11891       if (epartIsReg(modrm)) {
11892          assign( sV, getMMXReg(eregOfRM(modrm)) );
11893          delta += 3+1;
11894          DIP("pmaddubsw %s,%s\n", nameMMXReg(eregOfRM(modrm)),
11895                                   nameMMXReg(gregOfRM(modrm)));
11896       } else {
11897          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
11898          assign( sV, loadLE(Ity_I64, mkexpr(addr)) );
11899          delta += 3+alen;
11900          DIP("pmaddubsw %s,%s\n", dis_buf,
11901                                   nameMMXReg(gregOfRM(modrm)));
11902       }
11903
11904       /* compute dV unsigned x sV signed */
11905       assign( sVoddsSX,
11906               binop(Iop_SarN16x4, mkexpr(sV), mkU8(8)) );
11907       assign( sVevensSX,
11908               binop(Iop_SarN16x4, 
11909                     binop(Iop_ShlN16x4, mkexpr(sV), mkU8(8)), 
11910                     mkU8(8)) );
11911       assign( dVoddsZX,
11912               binop(Iop_ShrN16x4, mkexpr(dV), mkU8(8)) );
11913       assign( dVevensZX,
11914               binop(Iop_ShrN16x4,
11915                     binop(Iop_ShlN16x4, mkexpr(dV), mkU8(8)),
11916                     mkU8(8)) );
11917
11918       putMMXReg(
11919          gregOfRM(modrm),
11920          binop(Iop_QAdd16Sx4,
11921                binop(Iop_Mul16x4, mkexpr(sVoddsSX), mkexpr(dVoddsZX)),
11922                binop(Iop_Mul16x4, mkexpr(sVevensSX), mkexpr(dVevensZX))
11923          )
11924       );
11925       goto decode_success;
11926    }
11927
11928    /* 66 0F 38 04 = PMADDUBSW -- Multiply and Add Packed Signed and
11929       Unsigned Bytes (XMM) */
11930    if (sz == 2
11931        && insn[0] == 0x0F && insn[1] == 0x38 && insn[2] == 0x04) {
11932       IRTemp sV        = newTemp(Ity_V128);
11933       IRTemp dV        = newTemp(Ity_V128);
11934       IRTemp sVoddsSX  = newTemp(Ity_V128);
11935       IRTemp sVevensSX = newTemp(Ity_V128);
11936       IRTemp dVoddsZX  = newTemp(Ity_V128);
11937       IRTemp dVevensZX = newTemp(Ity_V128);
11938
11939       modrm = insn[3];
11940       assign( dV, getXMMReg(gregOfRM(modrm)) );
11941
11942       if (epartIsReg(modrm)) {
11943          assign( sV, getXMMReg(eregOfRM(modrm)) );
11944          delta += 3+1;
11945          DIP("pmaddubsw %s,%s\n", nameXMMReg(eregOfRM(modrm)),
11946                                   nameXMMReg(gregOfRM(modrm)));
11947       } else {
11948          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
11949          gen_SEGV_if_not_16_aligned( addr );
11950          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
11951          delta += 3+alen;
11952          DIP("pmaddubsw %s,%s\n", dis_buf,
11953                                   nameXMMReg(gregOfRM(modrm)));
11954       }
11955
11956       /* compute dV unsigned x sV signed */
11957       assign( sVoddsSX,
11958               binop(Iop_SarN16x8, mkexpr(sV), mkU8(8)) );
11959       assign( sVevensSX,
11960               binop(Iop_SarN16x8, 
11961                     binop(Iop_ShlN16x8, mkexpr(sV), mkU8(8)), 
11962                     mkU8(8)) );
11963       assign( dVoddsZX,
11964               binop(Iop_ShrN16x8, mkexpr(dV), mkU8(8)) );
11965       assign( dVevensZX,
11966               binop(Iop_ShrN16x8,
11967                     binop(Iop_ShlN16x8, mkexpr(dV), mkU8(8)),
11968                     mkU8(8)) );
11969
11970       putXMMReg(
11971          gregOfRM(modrm),
11972          binop(Iop_QAdd16Sx8,
11973                binop(Iop_Mul16x8, mkexpr(sVoddsSX), mkexpr(dVoddsZX)),
11974                binop(Iop_Mul16x8, mkexpr(sVevensSX), mkexpr(dVevensZX))
11975          )
11976       );
11977       goto decode_success;
11978    }
11979
11980    /* ***--- these are MMX class insns introduced in SSSE3 ---*** */
11981    /* 0F 38 03 = PHADDSW -- 16x4 signed qadd across from E (mem or
11982       mmx) and G to G (mmx). */
11983    /* 0F 38 07 = PHSUBSW -- 16x4 signed qsub across from E (mem or
11984       mmx) and G to G (mmx). */
11985    /* 0F 38 01 = PHADDW -- 16x4 add across from E (mem or mmx) and G
11986       to G (mmx). */
11987    /* 0F 38 05 = PHSUBW -- 16x4 sub across from E (mem or mmx) and G
11988       to G (mmx). */
11989    /* 0F 38 02 = PHADDD -- 32x2 add across from E (mem or mmx) and G
11990       to G (mmx). */
11991    /* 0F 38 06 = PHSUBD -- 32x2 sub across from E (mem or mmx) and G
11992       to G (mmx). */
11993
11994    if (sz == 4 
11995        && insn[0] == 0x0F && insn[1] == 0x38 
11996        && (insn[2] == 0x03 || insn[2] == 0x07 || insn[2] == 0x01
11997            || insn[2] == 0x05 || insn[2] == 0x02 || insn[2] == 0x06)) {
11998       HChar* str    = "???";
11999       IROp   opV64  = Iop_INVALID;
12000       IROp   opCatO = Iop_CatOddLanes16x4;
12001       IROp   opCatE = Iop_CatEvenLanes16x4;
12002       IRTemp sV     = newTemp(Ity_I64);
12003       IRTemp dV     = newTemp(Ity_I64);
12004
12005       modrm = insn[3];
12006
12007       switch (insn[2]) {
12008          case 0x03: opV64 = Iop_QAdd16Sx4; str = "addsw"; break;
12009          case 0x07: opV64 = Iop_QSub16Sx4; str = "subsw"; break;
12010          case 0x01: opV64 = Iop_Add16x4;   str = "addw";  break;
12011          case 0x05: opV64 = Iop_Sub16x4;   str = "subw";  break;
12012          case 0x02: opV64 = Iop_Add32x2;   str = "addd";  break;
12013          case 0x06: opV64 = Iop_Sub32x2;   str = "subd";  break;
12014          default: vassert(0);
12015       }
12016       if (insn[2] == 0x02 || insn[2] == 0x06) {
12017          opCatO = Iop_InterleaveHI32x2;
12018          opCatE = Iop_InterleaveLO32x2;
12019       }
12020
12021       do_MMX_preamble();
12022       assign( dV, getMMXReg(gregOfRM(modrm)) );
12023
12024       if (epartIsReg(modrm)) {
12025          assign( sV, getMMXReg(eregOfRM(modrm)) );
12026          delta += 3+1;
12027          DIP("ph%s %s,%s\n", str, nameMMXReg(eregOfRM(modrm)),
12028                                   nameMMXReg(gregOfRM(modrm)));
12029       } else {
12030          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
12031          assign( sV, loadLE(Ity_I64, mkexpr(addr)) );
12032          delta += 3+alen;
12033          DIP("ph%s %s,%s\n", str, dis_buf,
12034                                   nameMMXReg(gregOfRM(modrm)));
12035       }
12036
12037       putMMXReg(
12038          gregOfRM(modrm),
12039          binop(opV64,
12040                binop(opCatE,mkexpr(sV),mkexpr(dV)),
12041                binop(opCatO,mkexpr(sV),mkexpr(dV))
12042          )
12043       );
12044       goto decode_success;
12045    }
12046
12047    /* 66 0F 38 03 = PHADDSW -- 16x8 signed qadd across from E (mem or
12048       xmm) and G to G (xmm). */
12049    /* 66 0F 38 07 = PHSUBSW -- 16x8 signed qsub across from E (mem or
12050       xmm) and G to G (xmm). */
12051    /* 66 0F 38 01 = PHADDW -- 16x8 add across from E (mem or xmm) and
12052       G to G (xmm). */
12053    /* 66 0F 38 05 = PHSUBW -- 16x8 sub across from E (mem or xmm) and
12054       G to G (xmm). */
12055    /* 66 0F 38 02 = PHADDD -- 32x4 add across from E (mem or xmm) and
12056       G to G (xmm). */
12057    /* 66 0F 38 06 = PHSUBD -- 32x4 sub across from E (mem or xmm) and
12058       G to G (xmm). */
12059
12060    if (sz == 2
12061        && insn[0] == 0x0F && insn[1] == 0x38 
12062        && (insn[2] == 0x03 || insn[2] == 0x07 || insn[2] == 0x01
12063            || insn[2] == 0x05 || insn[2] == 0x02 || insn[2] == 0x06)) {
12064       HChar* str    = "???";
12065       IROp   opV64  = Iop_INVALID;
12066       IROp   opCatO = Iop_CatOddLanes16x4;
12067       IROp   opCatE = Iop_CatEvenLanes16x4;
12068       IRTemp sV     = newTemp(Ity_V128);
12069       IRTemp dV     = newTemp(Ity_V128);
12070       IRTemp sHi    = newTemp(Ity_I64);
12071       IRTemp sLo    = newTemp(Ity_I64);
12072       IRTemp dHi    = newTemp(Ity_I64);
12073       IRTemp dLo    = newTemp(Ity_I64);
12074
12075       modrm = insn[3];
12076
12077       switch (insn[2]) {
12078          case 0x03: opV64 = Iop_QAdd16Sx4; str = "addsw"; break;
12079          case 0x07: opV64 = Iop_QSub16Sx4; str = "subsw"; break;
12080          case 0x01: opV64 = Iop_Add16x4;   str = "addw";  break;
12081          case 0x05: opV64 = Iop_Sub16x4;   str = "subw";  break;
12082          case 0x02: opV64 = Iop_Add32x2;   str = "addd";  break;
12083          case 0x06: opV64 = Iop_Sub32x2;   str = "subd";  break;
12084          default: vassert(0);
12085       }
12086       if (insn[2] == 0x02 || insn[2] == 0x06) {
12087          opCatO = Iop_InterleaveHI32x2;
12088          opCatE = Iop_InterleaveLO32x2;
12089       }
12090
12091       assign( dV, getXMMReg(gregOfRM(modrm)) );
12092
12093       if (epartIsReg(modrm)) {
12094          assign( sV, getXMMReg( eregOfRM(modrm)) );
12095          DIP("ph%s %s,%s\n", str, nameXMMReg(eregOfRM(modrm)),
12096                                   nameXMMReg(gregOfRM(modrm)));
12097          delta += 3+1;
12098       } else {
12099          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
12100          gen_SEGV_if_not_16_aligned( addr );
12101          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
12102          DIP("ph%s %s,%s\n", str, dis_buf,
12103                              nameXMMReg(gregOfRM(modrm)));
12104          delta += 3+alen;
12105       }
12106
12107       assign( dHi, unop(Iop_V128HIto64, mkexpr(dV)) );
12108       assign( dLo, unop(Iop_V128to64,   mkexpr(dV)) );
12109       assign( sHi, unop(Iop_V128HIto64, mkexpr(sV)) );
12110       assign( sLo, unop(Iop_V128to64,   mkexpr(sV)) );
12111
12112       /* This isn't a particularly efficient way to compute the
12113          result, but at least it avoids a proliferation of IROps,
12114          hence avoids complication all the backends. */
12115       putXMMReg(
12116          gregOfRM(modrm), 
12117          binop(Iop_64HLtoV128,
12118                binop(opV64,
12119                      binop(opCatE,mkexpr(sHi),mkexpr(sLo)),
12120                      binop(opCatO,mkexpr(sHi),mkexpr(sLo))
12121                ),
12122                binop(opV64,
12123                      binop(opCatE,mkexpr(dHi),mkexpr(dLo)),
12124                      binop(opCatO,mkexpr(dHi),mkexpr(dLo))
12125                )
12126          )
12127       );
12128       goto decode_success;
12129    }
12130
12131    /* 0F 38 0B = PMULHRSW -- Packed Multiply High with Round and Scale
12132       (MMX) */
12133    if (sz == 4 
12134        && insn[0] == 0x0F && insn[1] == 0x38 && insn[2] == 0x0B) {
12135       IRTemp sV = newTemp(Ity_I64);
12136       IRTemp dV = newTemp(Ity_I64);
12137
12138       modrm = insn[3];
12139       do_MMX_preamble();
12140       assign( dV, getMMXReg(gregOfRM(modrm)) );
12141
12142       if (epartIsReg(modrm)) {
12143          assign( sV, getMMXReg(eregOfRM(modrm)) );
12144          delta += 3+1;
12145          DIP("pmulhrsw %s,%s\n", nameMMXReg(eregOfRM(modrm)),
12146                                  nameMMXReg(gregOfRM(modrm)));
12147       } else {
12148          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
12149          assign( sV, loadLE(Ity_I64, mkexpr(addr)) );
12150          delta += 3+alen;
12151          DIP("pmulhrsw %s,%s\n", dis_buf,
12152                                  nameMMXReg(gregOfRM(modrm)));
12153       }
12154
12155       putMMXReg(
12156          gregOfRM(modrm),
12157          dis_PMULHRSW_helper( mkexpr(sV), mkexpr(dV) )
12158       );
12159       goto decode_success;
12160    }
12161
12162    /* 66 0F 38 0B = PMULHRSW -- Packed Multiply High with Round and
12163       Scale (XMM) */
12164    if (sz == 2
12165        && insn[0] == 0x0F && insn[1] == 0x38 && insn[2] == 0x0B) {
12166       IRTemp sV  = newTemp(Ity_V128);
12167       IRTemp dV  = newTemp(Ity_V128);
12168       IRTemp sHi = newTemp(Ity_I64);
12169       IRTemp sLo = newTemp(Ity_I64);
12170       IRTemp dHi = newTemp(Ity_I64);
12171       IRTemp dLo = newTemp(Ity_I64);
12172
12173       modrm = insn[3];
12174       assign( dV, getXMMReg(gregOfRM(modrm)) );
12175
12176       if (epartIsReg(modrm)) {
12177          assign( sV, getXMMReg(eregOfRM(modrm)) );
12178          delta += 3+1;
12179          DIP("pmulhrsw %s,%s\n", nameXMMReg(eregOfRM(modrm)),
12180                                  nameXMMReg(gregOfRM(modrm)));
12181       } else {
12182          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
12183          gen_SEGV_if_not_16_aligned( addr );
12184          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
12185          delta += 3+alen;
12186          DIP("pmulhrsw %s,%s\n", dis_buf,
12187                                  nameXMMReg(gregOfRM(modrm)));
12188       }
12189
12190       assign( dHi, unop(Iop_V128HIto64, mkexpr(dV)) );
12191       assign( dLo, unop(Iop_V128to64,   mkexpr(dV)) );
12192       assign( sHi, unop(Iop_V128HIto64, mkexpr(sV)) );
12193       assign( sLo, unop(Iop_V128to64,   mkexpr(sV)) );
12194
12195       putXMMReg(
12196          gregOfRM(modrm),
12197          binop(Iop_64HLtoV128,
12198                dis_PMULHRSW_helper( mkexpr(sHi), mkexpr(dHi) ),
12199                dis_PMULHRSW_helper( mkexpr(sLo), mkexpr(dLo) )
12200          )
12201       );
12202       goto decode_success;
12203    }
12204
12205    /* 0F 38 08 = PSIGNB -- Packed Sign 8x8  (MMX) */
12206    /* 0F 38 09 = PSIGNW -- Packed Sign 16x4 (MMX) */
12207    /* 0F 38 09 = PSIGND -- Packed Sign 32x2 (MMX) */
12208    if (sz == 4 
12209        && insn[0] == 0x0F && insn[1] == 0x38 
12210        && (insn[2] == 0x08 || insn[2] == 0x09 || insn[2] == 0x0A)) {
12211       IRTemp sV      = newTemp(Ity_I64);
12212       IRTemp dV      = newTemp(Ity_I64);
12213       HChar* str     = "???";
12214       Int    laneszB = 0;
12215
12216       switch (insn[2]) {
12217          case 0x08: laneszB = 1; str = "b"; break;
12218          case 0x09: laneszB = 2; str = "w"; break;
12219          case 0x0A: laneszB = 4; str = "d"; break;
12220          default: vassert(0);
12221       }
12222
12223       modrm = insn[3];
12224       do_MMX_preamble();
12225       assign( dV, getMMXReg(gregOfRM(modrm)) );
12226
12227       if (epartIsReg(modrm)) {
12228          assign( sV, getMMXReg(eregOfRM(modrm)) );
12229          delta += 3+1;
12230          DIP("psign%s %s,%s\n", str, nameMMXReg(eregOfRM(modrm)),
12231                                      nameMMXReg(gregOfRM(modrm)));
12232       } else {
12233          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
12234          assign( sV, loadLE(Ity_I64, mkexpr(addr)) );
12235          delta += 3+alen;
12236          DIP("psign%s %s,%s\n", str, dis_buf,
12237                                      nameMMXReg(gregOfRM(modrm)));
12238       }
12239
12240       putMMXReg(
12241          gregOfRM(modrm),
12242          dis_PSIGN_helper( mkexpr(sV), mkexpr(dV), laneszB )
12243       );
12244       goto decode_success;
12245    }
12246
12247    /* 66 0F 38 08 = PSIGNB -- Packed Sign 8x16 (XMM) */
12248    /* 66 0F 38 09 = PSIGNW -- Packed Sign 16x8 (XMM) */
12249    /* 66 0F 38 09 = PSIGND -- Packed Sign 32x4 (XMM) */
12250    if (sz == 2
12251        && insn[0] == 0x0F && insn[1] == 0x38 
12252        && (insn[2] == 0x08 || insn[2] == 0x09 || insn[2] == 0x0A)) {
12253       IRTemp sV      = newTemp(Ity_V128);
12254       IRTemp dV      = newTemp(Ity_V128);
12255       IRTemp sHi     = newTemp(Ity_I64);
12256       IRTemp sLo     = newTemp(Ity_I64);
12257       IRTemp dHi     = newTemp(Ity_I64);
12258       IRTemp dLo     = newTemp(Ity_I64);
12259       HChar* str     = "???";
12260       Int    laneszB = 0;
12261
12262       switch (insn[2]) {
12263          case 0x08: laneszB = 1; str = "b"; break;
12264          case 0x09: laneszB = 2; str = "w"; break;
12265          case 0x0A: laneszB = 4; str = "d"; break;
12266          default: vassert(0);
12267       }
12268
12269       modrm = insn[3];
12270       assign( dV, getXMMReg(gregOfRM(modrm)) );
12271
12272       if (epartIsReg(modrm)) {
12273          assign( sV, getXMMReg(eregOfRM(modrm)) );
12274          delta += 3+1;
12275          DIP("psign%s %s,%s\n", str, nameXMMReg(eregOfRM(modrm)),
12276                                      nameXMMReg(gregOfRM(modrm)));
12277       } else {
12278          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
12279          gen_SEGV_if_not_16_aligned( addr );
12280          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
12281          delta += 3+alen;
12282          DIP("psign%s %s,%s\n", str, dis_buf,
12283                                      nameXMMReg(gregOfRM(modrm)));
12284       }
12285
12286       assign( dHi, unop(Iop_V128HIto64, mkexpr(dV)) );
12287       assign( dLo, unop(Iop_V128to64,   mkexpr(dV)) );
12288       assign( sHi, unop(Iop_V128HIto64, mkexpr(sV)) );
12289       assign( sLo, unop(Iop_V128to64,   mkexpr(sV)) );
12290
12291       putXMMReg(
12292          gregOfRM(modrm),
12293          binop(Iop_64HLtoV128,
12294                dis_PSIGN_helper( mkexpr(sHi), mkexpr(dHi), laneszB ),
12295                dis_PSIGN_helper( mkexpr(sLo), mkexpr(dLo), laneszB )
12296          )
12297       );
12298       goto decode_success;
12299    }
12300
12301    /* 0F 38 1C = PABSB -- Packed Absolute Value 8x8  (MMX) */
12302    /* 0F 38 1D = PABSW -- Packed Absolute Value 16x4 (MMX) */
12303    /* 0F 38 1E = PABSD -- Packed Absolute Value 32x2 (MMX) */
12304    if (sz == 4 
12305        && insn[0] == 0x0F && insn[1] == 0x38 
12306        && (insn[2] == 0x1C || insn[2] == 0x1D || insn[2] == 0x1E)) {
12307       IRTemp sV      = newTemp(Ity_I64);
12308       HChar* str     = "???";
12309       Int    laneszB = 0;
12310
12311       switch (insn[2]) {
12312          case 0x1C: laneszB = 1; str = "b"; break;
12313          case 0x1D: laneszB = 2; str = "w"; break;
12314          case 0x1E: laneszB = 4; str = "d"; break;
12315          default: vassert(0);
12316       }
12317
12318       modrm = insn[3];
12319       do_MMX_preamble();
12320
12321       if (epartIsReg(modrm)) {
12322          assign( sV, getMMXReg(eregOfRM(modrm)) );
12323          delta += 3+1;
12324          DIP("pabs%s %s,%s\n", str, nameMMXReg(eregOfRM(modrm)),
12325                                     nameMMXReg(gregOfRM(modrm)));
12326       } else {
12327          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
12328          assign( sV, loadLE(Ity_I64, mkexpr(addr)) );
12329          delta += 3+alen;
12330          DIP("pabs%s %s,%s\n", str, dis_buf,
12331                                     nameMMXReg(gregOfRM(modrm)));
12332       }
12333
12334       putMMXReg(
12335          gregOfRM(modrm),
12336          dis_PABS_helper( mkexpr(sV), laneszB )
12337       );
12338       goto decode_success;
12339    }
12340
12341    /* 66 0F 38 1C = PABSB -- Packed Absolute Value 8x16 (XMM) */
12342    /* 66 0F 38 1D = PABSW -- Packed Absolute Value 16x8 (XMM) */
12343    /* 66 0F 38 1E = PABSD -- Packed Absolute Value 32x4 (XMM) */
12344    if (sz == 2
12345        && insn[0] == 0x0F && insn[1] == 0x38 
12346        && (insn[2] == 0x1C || insn[2] == 0x1D || insn[2] == 0x1E)) {
12347       IRTemp sV      = newTemp(Ity_V128);
12348       IRTemp sHi     = newTemp(Ity_I64);
12349       IRTemp sLo     = newTemp(Ity_I64);
12350       HChar* str     = "???";
12351       Int    laneszB = 0;
12352
12353       switch (insn[2]) {
12354          case 0x1C: laneszB = 1; str = "b"; break;
12355          case 0x1D: laneszB = 2; str = "w"; break;
12356          case 0x1E: laneszB = 4; str = "d"; break;
12357          default: vassert(0);
12358       }
12359
12360       modrm = insn[3];
12361
12362       if (epartIsReg(modrm)) {
12363          assign( sV, getXMMReg(eregOfRM(modrm)) );
12364          delta += 3+1;
12365          DIP("pabs%s %s,%s\n", str, nameXMMReg(eregOfRM(modrm)),
12366                                     nameXMMReg(gregOfRM(modrm)));
12367       } else {
12368          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
12369          gen_SEGV_if_not_16_aligned( addr );
12370          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
12371          delta += 3+alen;
12372          DIP("pabs%s %s,%s\n", str, dis_buf,
12373                                     nameXMMReg(gregOfRM(modrm)));
12374       }
12375
12376       assign( sHi, unop(Iop_V128HIto64, mkexpr(sV)) );
12377       assign( sLo, unop(Iop_V128to64,   mkexpr(sV)) );
12378
12379       putXMMReg(
12380          gregOfRM(modrm),
12381          binop(Iop_64HLtoV128,
12382                dis_PABS_helper( mkexpr(sHi), laneszB ),
12383                dis_PABS_helper( mkexpr(sLo), laneszB )
12384          )
12385       );
12386       goto decode_success;
12387    }
12388
12389    /* 0F 3A 0F = PALIGNR -- Packed Align Right (MMX) */
12390    if (sz == 4 
12391        && insn[0] == 0x0F && insn[1] == 0x3A && insn[2] == 0x0F) {
12392       IRTemp sV  = newTemp(Ity_I64);
12393       IRTemp dV  = newTemp(Ity_I64);
12394       IRTemp res = newTemp(Ity_I64);
12395
12396       modrm = insn[3];
12397       do_MMX_preamble();
12398       assign( dV, getMMXReg(gregOfRM(modrm)) );
12399
12400       if (epartIsReg(modrm)) {
12401          assign( sV, getMMXReg(eregOfRM(modrm)) );
12402          d32 = (UInt)insn[3+1];
12403          delta += 3+1+1;
12404          DIP("palignr $%d,%s,%s\n",  (Int)d32, 
12405                                      nameMMXReg(eregOfRM(modrm)),
12406                                      nameMMXReg(gregOfRM(modrm)));
12407       } else {
12408          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
12409          assign( sV, loadLE(Ity_I64, mkexpr(addr)) );
12410          d32 = (UInt)insn[3+alen];
12411          delta += 3+alen+1;
12412          DIP("palignr $%d%s,%s\n", (Int)d32,
12413                                    dis_buf,
12414                                    nameMMXReg(gregOfRM(modrm)));
12415       }
12416
12417       if (d32 == 0) {
12418          assign( res, mkexpr(sV) );
12419       }
12420       else if (d32 >= 1 && d32 <= 7) {
12421          assign(res, 
12422                 binop(Iop_Or64,
12423                       binop(Iop_Shr64, mkexpr(sV), mkU8(8*d32)),
12424                       binop(Iop_Shl64, mkexpr(dV), mkU8(8*(8-d32))
12425                      )));
12426       }
12427       else if (d32 == 8) {
12428         assign( res, mkexpr(dV) );
12429       }
12430       else if (d32 >= 9 && d32 <= 15) {
12431          assign( res, binop(Iop_Shr64, mkexpr(dV), mkU8(8*(d32-8))) );
12432       }
12433       else if (d32 >= 16 && d32 <= 255) {
12434          assign( res, mkU64(0) );
12435       }
12436       else
12437          vassert(0);
12438
12439       putMMXReg( gregOfRM(modrm), mkexpr(res) );
12440       goto decode_success;
12441    }
12442
12443    /* 66 0F 3A 0F = PALIGNR -- Packed Align Right (XMM) */
12444    if (sz == 2
12445        && insn[0] == 0x0F && insn[1] == 0x3A && insn[2] == 0x0F) {
12446       IRTemp sV  = newTemp(Ity_V128);
12447       IRTemp dV  = newTemp(Ity_V128);
12448       IRTemp sHi = newTemp(Ity_I64);
12449       IRTemp sLo = newTemp(Ity_I64);
12450       IRTemp dHi = newTemp(Ity_I64);
12451       IRTemp dLo = newTemp(Ity_I64);
12452       IRTemp rHi = newTemp(Ity_I64);
12453       IRTemp rLo = newTemp(Ity_I64);
12454
12455       modrm = insn[3];
12456       assign( dV, getXMMReg(gregOfRM(modrm)) );
12457
12458       if (epartIsReg(modrm)) {
12459          assign( sV, getXMMReg(eregOfRM(modrm)) );
12460          d32 = (UInt)insn[3+1];
12461          delta += 3+1+1;
12462          DIP("palignr $%d,%s,%s\n", (Int)d32,
12463                                     nameXMMReg(eregOfRM(modrm)),
12464                                     nameXMMReg(gregOfRM(modrm)));
12465       } else {
12466          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
12467          gen_SEGV_if_not_16_aligned( addr );
12468          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
12469          d32 = (UInt)insn[3+alen];
12470          delta += 3+alen+1;
12471          DIP("palignr $%d,%s,%s\n", (Int)d32,
12472                                     dis_buf,
12473                                     nameXMMReg(gregOfRM(modrm)));
12474       }
12475
12476       assign( dHi, unop(Iop_V128HIto64, mkexpr(dV)) );
12477       assign( dLo, unop(Iop_V128to64,   mkexpr(dV)) );
12478       assign( sHi, unop(Iop_V128HIto64, mkexpr(sV)) );
12479       assign( sLo, unop(Iop_V128to64,   mkexpr(sV)) );
12480
12481       if (d32 == 0) {
12482          assign( rHi, mkexpr(sHi) );
12483          assign( rLo, mkexpr(sLo) );
12484       }
12485       else if (d32 >= 1 && d32 <= 7) {
12486          assign( rHi, dis_PALIGNR_XMM_helper(dLo, sHi, d32) );
12487          assign( rLo, dis_PALIGNR_XMM_helper(sHi, sLo, d32) );
12488       }
12489       else if (d32 == 8) {
12490          assign( rHi, mkexpr(dLo) );
12491          assign( rLo, mkexpr(sHi) );
12492       }
12493       else if (d32 >= 9 && d32 <= 15) {
12494          assign( rHi, dis_PALIGNR_XMM_helper(dHi, dLo, d32-8) );
12495          assign( rLo, dis_PALIGNR_XMM_helper(dLo, sHi, d32-8) );
12496       }
12497       else if (d32 == 16) {
12498          assign( rHi, mkexpr(dHi) );
12499          assign( rLo, mkexpr(dLo) );
12500       }
12501       else if (d32 >= 17 && d32 <= 23) {
12502          assign( rHi, binop(Iop_Shr64, mkexpr(dHi), mkU8(8*(d32-16))) );
12503          assign( rLo, dis_PALIGNR_XMM_helper(dHi, dLo, d32-16) );
12504       }
12505       else if (d32 == 24) {
12506          assign( rHi, mkU64(0) );
12507          assign( rLo, mkexpr(dHi) );
12508       }
12509       else if (d32 >= 25 && d32 <= 31) {
12510          assign( rHi, mkU64(0) );
12511          assign( rLo, binop(Iop_Shr64, mkexpr(dHi), mkU8(8*(d32-24))) );
12512       }
12513       else if (d32 >= 32 && d32 <= 255) {
12514          assign( rHi, mkU64(0) );
12515          assign( rLo, mkU64(0) );
12516       }
12517       else
12518          vassert(0);
12519
12520       putXMMReg(
12521          gregOfRM(modrm),
12522          binop(Iop_64HLtoV128, mkexpr(rHi), mkexpr(rLo))
12523       );
12524       goto decode_success;
12525    }
12526
12527    /* 0F 38 00 = PSHUFB -- Packed Shuffle Bytes 8x8 (MMX) */
12528    if (sz == 4 
12529        && insn[0] == 0x0F && insn[1] == 0x38 && insn[2] == 0x00) {
12530       IRTemp sV      = newTemp(Ity_I64);
12531       IRTemp dV      = newTemp(Ity_I64);
12532
12533       modrm = insn[3];
12534       do_MMX_preamble();
12535       assign( dV, getMMXReg(gregOfRM(modrm)) );
12536
12537       if (epartIsReg(modrm)) {
12538          assign( sV, getMMXReg(eregOfRM(modrm)) );
12539          delta += 3+1;
12540          DIP("pshufb %s,%s\n", nameMMXReg(eregOfRM(modrm)),
12541                                nameMMXReg(gregOfRM(modrm)));
12542       } else {
12543          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
12544          assign( sV, loadLE(Ity_I64, mkexpr(addr)) );
12545          delta += 3+alen;
12546          DIP("pshufb %s,%s\n", dis_buf,
12547                                nameMMXReg(gregOfRM(modrm)));
12548       }
12549
12550       putMMXReg(
12551          gregOfRM(modrm),
12552          binop(
12553             Iop_And64,
12554             /* permute the lanes */
12555             binop(
12556                Iop_Perm8x8,
12557                mkexpr(dV),
12558                binop(Iop_And64, mkexpr(sV), mkU64(0x0707070707070707ULL))
12559             ),
12560             /* mask off lanes which have (index & 0x80) == 0x80 */
12561             unop(Iop_Not64, binop(Iop_SarN8x8, mkexpr(sV), mkU8(7)))
12562          )
12563       );
12564       goto decode_success;
12565    }
12566
12567    /* 66 0F 38 00 = PSHUFB -- Packed Shuffle Bytes 8x16 (XMM) */
12568    if (sz == 2
12569        && insn[0] == 0x0F && insn[1] == 0x38 && insn[2] == 0x00) {
12570       IRTemp sV         = newTemp(Ity_V128);
12571       IRTemp dV         = newTemp(Ity_V128);
12572       IRTemp sHi        = newTemp(Ity_I64);
12573       IRTemp sLo        = newTemp(Ity_I64);
12574       IRTemp dHi        = newTemp(Ity_I64);
12575       IRTemp dLo        = newTemp(Ity_I64);
12576       IRTemp rHi        = newTemp(Ity_I64);
12577       IRTemp rLo        = newTemp(Ity_I64);
12578       IRTemp sevens     = newTemp(Ity_I64);
12579       IRTemp mask0x80hi = newTemp(Ity_I64);
12580       IRTemp mask0x80lo = newTemp(Ity_I64);
12581       IRTemp maskBit3hi = newTemp(Ity_I64);
12582       IRTemp maskBit3lo = newTemp(Ity_I64);
12583       IRTemp sAnd7hi    = newTemp(Ity_I64);
12584       IRTemp sAnd7lo    = newTemp(Ity_I64);
12585       IRTemp permdHi    = newTemp(Ity_I64);
12586       IRTemp permdLo    = newTemp(Ity_I64);
12587
12588       modrm = insn[3];
12589       assign( dV, getXMMReg(gregOfRM(modrm)) );
12590
12591       if (epartIsReg(modrm)) {
12592          assign( sV, getXMMReg(eregOfRM(modrm)) );
12593          delta += 3+1;
12594          DIP("pshufb %s,%s\n", nameXMMReg(eregOfRM(modrm)),
12595                                nameXMMReg(gregOfRM(modrm)));
12596       } else {
12597          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
12598          gen_SEGV_if_not_16_aligned( addr );
12599          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
12600          delta += 3+alen;
12601          DIP("pshufb %s,%s\n", dis_buf,
12602                                nameXMMReg(gregOfRM(modrm)));
12603       }
12604
12605       assign( dHi, unop(Iop_V128HIto64, mkexpr(dV)) );
12606       assign( dLo, unop(Iop_V128to64,   mkexpr(dV)) );
12607       assign( sHi, unop(Iop_V128HIto64, mkexpr(sV)) );
12608       assign( sLo, unop(Iop_V128to64,   mkexpr(sV)) );
12609
12610       assign( sevens, mkU64(0x0707070707070707ULL) );
12611
12612       /*
12613       mask0x80hi = Not(SarN8x8(sHi,7))
12614       maskBit3hi = SarN8x8(ShlN8x8(sHi,4),7)
12615       sAnd7hi    = And(sHi,sevens)
12616       permdHi    = Or( And(Perm8x8(dHi,sAnd7hi),maskBit3hi),
12617                        And(Perm8x8(dLo,sAnd7hi),Not(maskBit3hi)) )
12618       rHi        = And(permdHi,mask0x80hi)
12619       */
12620       assign(
12621          mask0x80hi,
12622          unop(Iop_Not64, binop(Iop_SarN8x8,mkexpr(sHi),mkU8(7))));
12623
12624       assign(
12625          maskBit3hi,
12626          binop(Iop_SarN8x8,
12627                binop(Iop_ShlN8x8,mkexpr(sHi),mkU8(4)),
12628                mkU8(7)));
12629
12630       assign(sAnd7hi, binop(Iop_And64,mkexpr(sHi),mkexpr(sevens)));
12631
12632       assign(
12633          permdHi,
12634          binop(
12635             Iop_Or64,
12636             binop(Iop_And64,
12637                   binop(Iop_Perm8x8,mkexpr(dHi),mkexpr(sAnd7hi)),
12638                   mkexpr(maskBit3hi)),
12639             binop(Iop_And64,
12640                   binop(Iop_Perm8x8,mkexpr(dLo),mkexpr(sAnd7hi)),
12641                   unop(Iop_Not64,mkexpr(maskBit3hi))) ));
12642
12643       assign(rHi, binop(Iop_And64,mkexpr(permdHi),mkexpr(mask0x80hi)) );
12644
12645       /* And the same for the lower half of the result.  What fun. */
12646
12647       assign(
12648          mask0x80lo,
12649          unop(Iop_Not64, binop(Iop_SarN8x8,mkexpr(sLo),mkU8(7))));
12650
12651       assign(
12652          maskBit3lo,
12653          binop(Iop_SarN8x8,
12654                binop(Iop_ShlN8x8,mkexpr(sLo),mkU8(4)),
12655                mkU8(7)));
12656
12657       assign(sAnd7lo, binop(Iop_And64,mkexpr(sLo),mkexpr(sevens)));
12658
12659       assign(
12660          permdLo,
12661          binop(
12662             Iop_Or64,
12663             binop(Iop_And64,
12664                   binop(Iop_Perm8x8,mkexpr(dHi),mkexpr(sAnd7lo)),
12665                   mkexpr(maskBit3lo)),
12666             binop(Iop_And64,
12667                   binop(Iop_Perm8x8,mkexpr(dLo),mkexpr(sAnd7lo)),
12668                   unop(Iop_Not64,mkexpr(maskBit3lo))) ));
12669
12670       assign(rLo, binop(Iop_And64,mkexpr(permdLo),mkexpr(mask0x80lo)) );
12671
12672       putXMMReg(
12673          gregOfRM(modrm),
12674          binop(Iop_64HLtoV128, mkexpr(rHi), mkexpr(rLo))
12675       );
12676       goto decode_success;
12677    }
12678
12679    /* ---------------------------------------------------- */
12680    /* --- end of the SSSE3 decoder.                    --- */
12681    /* ---------------------------------------------------- */
12682
12683    /* ---------------------------------------------------- */
12684    /* --- start of the SSE4 decoder                    --- */
12685    /* ---------------------------------------------------- */
12686
12687    /* 66 0F 3A 0B /r ib = ROUNDSD imm8, xmm2/m64, xmm1
12688       (Partial implementation only -- only deal with cases where
12689       the rounding mode is specified directly by the immediate byte.)
12690       66 0F 3A 0A /r ib = ROUNDSS imm8, xmm2/m32, xmm1
12691       (Limitations ditto)
12692    */
12693    if (sz == 2 
12694        && insn[0] == 0x0F && insn[1] == 0x3A
12695        && (/*insn[2] == 0x0B || */insn[2] == 0x0A)) {
12696
12697       Bool   isD = insn[2] == 0x0B;
12698       IRTemp src = newTemp(isD ? Ity_F64 : Ity_F32);
12699       IRTemp res = newTemp(isD ? Ity_F64 : Ity_F32);
12700       Int    imm = 0;
12701
12702       modrm = insn[3];
12703
12704       if (epartIsReg(modrm)) {
12705          assign( src, 
12706                  isD ? getXMMRegLane64F( eregOfRM(modrm), 0 )
12707                      : getXMMRegLane32F( eregOfRM(modrm), 0 ) );
12708          imm = insn[3+1];
12709          if (imm & ~3) goto decode_failure;
12710          delta += 3+1+1;
12711          DIP( "rounds%c $%d,%s,%s\n",
12712               isD ? 'd' : 's',
12713               imm, nameXMMReg( eregOfRM(modrm) ),
12714                    nameXMMReg( gregOfRM(modrm) ) );
12715       } else {
12716          addr = disAMode( &alen, sorb, delta+3, dis_buf );
12717          assign( src, loadLE( isD ? Ity_F64 : Ity_F32, mkexpr(addr) ));
12718          imm = insn[3+alen];
12719          if (imm & ~3) goto decode_failure;
12720          delta += 3+alen+1;
12721          DIP( "roundsd $%d,%s,%s\n",
12722               imm, dis_buf, nameXMMReg( gregOfRM(modrm) ) );
12723       }
12724
12725       /* (imm & 3) contains an Intel-encoded rounding mode.  Because
12726          that encoding is the same as the encoding for IRRoundingMode,
12727          we can use that value directly in the IR as a rounding
12728          mode. */
12729       assign(res, binop(isD ? Iop_RoundF64toInt : Iop_RoundF32toInt,
12730                   mkU32(imm & 3), mkexpr(src)) );
12731
12732       if (isD)
12733          putXMMRegLane64F( gregOfRM(modrm), 0, mkexpr(res) );
12734       else
12735          putXMMRegLane32F( gregOfRM(modrm), 0, mkexpr(res) );
12736
12737       goto decode_success;
12738    }
12739
12740    /* F3 0F BD -- LZCNT (count leading zeroes.  An AMD extension,
12741       which we can only decode if we're sure this is an AMD cpu that
12742       supports LZCNT, since otherwise it's BSR, which behaves
12743       differently. */
12744    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0xBD
12745        && 0 != (archinfo->hwcaps & VEX_HWCAPS_X86_LZCNT)) {
12746       vassert(sz == 2 || sz == 4);
12747       /*IRType*/ ty  = szToITy(sz);
12748       IRTemp     src = newTemp(ty);
12749       modrm = insn[3];
12750       if (epartIsReg(modrm)) {
12751          assign(src, getIReg(sz, eregOfRM(modrm)));
12752          delta += 3+1;
12753          DIP("lzcnt%c %s, %s\n", nameISize(sz),
12754              nameIReg(sz, eregOfRM(modrm)),
12755              nameIReg(sz, gregOfRM(modrm)));
12756       } else {
12757          addr = disAMode( &alen, sorb, delta+3, dis_buf );
12758          assign(src, loadLE(ty, mkexpr(addr)));
12759          delta += 3+alen;
12760          DIP("lzcnt%c %s, %s\n", nameISize(sz), dis_buf,
12761              nameIReg(sz, gregOfRM(modrm)));
12762       }
12763
12764       IRTemp res = gen_LZCNT(ty, src);
12765       putIReg(sz, gregOfRM(modrm), mkexpr(res));
12766
12767       // Update flags.  This is pretty lame .. perhaps can do better
12768       // if this turns out to be performance critical.
12769       // O S A P are cleared.  Z is set if RESULT == 0.
12770       // C is set if SRC is zero.
12771       IRTemp src32 = newTemp(Ity_I32);
12772       IRTemp res32 = newTemp(Ity_I32);
12773       assign(src32, widenUto32(mkexpr(src)));
12774       assign(res32, widenUto32(mkexpr(res)));
12775
12776       IRTemp oszacp = newTemp(Ity_I32);
12777       assign(
12778          oszacp,
12779          binop(Iop_Or32,
12780                binop(Iop_Shl32,
12781                      unop(Iop_1Uto32,
12782                           binop(Iop_CmpEQ32, mkexpr(res32), mkU32(0))),
12783                      mkU8(X86G_CC_SHIFT_Z)),
12784                binop(Iop_Shl32,
12785                      unop(Iop_1Uto32,
12786                           binop(Iop_CmpEQ32, mkexpr(src32), mkU32(0))),
12787                      mkU8(X86G_CC_SHIFT_C))
12788          )
12789       );
12790
12791       stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(X86G_CC_OP_COPY) ));
12792       stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0) ));
12793       stmt( IRStmt_Put( OFFB_CC_NDEP, mkU32(0) ));
12794       stmt( IRStmt_Put( OFFB_CC_DEP1, mkexpr(oszacp) ));
12795
12796       goto decode_success;
12797    }
12798
12799    /* ---------------------------------------------------- */
12800    /* --- end of the SSE4 decoder                      --- */
12801    /* ---------------------------------------------------- */
12802
12803    after_sse_decoders:
12804
12805    /* ---------------------------------------------------- */
12806    /* --- deal with misc 0x67 pfxs (addr size override) -- */
12807    /* ---------------------------------------------------- */
12808
12809    /* 67 E3 = JCXZ (for JECXZ see below) */
12810    if (insn[0] == 0x67 && insn[1] == 0xE3 && sz == 4) {
12811       delta += 2;
12812       d32 = (((Addr32)guest_EIP_bbstart)+delta+1) + getSDisp8(delta);
12813       delta ++;
12814       stmt( IRStmt_Exit(
12815                binop(Iop_CmpEQ16, getIReg(2,R_ECX), mkU16(0)),
12816                Ijk_Boring,
12817                IRConst_U32(d32)
12818             ));
12819        DIP("jcxz 0x%x\n", d32);
12820        goto decode_success;
12821    }
12822
12823    /* ---------------------------------------------------- */
12824    /* --- start of the baseline insn decoder            -- */
12825    /* ---------------------------------------------------- */
12826
12827    /* Get the primary opcode. */
12828    opc = getIByte(delta); delta++;
12829
12830    /* We get here if the current insn isn't SSE, or this CPU doesn't
12831       support SSE. */
12832
12833    switch (opc) {
12834
12835    /* ------------------------ Control flow --------------- */
12836
12837    case 0xC2: /* RET imm16 */
12838       d32 = getUDisp16(delta); 
12839       delta += 2;
12840       dis_ret(d32);
12841       dres.whatNext = Dis_StopHere;
12842       DIP("ret %d\n", (Int)d32);
12843       break;
12844    case 0xC3: /* RET */
12845       dis_ret(0);
12846       dres.whatNext = Dis_StopHere;
12847       DIP("ret\n");
12848       break;
12849
12850    case 0xCF: /* IRET */
12851       /* Note, this is an extremely kludgey and limited implementation
12852          of iret.  All it really does is: 
12853             popl %EIP; popl %CS; popl %EFLAGS.
12854          %CS is set but ignored (as it is in (eg) popw %cs)". */
12855       t1 = newTemp(Ity_I32); /* ESP */
12856       t2 = newTemp(Ity_I32); /* new EIP */
12857       t3 = newTemp(Ity_I32); /* new CS */
12858       t4 = newTemp(Ity_I32); /* new EFLAGS */
12859       assign(t1, getIReg(4,R_ESP));
12860       assign(t2, loadLE(Ity_I32, binop(Iop_Add32,mkexpr(t1),mkU32(0) )));
12861       assign(t3, loadLE(Ity_I32, binop(Iop_Add32,mkexpr(t1),mkU32(4) )));
12862       assign(t4, loadLE(Ity_I32, binop(Iop_Add32,mkexpr(t1),mkU32(8) )));
12863       /* Get stuff off stack */
12864       putIReg(4, R_ESP,binop(Iop_Add32, mkexpr(t1), mkU32(12)));
12865       /* set %CS (which is ignored anyway) */
12866       putSReg( R_CS, unop(Iop_32to16, mkexpr(t3)) );
12867       /* set %EFLAGS */
12868       set_EFLAGS_from_value( t4, False/*!emit_AC_emwarn*/, 0/*unused*/ );
12869       /* goto new EIP value */
12870       jmp_treg(Ijk_Ret,t2);
12871       dres.whatNext = Dis_StopHere;
12872       DIP("iret (very kludgey)\n");
12873       break;
12874
12875    case 0xE8: /* CALL J4 */
12876       d32 = getUDisp32(delta); delta += 4;
12877       d32 += (guest_EIP_bbstart+delta); 
12878       /* (guest_eip_bbstart+delta) == return-to addr, d32 == call-to addr */
12879       if (d32 == guest_EIP_bbstart+delta && getIByte(delta) >= 0x58 
12880                                          && getIByte(delta) <= 0x5F) {
12881          /* Specially treat the position-independent-code idiom 
12882                  call X
12883               X: popl %reg
12884             as 
12885                  movl %eip, %reg.
12886             since this generates better code, but for no other reason. */
12887          Int archReg = getIByte(delta) - 0x58;
12888          /* vex_printf("-- fPIC thingy\n"); */
12889          putIReg(4, archReg, mkU32(guest_EIP_bbstart+delta));
12890          delta++; /* Step over the POP */
12891          DIP("call 0x%x ; popl %s\n",d32,nameIReg(4,archReg));
12892       } else {
12893          /* The normal sequence for a call. */
12894          t1 = newTemp(Ity_I32); 
12895          assign(t1, binop(Iop_Sub32, getIReg(4,R_ESP), mkU32(4)));
12896          putIReg(4, R_ESP, mkexpr(t1));
12897          storeLE( mkexpr(t1), mkU32(guest_EIP_bbstart+delta));
12898          if (resteerOkFn( callback_opaque, (Addr64)(Addr32)d32 )) {
12899             /* follow into the call target. */
12900             dres.whatNext   = Dis_ResteerU;
12901             dres.continueAt = (Addr64)(Addr32)d32;
12902          } else {
12903             jmp_lit(Ijk_Call,d32);
12904             dres.whatNext = Dis_StopHere;
12905          }
12906          DIP("call 0x%x\n",d32);
12907       }
12908       break;
12909
12910 //--    case 0xC8: /* ENTER */ 
12911 //--       d32 = getUDisp16(eip); eip += 2;
12912 //--       abyte = getIByte(delta); delta++;
12913 //-- 
12914 //--       vg_assert(sz == 4);           
12915 //--       vg_assert(abyte == 0);
12916 //-- 
12917 //--       t1 = newTemp(cb); t2 = newTemp(cb);
12918 //--       uInstr2(cb, GET,   sz, ArchReg, R_EBP, TempReg, t1);
12919 //--       uInstr2(cb, GET,    4, ArchReg, R_ESP, TempReg, t2);
12920 //--       uInstr2(cb, SUB,    4, Literal, 0,     TempReg, t2);
12921 //--       uLiteral(cb, sz);
12922 //--       uInstr2(cb, PUT,    4, TempReg, t2,    ArchReg, R_ESP);
12923 //--       uInstr2(cb, STORE,  4, TempReg, t1,    TempReg, t2);
12924 //--       uInstr2(cb, PUT,    4, TempReg, t2,    ArchReg, R_EBP);
12925 //--       if (d32) {
12926 //--          uInstr2(cb, SUB,    4, Literal, 0,     TempReg, t2);
12927 //--          uLiteral(cb, d32);
12928 //--          uInstr2(cb, PUT,    4, TempReg, t2,    ArchReg, R_ESP);
12929 //--       }
12930 //--       DIP("enter 0x%x, 0x%x", d32, abyte);
12931 //--       break;
12932
12933    case 0xC9: /* LEAVE */
12934       vassert(sz == 4);
12935       t1 = newTemp(Ity_I32); t2 = newTemp(Ity_I32);
12936       assign(t1, getIReg(4,R_EBP));
12937       /* First PUT ESP looks redundant, but need it because ESP must
12938          always be up-to-date for Memcheck to work... */
12939       putIReg(4, R_ESP, mkexpr(t1));
12940       assign(t2, loadLE(Ity_I32,mkexpr(t1)));
12941       putIReg(4, R_EBP, mkexpr(t2));
12942       putIReg(4, R_ESP, binop(Iop_Add32, mkexpr(t1), mkU32(4)) );
12943       DIP("leave\n");
12944       break;
12945
12946    /* ---------------- Misc weird-ass insns --------------- */
12947
12948    case 0x27: /* DAA */
12949    case 0x2F: /* DAS */
12950    case 0x37: /* AAA */
12951    case 0x3F: /* AAS */
12952       /* An ugly implementation for some ugly instructions.  Oh
12953          well. */
12954       if (sz != 4) goto decode_failure;
12955       t1 = newTemp(Ity_I32);
12956       t2 = newTemp(Ity_I32);
12957       /* Make up a 32-bit value (t1), with the old value of AX in the
12958          bottom 16 bits, and the old OSZACP bitmask in the upper 16
12959          bits. */
12960       assign(t1, 
12961              binop(Iop_16HLto32, 
12962                    unop(Iop_32to16,
12963                         mk_x86g_calculate_eflags_all()),
12964                    getIReg(2, R_EAX)
12965             ));
12966       /* Call the helper fn, to get a new AX and OSZACP value, and
12967          poke both back into the guest state.  Also pass the helper
12968          the actual opcode so it knows which of the 4 instructions it
12969          is doing the computation for. */
12970       vassert(opc == 0x27 || opc == 0x2F || opc == 0x37 || opc == 0x3F);
12971       assign(t2,
12972               mkIRExprCCall(
12973                  Ity_I32, 0/*regparm*/, "x86g_calculate_daa_das_aaa_aas",
12974                  &x86g_calculate_daa_das_aaa_aas,
12975                  mkIRExprVec_2( mkexpr(t1), mkU32( opc & 0xFF) )
12976             ));
12977      putIReg(2, R_EAX, unop(Iop_32to16, mkexpr(t2) ));
12978
12979      stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(X86G_CC_OP_COPY) ));
12980      stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0) ));
12981      stmt( IRStmt_Put( OFFB_CC_DEP1, 
12982                        binop(Iop_And32,
12983                              binop(Iop_Shr32, mkexpr(t2), mkU8(16)),
12984                              mkU32( X86G_CC_MASK_C | X86G_CC_MASK_P 
12985                                     | X86G_CC_MASK_A | X86G_CC_MASK_Z 
12986                                     | X86G_CC_MASK_S| X86G_CC_MASK_O )
12987                             )
12988                       )
12989          );
12990      /* Set NDEP even though it isn't used.  This makes redundant-PUT
12991         elimination of previous stores to this field work better. */
12992      stmt( IRStmt_Put( OFFB_CC_NDEP, mkU32(0) ));
12993      switch (opc) {
12994         case 0x27: DIP("daa\n"); break;
12995         case 0x2F: DIP("das\n"); break;
12996         case 0x37: DIP("aaa\n"); break;
12997         case 0x3F: DIP("aas\n"); break;
12998         default: vassert(0);
12999      }
13000      break;
13001
13002    case 0xD4: /* AAM */
13003    case 0xD5: /* AAD */
13004       d32 = getIByte(delta); delta++;
13005       if (sz != 4 || d32 != 10) goto decode_failure;
13006       t1 = newTemp(Ity_I32);
13007       t2 = newTemp(Ity_I32);
13008       /* Make up a 32-bit value (t1), with the old value of AX in the
13009          bottom 16 bits, and the old OSZACP bitmask in the upper 16
13010          bits. */
13011       assign(t1, 
13012              binop(Iop_16HLto32, 
13013                    unop(Iop_32to16,
13014                         mk_x86g_calculate_eflags_all()),
13015                    getIReg(2, R_EAX)
13016             ));
13017       /* Call the helper fn, to get a new AX and OSZACP value, and
13018          poke both back into the guest state.  Also pass the helper
13019          the actual opcode so it knows which of the 2 instructions it
13020          is doing the computation for. */
13021       assign(t2,
13022               mkIRExprCCall(
13023                  Ity_I32, 0/*regparm*/, "x86g_calculate_aad_aam",
13024                  &x86g_calculate_aad_aam,
13025                  mkIRExprVec_2( mkexpr(t1), mkU32( opc & 0xFF) )
13026             ));
13027       putIReg(2, R_EAX, unop(Iop_32to16, mkexpr(t2) ));
13028
13029       stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(X86G_CC_OP_COPY) ));
13030       stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0) ));
13031       stmt( IRStmt_Put( OFFB_CC_DEP1, 
13032                         binop(Iop_And32,
13033                               binop(Iop_Shr32, mkexpr(t2), mkU8(16)),
13034                               mkU32( X86G_CC_MASK_C | X86G_CC_MASK_P 
13035                                      | X86G_CC_MASK_A | X86G_CC_MASK_Z 
13036                                      | X86G_CC_MASK_S| X86G_CC_MASK_O )
13037                              )
13038                        )
13039           );
13040       /* Set NDEP even though it isn't used.  This makes
13041          redundant-PUT elimination of previous stores to this field
13042          work better. */
13043       stmt( IRStmt_Put( OFFB_CC_NDEP, mkU32(0) ));
13044
13045       DIP(opc == 0xD4 ? "aam\n" : "aad\n");
13046       break;
13047
13048    /* ------------------------ CWD/CDQ -------------------- */
13049
13050    case 0x98: /* CBW */
13051       if (sz == 4) {
13052          putIReg(4, R_EAX, unop(Iop_16Sto32, getIReg(2, R_EAX)));
13053          DIP("cwde\n");
13054       } else {
13055          vassert(sz == 2);
13056          putIReg(2, R_EAX, unop(Iop_8Sto16, getIReg(1, R_EAX)));
13057          DIP("cbw\n");
13058       }
13059       break;
13060
13061    case 0x99: /* CWD/CDQ */
13062       ty = szToITy(sz);
13063       putIReg(sz, R_EDX,
13064                   binop(mkSizedOp(ty,Iop_Sar8), 
13065                         getIReg(sz, R_EAX),
13066                         mkU8(sz == 2 ? 15 : 31)) );
13067       DIP(sz == 2 ? "cwdq\n" : "cdqq\n");
13068       break;
13069
13070    /* ------------------------ FPU ops -------------------- */
13071
13072    case 0x9E: /* SAHF */
13073       codegen_SAHF();
13074       DIP("sahf\n");
13075       break;
13076
13077    case 0x9F: /* LAHF */
13078       codegen_LAHF();
13079       DIP("lahf\n");
13080       break;
13081
13082    case 0x9B: /* FWAIT */
13083       /* ignore? */
13084       DIP("fwait\n");
13085       break;
13086
13087    case 0xD8:
13088    case 0xD9:
13089    case 0xDA:
13090    case 0xDB:
13091    case 0xDC:
13092    case 0xDD:
13093    case 0xDE:
13094    case 0xDF: {
13095       Int  delta0    = delta;
13096       Bool decode_OK = False;
13097       delta = dis_FPU ( &decode_OK, sorb, delta );
13098       if (!decode_OK) {
13099          delta = delta0;
13100          goto decode_failure;
13101       }
13102       break;
13103    }
13104
13105    /* ------------------------ INC & DEC ------------------ */
13106
13107    case 0x40: /* INC eAX */
13108    case 0x41: /* INC eCX */
13109    case 0x42: /* INC eDX */
13110    case 0x43: /* INC eBX */
13111    case 0x44: /* INC eSP */
13112    case 0x45: /* INC eBP */
13113    case 0x46: /* INC eSI */
13114    case 0x47: /* INC eDI */
13115       vassert(sz == 2 || sz == 4);
13116       ty = szToITy(sz);
13117       t1 = newTemp(ty);
13118       assign( t1, binop(mkSizedOp(ty,Iop_Add8),
13119                         getIReg(sz, (UInt)(opc - 0x40)),
13120                         mkU(ty,1)) );
13121       setFlags_INC_DEC( True, t1, ty );
13122       putIReg(sz, (UInt)(opc - 0x40), mkexpr(t1));
13123       DIP("inc%c %s\n", nameISize(sz), nameIReg(sz,opc-0x40));
13124       break;
13125
13126    case 0x48: /* DEC eAX */
13127    case 0x49: /* DEC eCX */
13128    case 0x4A: /* DEC eDX */
13129    case 0x4B: /* DEC eBX */
13130    case 0x4C: /* DEC eSP */
13131    case 0x4D: /* DEC eBP */
13132    case 0x4E: /* DEC eSI */
13133    case 0x4F: /* DEC eDI */
13134       vassert(sz == 2 || sz == 4);
13135       ty = szToITy(sz);
13136       t1 = newTemp(ty);
13137       assign( t1, binop(mkSizedOp(ty,Iop_Sub8),
13138                         getIReg(sz, (UInt)(opc - 0x48)),
13139                         mkU(ty,1)) );
13140       setFlags_INC_DEC( False, t1, ty );
13141       putIReg(sz, (UInt)(opc - 0x48), mkexpr(t1));
13142       DIP("dec%c %s\n", nameISize(sz), nameIReg(sz,opc-0x48));
13143       break;
13144
13145    /* ------------------------ INT ------------------------ */
13146
13147    case 0xCC: /* INT 3 */
13148       jmp_lit(Ijk_SigTRAP,((Addr32)guest_EIP_bbstart)+delta);
13149       dres.whatNext = Dis_StopHere;
13150       DIP("int $0x3\n");
13151       break;
13152
13153    case 0xCD: /* INT imm8 */
13154       d32 = getIByte(delta); delta++;
13155
13156       /* For any of the cases where we emit a jump (that is, for all
13157          currently handled cases), it's important that all ArchRegs
13158          carry their up-to-date value at this point.  So we declare an
13159          end-of-block here, which forces any TempRegs caching ArchRegs
13160          to be flushed. */
13161
13162       /* Handle int $0x30 (l4re syscall) */
13163       if (d32 == 0x30) {
13164           jmp_lit(Ijk_Sys_int48,((Addr32)guest_EIP_bbstart)+delta);
13165          dres.whatNext = Dis_StopHere;
13166          DIP("int $0x30\n");
13167          break;
13168       }
13169
13170       /* Handle int $0x32 (l4re syscall) */
13171       if (d32 == 0x32) {
13172           jmp_lit(Ijk_Sys_int50,((Addr32)guest_EIP_bbstart)+delta);
13173          dres.whatNext = Dis_StopHere;
13174          DIP("int $0x32\n");
13175          break;
13176       }
13177
13178       /* Handle int $0x40 .. $0x43 by synthesising a segfault and a
13179          restart of this instruction (hence the "-2" two lines below,
13180          to get the restart EIP to be this instruction.  This is
13181          probably Linux-specific and it would be more correct to only
13182          do this if the VexAbiInfo says that is what we should do. */
13183       if (d32 >= 0x40 && d32 <= 0x43) {
13184          jmp_lit(Ijk_SigSEGV,((Addr32)guest_EIP_bbstart)+delta-2);
13185          dres.whatNext = Dis_StopHere;
13186          DIP("int $0x%x\n", (Int)d32);
13187          break;
13188       }
13189
13190       /* Handle int $0x80 (linux syscalls), int $0x81 and $0x82
13191          (darwin syscalls).  As part of this, note where we are, so we
13192          can back up the guest to this point if the syscall needs to
13193          be restarted. */
13194       if (d32 == 0x80) {
13195          stmt( IRStmt_Put( OFFB_IP_AT_SYSCALL,
13196                            mkU32(guest_EIP_curr_instr) ) );
13197          jmp_lit(Ijk_Sys_int128,((Addr32)guest_EIP_bbstart)+delta);
13198          dres.whatNext = Dis_StopHere;
13199          DIP("int $0x80\n");
13200          break;
13201       }
13202       if (d32 == 0x81) {
13203          stmt( IRStmt_Put( OFFB_IP_AT_SYSCALL,
13204                            mkU32(guest_EIP_curr_instr) ) );
13205          jmp_lit(Ijk_Sys_int129,((Addr32)guest_EIP_bbstart)+delta);
13206          dres.whatNext = Dis_StopHere;
13207          DIP("int $0x81\n");
13208          break;
13209       }
13210       if (d32 == 0x82) {
13211          stmt( IRStmt_Put( OFFB_IP_AT_SYSCALL,
13212                            mkU32(guest_EIP_curr_instr) ) );
13213          jmp_lit(Ijk_Sys_int130,((Addr32)guest_EIP_bbstart)+delta);
13214          dres.whatNext = Dis_StopHere;
13215          DIP("int $0x82\n");
13216          break;
13217       }
13218
13219       /* none of the above */
13220       goto decode_failure;
13221
13222    /* ------------------------ Jcond, byte offset --------- */
13223
13224    case 0xEB: /* Jb (jump, byte offset) */
13225       d32 = (((Addr32)guest_EIP_bbstart)+delta+1) + getSDisp8(delta); 
13226       delta++;
13227       if (resteerOkFn( callback_opaque, (Addr64)(Addr32)d32) ) {
13228          dres.whatNext   = Dis_ResteerU;
13229          dres.continueAt = (Addr64)(Addr32)d32;
13230       } else {
13231          jmp_lit(Ijk_Boring,d32);
13232          dres.whatNext = Dis_StopHere;
13233       }
13234       DIP("jmp-8 0x%x\n", d32);
13235       break;
13236
13237    case 0xE9: /* Jv (jump, 16/32 offset) */
13238       vassert(sz == 4); /* JRS added 2004 July 11 */
13239       d32 = (((Addr32)guest_EIP_bbstart)+delta+sz) + getSDisp(sz,delta); 
13240       delta += sz;
13241       if (resteerOkFn( callback_opaque, (Addr64)(Addr32)d32) ) {
13242          dres.whatNext   = Dis_ResteerU;
13243          dres.continueAt = (Addr64)(Addr32)d32;
13244       } else {
13245          jmp_lit(Ijk_Boring,d32);
13246          dres.whatNext = Dis_StopHere;
13247       }
13248       DIP("jmp 0x%x\n", d32);
13249       break;
13250
13251    case 0x70:
13252    case 0x71:
13253    case 0x72: /* JBb/JNAEb (jump below) */
13254    case 0x73: /* JNBb/JAEb (jump not below) */
13255    case 0x74: /* JZb/JEb (jump zero) */
13256    case 0x75: /* JNZb/JNEb (jump not zero) */
13257    case 0x76: /* JBEb/JNAb (jump below or equal) */
13258    case 0x77: /* JNBEb/JAb (jump not below or equal) */
13259    case 0x78: /* JSb (jump negative) */
13260    case 0x79: /* JSb (jump not negative) */
13261    case 0x7A: /* JP (jump parity even) */
13262    case 0x7B: /* JNP/JPO (jump parity odd) */
13263    case 0x7C: /* JLb/JNGEb (jump less) */
13264    case 0x7D: /* JGEb/JNLb (jump greater or equal) */
13265    case 0x7E: /* JLEb/JNGb (jump less or equal) */
13266    case 0x7F: /* JGb/JNLEb (jump greater) */
13267     { Int    jmpDelta;
13268       HChar* comment  = "";
13269       jmpDelta = (Int)getSDisp8(delta);
13270       vassert(-128 <= jmpDelta && jmpDelta < 128);
13271       d32 = (((Addr32)guest_EIP_bbstart)+delta+1) + jmpDelta; 
13272       delta++;
13273       if (resteerCisOk
13274           && vex_control.guest_chase_cond
13275           && (Addr32)d32 != (Addr32)guest_EIP_bbstart
13276           && jmpDelta < 0
13277           && resteerOkFn( callback_opaque, (Addr64)(Addr32)d32) ) {
13278          /* Speculation: assume this backward branch is taken.  So we
13279             need to emit a side-exit to the insn following this one,
13280             on the negation of the condition, and continue at the
13281             branch target address (d32).  If we wind up back at the
13282             first instruction of the trace, just stop; it's better to
13283             let the IR loop unroller handle that case. */
13284          stmt( IRStmt_Exit( 
13285                   mk_x86g_calculate_condition((X86Condcode)(1 ^ (opc - 0x70))),
13286                   Ijk_Boring,
13287                   IRConst_U32(guest_EIP_bbstart+delta) ) );
13288          dres.whatNext   = Dis_ResteerC;
13289          dres.continueAt = (Addr64)(Addr32)d32;
13290          comment = "(assumed taken)";
13291       }
13292       else
13293       if (resteerCisOk
13294           && vex_control.guest_chase_cond
13295           && (Addr32)d32 != (Addr32)guest_EIP_bbstart
13296           && jmpDelta >= 0
13297           && resteerOkFn( callback_opaque, 
13298                           (Addr64)(Addr32)(guest_EIP_bbstart+delta)) ) {
13299          /* Speculation: assume this forward branch is not taken.  So
13300             we need to emit a side-exit to d32 (the dest) and continue
13301             disassembling at the insn immediately following this
13302             one. */
13303          stmt( IRStmt_Exit( 
13304                   mk_x86g_calculate_condition((X86Condcode)(opc - 0x70)),
13305                   Ijk_Boring,
13306                   IRConst_U32(d32) ) );
13307          dres.whatNext   = Dis_ResteerC;
13308          dres.continueAt = (Addr64)(Addr32)(guest_EIP_bbstart+delta);
13309          comment = "(assumed not taken)";
13310       }
13311       else {
13312          /* Conservative default translation - end the block at this
13313             point. */
13314          jcc_01( (X86Condcode)(opc - 0x70), 
13315                  (Addr32)(guest_EIP_bbstart+delta), d32);
13316          dres.whatNext = Dis_StopHere;
13317       }
13318       DIP("j%s-8 0x%x %s\n", name_X86Condcode(opc - 0x70), d32, comment);
13319       break;
13320     }
13321
13322    case 0xE3: /* JECXZ (for JCXZ see above) */
13323       if (sz != 4) goto decode_failure;
13324       d32 = (((Addr32)guest_EIP_bbstart)+delta+1) + getSDisp8(delta);
13325       delta ++;
13326       stmt( IRStmt_Exit(
13327                binop(Iop_CmpEQ32, getIReg(4,R_ECX), mkU32(0)),
13328             Ijk_Boring,
13329             IRConst_U32(d32)
13330           ));
13331       DIP("jecxz 0x%x\n", d32);
13332       break;
13333
13334    case 0xE0: /* LOOPNE disp8: decrement count, jump if count != 0 && ZF==0 */
13335    case 0xE1: /* LOOPE  disp8: decrement count, jump if count != 0 && ZF==1 */
13336    case 0xE2: /* LOOP   disp8: decrement count, jump if count != 0 */
13337     { /* Again, the docs say this uses ECX/CX as a count depending on
13338          the address size override, not the operand one.  Since we
13339          don't handle address size overrides, I guess that means
13340          ECX. */
13341       IRExpr* zbit  = NULL;
13342       IRExpr* count = NULL;
13343       IRExpr* cond  = NULL;
13344       HChar*  xtra  = NULL;
13345
13346       if (sz != 4) goto decode_failure;
13347       d32 = (((Addr32)guest_EIP_bbstart)+delta+1) + getSDisp8(delta);
13348       delta++;
13349       putIReg(4, R_ECX, binop(Iop_Sub32, getIReg(4,R_ECX), mkU32(1)));
13350
13351       count = getIReg(4,R_ECX);
13352       cond = binop(Iop_CmpNE32, count, mkU32(0));
13353       switch (opc) {
13354          case 0xE2: 
13355             xtra = ""; 
13356             break;
13357          case 0xE1: 
13358             xtra = "e"; 
13359             zbit = mk_x86g_calculate_condition( X86CondZ );
13360             cond = mkAnd1(cond, zbit);
13361             break;
13362          case 0xE0: 
13363             xtra = "ne";
13364             zbit = mk_x86g_calculate_condition( X86CondNZ );
13365             cond = mkAnd1(cond, zbit);
13366             break;
13367          default:
13368             vassert(0);
13369       }
13370       stmt( IRStmt_Exit(cond, Ijk_Boring, IRConst_U32(d32)) );
13371
13372       DIP("loop%s 0x%x\n", xtra, d32);
13373       break;
13374     }
13375
13376    /* ------------------------ IMUL ----------------------- */
13377
13378    case 0x69: /* IMUL Iv, Ev, Gv */
13379       delta = dis_imul_I_E_G ( sorb, sz, delta, sz );
13380       break;
13381    case 0x6B: /* IMUL Ib, Ev, Gv */
13382       delta = dis_imul_I_E_G ( sorb, sz, delta, 1 );
13383       break;
13384
13385    /* ------------------------ MOV ------------------------ */
13386
13387    case 0x88: /* MOV Gb,Eb */
13388       delta = dis_mov_G_E(sorb, 1, delta);
13389       break;
13390
13391    case 0x89: /* MOV Gv,Ev */
13392       delta = dis_mov_G_E(sorb, sz, delta);
13393       break;
13394
13395    case 0x8A: /* MOV Eb,Gb */
13396       delta = dis_mov_E_G(sorb, 1, delta);
13397       break;
13398  
13399    case 0x8B: /* MOV Ev,Gv */
13400       delta = dis_mov_E_G(sorb, sz, delta);
13401       break;
13402  
13403    case 0x8D: /* LEA M,Gv */
13404       if (sz != 4)
13405          goto decode_failure;
13406       modrm = getIByte(delta);
13407       if (epartIsReg(modrm)) 
13408          goto decode_failure;
13409       /* NOTE!  this is the one place where a segment override prefix
13410          has no effect on the address calculation.  Therefore we pass
13411          zero instead of sorb here. */
13412       addr = disAMode ( &alen, /*sorb*/ 0, delta, dis_buf );
13413       delta += alen;
13414       putIReg(sz, gregOfRM(modrm), mkexpr(addr));
13415       DIP("lea%c %s, %s\n", nameISize(sz), dis_buf, 
13416                             nameIReg(sz,gregOfRM(modrm)));
13417       break;
13418
13419    case 0x8C: /* MOV Sw,Ew -- MOV from a SEGMENT REGISTER */
13420       delta = dis_mov_Sw_Ew(sorb, sz, delta);
13421       break;
13422
13423    case 0x8E: /* MOV Ew,Sw -- MOV to a SEGMENT REGISTER */
13424       delta = dis_mov_Ew_Sw(sorb, delta);
13425       break;
13426  
13427    case 0xA0: /* MOV Ob,AL */
13428       sz = 1;
13429       /* Fall through ... */
13430    case 0xA1: /* MOV Ov,eAX */
13431       d32 = getUDisp32(delta); delta += 4;
13432       ty = szToITy(sz);
13433       addr = newTemp(Ity_I32);
13434       assign( addr, handleSegOverride(sorb, mkU32(d32)) );
13435       putIReg(sz, R_EAX, loadLE(ty, mkexpr(addr)));
13436       DIP("mov%c %s0x%x, %s\n", nameISize(sz), sorbTxt(sorb),
13437                                 d32, nameIReg(sz,R_EAX));
13438       break;
13439
13440    case 0xA2: /* MOV Ob,AL */
13441       sz = 1;
13442       /* Fall through ... */
13443    case 0xA3: /* MOV eAX,Ov */
13444       d32 = getUDisp32(delta); delta += 4;
13445       ty = szToITy(sz);
13446       addr = newTemp(Ity_I32);
13447       assign( addr, handleSegOverride(sorb, mkU32(d32)) );
13448       storeLE( mkexpr(addr), getIReg(sz,R_EAX) );
13449       DIP("mov%c %s, %s0x%x\n", nameISize(sz), nameIReg(sz,R_EAX),
13450                                 sorbTxt(sorb), d32);
13451       break;
13452
13453    case 0xB0: /* MOV imm,AL */
13454    case 0xB1: /* MOV imm,CL */
13455    case 0xB2: /* MOV imm,DL */
13456    case 0xB3: /* MOV imm,BL */
13457    case 0xB4: /* MOV imm,AH */
13458    case 0xB5: /* MOV imm,CH */
13459    case 0xB6: /* MOV imm,DH */
13460    case 0xB7: /* MOV imm,BH */
13461       d32 = getIByte(delta); delta += 1;
13462       putIReg(1, opc-0xB0, mkU8(d32));
13463       DIP("movb $0x%x,%s\n", d32, nameIReg(1,opc-0xB0));
13464       break;
13465
13466    case 0xB8: /* MOV imm,eAX */
13467    case 0xB9: /* MOV imm,eCX */
13468    case 0xBA: /* MOV imm,eDX */
13469    case 0xBB: /* MOV imm,eBX */
13470    case 0xBC: /* MOV imm,eSP */
13471    case 0xBD: /* MOV imm,eBP */
13472    case 0xBE: /* MOV imm,eSI */
13473    case 0xBF: /* MOV imm,eDI */
13474       d32 = getUDisp(sz,delta); delta += sz;
13475       putIReg(sz, opc-0xB8, mkU(szToITy(sz), d32));
13476       DIP("mov%c $0x%x,%s\n", nameISize(sz), d32, nameIReg(sz,opc-0xB8));
13477       break;
13478
13479    case 0xC6: /* MOV Ib,Eb */
13480       sz = 1;
13481       goto do_Mov_I_E;
13482    case 0xC7: /* MOV Iv,Ev */
13483       goto do_Mov_I_E;
13484
13485    do_Mov_I_E:
13486       modrm = getIByte(delta);
13487       if (epartIsReg(modrm)) {
13488          delta++; /* mod/rm byte */
13489          d32 = getUDisp(sz,delta); delta += sz;
13490          putIReg(sz, eregOfRM(modrm), mkU(szToITy(sz), d32));
13491          DIP("mov%c $0x%x, %s\n", nameISize(sz), d32, 
13492                                   nameIReg(sz,eregOfRM(modrm)));
13493       } else {
13494          addr = disAMode ( &alen, sorb, delta, dis_buf );
13495          delta += alen;
13496          d32 = getUDisp(sz,delta); delta += sz;
13497          storeLE(mkexpr(addr), mkU(szToITy(sz), d32));
13498          DIP("mov%c $0x%x, %s\n", nameISize(sz), d32, dis_buf);
13499       }
13500       break;
13501
13502    /* ------------------------ opl imm, A ----------------- */
13503
13504    case 0x04: /* ADD Ib, AL */
13505       delta = dis_op_imm_A(  1, False, Iop_Add8, True, delta, "add" );
13506       break;
13507    case 0x05: /* ADD Iv, eAX */
13508       delta = dis_op_imm_A( sz, False, Iop_Add8, True, delta, "add" );
13509       break;
13510
13511    case 0x0C: /* OR Ib, AL */
13512       delta = dis_op_imm_A(  1, False, Iop_Or8, True, delta, "or" );
13513       break;
13514    case 0x0D: /* OR Iv, eAX */
13515       delta = dis_op_imm_A( sz, False, Iop_Or8, True, delta, "or" );
13516       break;
13517
13518    case 0x14: /* ADC Ib, AL */
13519       delta = dis_op_imm_A(  1, True, Iop_Add8, True, delta, "adc" );
13520       break;
13521    case 0x15: /* ADC Iv, eAX */
13522       delta = dis_op_imm_A( sz, True, Iop_Add8, True, delta, "adc" );
13523       break;
13524
13525    case 0x1C: /* SBB Ib, AL */
13526       delta = dis_op_imm_A( 1, True, Iop_Sub8, True, delta, "sbb" );
13527       break;
13528    case 0x1D: /* SBB Iv, eAX */
13529       delta = dis_op_imm_A( sz, True, Iop_Sub8, True, delta, "sbb" );
13530       break;
13531
13532    case 0x24: /* AND Ib, AL */
13533       delta = dis_op_imm_A(  1, False, Iop_And8, True, delta, "and" );
13534       break;
13535    case 0x25: /* AND Iv, eAX */
13536       delta = dis_op_imm_A( sz, False, Iop_And8, True, delta, "and" );
13537       break;
13538
13539    case 0x2C: /* SUB Ib, AL */
13540       delta = dis_op_imm_A(  1, False, Iop_Sub8, True, delta, "sub" );
13541       break;
13542    case 0x2D: /* SUB Iv, eAX */
13543       delta = dis_op_imm_A( sz, False, Iop_Sub8, True, delta, "sub" );
13544       break;
13545
13546    case 0x34: /* XOR Ib, AL */
13547       delta = dis_op_imm_A(  1, False, Iop_Xor8, True, delta, "xor" );
13548       break;
13549    case 0x35: /* XOR Iv, eAX */
13550       delta = dis_op_imm_A( sz, False, Iop_Xor8, True, delta, "xor" );
13551       break;
13552
13553    case 0x3C: /* CMP Ib, AL */
13554       delta = dis_op_imm_A(  1, False, Iop_Sub8, False, delta, "cmp" );
13555       break;
13556    case 0x3D: /* CMP Iv, eAX */
13557       delta = dis_op_imm_A( sz, False, Iop_Sub8, False, delta, "cmp" );
13558       break;
13559
13560    case 0xA8: /* TEST Ib, AL */
13561       delta = dis_op_imm_A(  1, False, Iop_And8, False, delta, "test" );
13562       break;
13563    case 0xA9: /* TEST Iv, eAX */
13564       delta = dis_op_imm_A( sz, False, Iop_And8, False, delta, "test" );
13565       break;
13566
13567    /* ------------------------ opl Ev, Gv ----------------- */
13568  
13569    case 0x02: /* ADD Eb,Gb */
13570       delta = dis_op2_E_G ( sorb, False, Iop_Add8, True, 1, delta, "add" );
13571       break;
13572    case 0x03: /* ADD Ev,Gv */
13573       delta = dis_op2_E_G ( sorb, False, Iop_Add8, True, sz, delta, "add" );
13574       break;
13575
13576    case 0x0A: /* OR Eb,Gb */
13577       delta = dis_op2_E_G ( sorb, False, Iop_Or8, True, 1, delta, "or" );
13578       break;
13579    case 0x0B: /* OR Ev,Gv */
13580       delta = dis_op2_E_G ( sorb, False, Iop_Or8, True, sz, delta, "or" );
13581       break;
13582
13583    case 0x12: /* ADC Eb,Gb */
13584       delta = dis_op2_E_G ( sorb, True, Iop_Add8, True, 1, delta, "adc" );
13585       break;
13586    case 0x13: /* ADC Ev,Gv */
13587       delta = dis_op2_E_G ( sorb, True, Iop_Add8, True, sz, delta, "adc" );
13588       break;
13589
13590    case 0x1A: /* SBB Eb,Gb */
13591       delta = dis_op2_E_G ( sorb, True, Iop_Sub8, True, 1, delta, "sbb" );
13592       break;
13593    case 0x1B: /* SBB Ev,Gv */
13594       delta = dis_op2_E_G ( sorb, True, Iop_Sub8, True, sz, delta, "sbb" );
13595       break;
13596
13597    case 0x22: /* AND Eb,Gb */
13598       delta = dis_op2_E_G ( sorb, False, Iop_And8, True, 1, delta, "and" );
13599       break;
13600    case 0x23: /* AND Ev,Gv */
13601       delta = dis_op2_E_G ( sorb, False, Iop_And8, True, sz, delta, "and" );
13602       break;
13603
13604    case 0x2A: /* SUB Eb,Gb */
13605       delta = dis_op2_E_G ( sorb, False, Iop_Sub8, True, 1, delta, "sub" );
13606       break;
13607    case 0x2B: /* SUB Ev,Gv */
13608       delta = dis_op2_E_G ( sorb, False, Iop_Sub8, True, sz, delta, "sub" );
13609       break;
13610
13611    case 0x32: /* XOR Eb,Gb */
13612       delta = dis_op2_E_G ( sorb, False, Iop_Xor8, True, 1, delta, "xor" );
13613       break;
13614    case 0x33: /* XOR Ev,Gv */
13615       delta = dis_op2_E_G ( sorb, False, Iop_Xor8, True, sz, delta, "xor" );
13616       break;
13617
13618    case 0x3A: /* CMP Eb,Gb */
13619       delta = dis_op2_E_G ( sorb, False, Iop_Sub8, False, 1, delta, "cmp" );
13620       break;
13621    case 0x3B: /* CMP Ev,Gv */
13622       delta = dis_op2_E_G ( sorb, False, Iop_Sub8, False, sz, delta, "cmp" );
13623       break;
13624
13625    case 0x84: /* TEST Eb,Gb */
13626       delta = dis_op2_E_G ( sorb, False, Iop_And8, False, 1, delta, "test" );
13627       break;
13628    case 0x85: /* TEST Ev,Gv */
13629       delta = dis_op2_E_G ( sorb, False, Iop_And8, False, sz, delta, "test" );
13630       break;
13631
13632    /* ------------------------ opl Gv, Ev ----------------- */
13633
13634    case 0x00: /* ADD Gb,Eb */
13635       delta = dis_op2_G_E ( sorb, pfx_lock, False,
13636                             Iop_Add8, True, 1, delta, "add" );
13637       break;
13638    case 0x01: /* ADD Gv,Ev */
13639       delta = dis_op2_G_E ( sorb, pfx_lock, False,
13640                             Iop_Add8, True, sz, delta, "add" );
13641       break;
13642
13643    case 0x08: /* OR Gb,Eb */
13644       delta = dis_op2_G_E ( sorb, pfx_lock, False,
13645                             Iop_Or8, True, 1, delta, "or" );
13646       break;
13647    case 0x09: /* OR Gv,Ev */
13648       delta = dis_op2_G_E ( sorb, pfx_lock, False,
13649                             Iop_Or8, True, sz, delta, "or" );
13650       break;
13651
13652    case 0x10: /* ADC Gb,Eb */
13653       delta = dis_op2_G_E ( sorb, pfx_lock, True,
13654                             Iop_Add8, True, 1, delta, "adc" );
13655       break;
13656    case 0x11: /* ADC Gv,Ev */
13657       delta = dis_op2_G_E ( sorb, pfx_lock, True,
13658                             Iop_Add8, True, sz, delta, "adc" );
13659       break;
13660
13661    case 0x18: /* SBB Gb,Eb */
13662       delta = dis_op2_G_E ( sorb, pfx_lock, True,
13663                             Iop_Sub8, True, 1, delta, "sbb" );
13664       break;
13665    case 0x19: /* SBB Gv,Ev */
13666       delta = dis_op2_G_E ( sorb, pfx_lock, True,
13667                             Iop_Sub8, True, sz, delta, "sbb" );
13668       break;
13669
13670    case 0x20: /* AND Gb,Eb */
13671       delta = dis_op2_G_E ( sorb, pfx_lock, False,
13672                             Iop_And8, True, 1, delta, "and" );
13673       break;
13674    case 0x21: /* AND Gv,Ev */
13675       delta = dis_op2_G_E ( sorb, pfx_lock, False,
13676                             Iop_And8, True, sz, delta, "and" );
13677       break;
13678
13679    case 0x28: /* SUB Gb,Eb */
13680       delta = dis_op2_G_E ( sorb, pfx_lock, False,
13681                             Iop_Sub8, True, 1, delta, "sub" );
13682       break;
13683    case 0x29: /* SUB Gv,Ev */
13684       delta = dis_op2_G_E ( sorb, pfx_lock, False,
13685                             Iop_Sub8, True, sz, delta, "sub" );
13686       break;
13687
13688    case 0x30: /* XOR Gb,Eb */
13689       delta = dis_op2_G_E ( sorb, pfx_lock, False,
13690                             Iop_Xor8, True, 1, delta, "xor" );
13691       break;
13692    case 0x31: /* XOR Gv,Ev */
13693       delta = dis_op2_G_E ( sorb, pfx_lock, False,
13694                             Iop_Xor8, True, sz, delta, "xor" );
13695       break;
13696
13697    case 0x38: /* CMP Gb,Eb */
13698       delta = dis_op2_G_E ( sorb, pfx_lock, False,
13699                             Iop_Sub8, False, 1, delta, "cmp" );
13700       break;
13701    case 0x39: /* CMP Gv,Ev */
13702       delta = dis_op2_G_E ( sorb, pfx_lock, False,
13703                             Iop_Sub8, False, sz, delta, "cmp" );
13704       break;
13705
13706    /* ------------------------ POP ------------------------ */
13707
13708    case 0x58: /* POP eAX */
13709    case 0x59: /* POP eCX */
13710    case 0x5A: /* POP eDX */
13711    case 0x5B: /* POP eBX */
13712    case 0x5D: /* POP eBP */
13713    case 0x5E: /* POP eSI */
13714    case 0x5F: /* POP eDI */
13715    case 0x5C: /* POP eSP */
13716       vassert(sz == 2 || sz == 4);
13717       t1 = newTemp(szToITy(sz)); t2 = newTemp(Ity_I32);
13718       assign(t2, getIReg(4, R_ESP));
13719       assign(t1, loadLE(szToITy(sz),mkexpr(t2)));
13720       putIReg(4, R_ESP, binop(Iop_Add32, mkexpr(t2), mkU32(sz)));
13721       putIReg(sz, opc-0x58, mkexpr(t1));
13722       DIP("pop%c %s\n", nameISize(sz), nameIReg(sz,opc-0x58));
13723       break;
13724
13725    case 0x9D: /* POPF */
13726       vassert(sz == 2 || sz == 4);
13727       t1 = newTemp(Ity_I32); t2 = newTemp(Ity_I32);
13728       assign(t2, getIReg(4, R_ESP));
13729       assign(t1, widenUto32(loadLE(szToITy(sz),mkexpr(t2))));
13730       putIReg(4, R_ESP, binop(Iop_Add32, mkexpr(t2), mkU32(sz)));
13731
13732       /* Generate IR to set %EFLAGS{O,S,Z,A,C,P,D,ID,AC} from the
13733          value in t1. */
13734       set_EFLAGS_from_value( t1, True/*emit_AC_emwarn*/,
13735                                  ((Addr32)guest_EIP_bbstart)+delta );
13736
13737       DIP("popf%c\n", nameISize(sz));
13738       break;
13739
13740    case 0x61: /* POPA */
13741       /* This is almost certainly wrong for sz==2.  So ... */
13742       if (sz != 4) goto decode_failure;
13743
13744       /* t5 is the old %ESP value. */
13745       t5 = newTemp(Ity_I32);
13746       assign( t5, getIReg(4, R_ESP) );
13747
13748       /* Reload all the registers, except %esp. */
13749       putIReg(4,R_EAX, loadLE(Ity_I32, binop(Iop_Add32,mkexpr(t5),mkU32(28)) ));
13750       putIReg(4,R_ECX, loadLE(Ity_I32, binop(Iop_Add32,mkexpr(t5),mkU32(24)) ));
13751       putIReg(4,R_EDX, loadLE(Ity_I32, binop(Iop_Add32,mkexpr(t5),mkU32(20)) ));
13752       putIReg(4,R_EBX, loadLE(Ity_I32, binop(Iop_Add32,mkexpr(t5),mkU32(16)) ));
13753       /* ignore saved %ESP */
13754       putIReg(4,R_EBP, loadLE(Ity_I32, binop(Iop_Add32,mkexpr(t5),mkU32( 8)) ));
13755       putIReg(4,R_ESI, loadLE(Ity_I32, binop(Iop_Add32,mkexpr(t5),mkU32( 4)) ));
13756       putIReg(4,R_EDI, loadLE(Ity_I32, binop(Iop_Add32,mkexpr(t5),mkU32( 0)) ));
13757
13758       /* and move %ESP back up */
13759       putIReg( 4, R_ESP, binop(Iop_Add32, mkexpr(t5), mkU32(8*4)) );
13760
13761       DIP("popa%c\n", nameISize(sz));
13762       break;
13763
13764    case 0x8F: /* POPL/POPW m32 */
13765      { Int    len;
13766        UChar  rm = getIByte(delta);
13767
13768        /* make sure this instruction is correct POP */
13769        if (epartIsReg(rm) || gregOfRM(rm) != 0)
13770           goto decode_failure;
13771        /* and has correct size */
13772        if (sz != 4 && sz != 2)
13773           goto decode_failure;
13774        ty = szToITy(sz);
13775
13776        t1 = newTemp(Ity_I32); /* stack address */
13777        t3 = newTemp(ty); /* data */
13778        /* set t1 to ESP: t1 = ESP */
13779        assign( t1, getIReg(4, R_ESP) );
13780        /* load M[ESP] to virtual register t3: t3 = M[t1] */
13781        assign( t3, loadLE(ty, mkexpr(t1)) );
13782        
13783        /* increase ESP; must be done before the STORE.  Intel manual says:
13784             If the ESP register is used as a base register for addressing
13785             a destination operand in memory, the POP instruction computes
13786             the effective address of the operand after it increments the
13787             ESP register.
13788        */
13789        putIReg(4, R_ESP, binop(Iop_Add32, mkexpr(t1), mkU32(sz)) );
13790
13791        /* resolve MODR/M */
13792        addr = disAMode ( &len, sorb, delta, dis_buf);
13793        storeLE( mkexpr(addr), mkexpr(t3) );
13794
13795        DIP("pop%c %s\n", sz==2 ? 'w' : 'l', dis_buf);
13796
13797        delta += len;
13798        break;
13799      }
13800
13801    case 0x1F: /* POP %DS */
13802       dis_pop_segreg( R_DS, sz ); break;
13803    case 0x07: /* POP %ES */
13804       dis_pop_segreg( R_ES, sz ); break;
13805    case 0x17: /* POP %SS */
13806       dis_pop_segreg( R_SS, sz ); break;
13807
13808    /* ------------------------ PUSH ----------------------- */
13809
13810    case 0x50: /* PUSH eAX */
13811    case 0x51: /* PUSH eCX */
13812    case 0x52: /* PUSH eDX */
13813    case 0x53: /* PUSH eBX */
13814    case 0x55: /* PUSH eBP */
13815    case 0x56: /* PUSH eSI */
13816    case 0x57: /* PUSH eDI */
13817    case 0x54: /* PUSH eSP */
13818       /* This is the Right Way, in that the value to be pushed is
13819          established before %esp is changed, so that pushl %esp
13820          correctly pushes the old value. */
13821       vassert(sz == 2 || sz == 4);
13822       ty = sz==2 ? Ity_I16 : Ity_I32;
13823       t1 = newTemp(ty); t2 = newTemp(Ity_I32);
13824       assign(t1, getIReg(sz, opc-0x50));
13825       assign(t2, binop(Iop_Sub32, getIReg(4, R_ESP), mkU32(sz)));
13826       putIReg(4, R_ESP, mkexpr(t2) );
13827       storeLE(mkexpr(t2),mkexpr(t1));
13828       DIP("push%c %s\n", nameISize(sz), nameIReg(sz,opc-0x50));
13829       break;
13830
13831
13832    case 0x68: /* PUSH Iv */
13833       d32 = getUDisp(sz,delta); delta += sz;
13834       goto do_push_I;
13835    case 0x6A: /* PUSH Ib, sign-extended to sz */
13836       d32 = getSDisp8(delta); delta += 1;
13837       goto do_push_I;
13838    do_push_I:
13839       ty = szToITy(sz);
13840       t1 = newTemp(Ity_I32); t2 = newTemp(ty);
13841       assign( t1, binop(Iop_Sub32,getIReg(4,R_ESP),mkU32(sz)) );
13842       putIReg(4, R_ESP, mkexpr(t1) );
13843       /* stop mkU16 asserting if d32 is a negative 16-bit number
13844          (bug #132813) */
13845       if (ty == Ity_I16)
13846          d32 &= 0xFFFF;
13847       storeLE( mkexpr(t1), mkU(ty,d32) );
13848       DIP("push%c $0x%x\n", nameISize(sz), d32);
13849       break;
13850
13851    case 0x9C: /* PUSHF */ {
13852       vassert(sz == 2 || sz == 4);
13853
13854       t1 = newTemp(Ity_I32);
13855       assign( t1, binop(Iop_Sub32,getIReg(4,R_ESP),mkU32(sz)) );
13856       putIReg(4, R_ESP, mkexpr(t1) );
13857
13858       /* Calculate OSZACP, and patch in fixed fields as per
13859          Intel docs. 
13860          - bit 1 is always 1
13861          - bit 9 is Interrupt Enable (should always be 1 in user mode?)
13862       */
13863       t2 = newTemp(Ity_I32);
13864       assign( t2, binop(Iop_Or32, 
13865                         mk_x86g_calculate_eflags_all(), 
13866                         mkU32( (1<<1)|(1<<9) ) ));
13867
13868       /* Patch in the D flag.  This can simply be a copy of bit 10 of
13869          baseBlock[OFFB_DFLAG]. */
13870       t3 = newTemp(Ity_I32);
13871       assign( t3, binop(Iop_Or32,
13872                         mkexpr(t2),
13873                         binop(Iop_And32,
13874                               IRExpr_Get(OFFB_DFLAG,Ity_I32),
13875                               mkU32(1<<10))) 
13876             );
13877
13878       /* And patch in the ID flag. */
13879       t4 = newTemp(Ity_I32);
13880       assign( t4, binop(Iop_Or32,
13881                         mkexpr(t3),
13882                         binop(Iop_And32,
13883                               binop(Iop_Shl32, IRExpr_Get(OFFB_IDFLAG,Ity_I32), 
13884                                                mkU8(21)),
13885                               mkU32(1<<21)))
13886             );
13887
13888       /* And patch in the AC flag. */
13889       t5 = newTemp(Ity_I32);
13890       assign( t5, binop(Iop_Or32,
13891                         mkexpr(t4),
13892                         binop(Iop_And32,
13893                               binop(Iop_Shl32, IRExpr_Get(OFFB_ACFLAG,Ity_I32), 
13894                                                mkU8(18)),
13895                               mkU32(1<<18)))
13896             );
13897
13898       /* if sz==2, the stored value needs to be narrowed. */
13899       if (sz == 2)
13900         storeLE( mkexpr(t1), unop(Iop_32to16,mkexpr(t5)) );
13901       else 
13902         storeLE( mkexpr(t1), mkexpr(t5) );
13903
13904       DIP("pushf%c\n", nameISize(sz));
13905       break;
13906    }
13907
13908    case 0x60: /* PUSHA */
13909       /* This is almost certainly wrong for sz==2.  So ... */
13910       if (sz != 4) goto decode_failure;
13911
13912       /* This is the Right Way, in that the value to be pushed is
13913          established before %esp is changed, so that pusha
13914          correctly pushes the old %esp value.  New value of %esp is
13915          pushed at start. */
13916       /* t0 is the %ESP value we're going to push. */
13917       t0 = newTemp(Ity_I32);
13918       assign( t0, getIReg(4, R_ESP) );
13919
13920       /* t5 will be the new %ESP value. */
13921       t5 = newTemp(Ity_I32);
13922       assign( t5, binop(Iop_Sub32, mkexpr(t0), mkU32(8*4)) );
13923
13924       /* Update guest state before prodding memory. */
13925       putIReg(4, R_ESP, mkexpr(t5));
13926
13927       /* Dump all the registers. */
13928       storeLE( binop(Iop_Add32,mkexpr(t5),mkU32(28)), getIReg(4,R_EAX) );
13929       storeLE( binop(Iop_Add32,mkexpr(t5),mkU32(24)), getIReg(4,R_ECX) );
13930       storeLE( binop(Iop_Add32,mkexpr(t5),mkU32(20)), getIReg(4,R_EDX) );
13931       storeLE( binop(Iop_Add32,mkexpr(t5),mkU32(16)), getIReg(4,R_EBX) );
13932       storeLE( binop(Iop_Add32,mkexpr(t5),mkU32(12)), mkexpr(t0) /*esp*/);
13933       storeLE( binop(Iop_Add32,mkexpr(t5),mkU32( 8)), getIReg(4,R_EBP) );
13934       storeLE( binop(Iop_Add32,mkexpr(t5),mkU32( 4)), getIReg(4,R_ESI) );
13935       storeLE( binop(Iop_Add32,mkexpr(t5),mkU32( 0)), getIReg(4,R_EDI) );
13936
13937       DIP("pusha%c\n", nameISize(sz));
13938       break;
13939
13940    case 0x0E: /* PUSH %CS */
13941       dis_push_segreg( R_CS, sz ); break;
13942    case 0x1E: /* PUSH %DS */
13943       dis_push_segreg( R_DS, sz ); break;
13944    case 0x06: /* PUSH %ES */
13945       dis_push_segreg( R_ES, sz ); break;
13946    case 0x16: /* PUSH %SS */
13947       dis_push_segreg( R_SS, sz ); break;
13948
13949    /* ------------------------ SCAS et al ----------------- */
13950
13951    case 0xA4: /* MOVS, no REP prefix */
13952    case 0xA5: 
13953       if (sorb != 0)
13954          goto decode_failure; /* else dis_string_op asserts */
13955       dis_string_op( dis_MOVS, ( opc == 0xA4 ? 1 : sz ), "movs", sorb );
13956       break;
13957
13958   case 0xA6: /* CMPSb, no REP prefix */
13959   case 0xA7:
13960       if (sorb != 0)
13961          goto decode_failure; /* else dis_string_op asserts */
13962       dis_string_op( dis_CMPS, ( opc == 0xA6 ? 1 : sz ), "cmps", sorb );
13963       break;
13964
13965    case 0xAA: /* STOS, no REP prefix */
13966    case 0xAB:
13967       if (sorb != 0)
13968          goto decode_failure; /* else dis_string_op asserts */
13969       dis_string_op( dis_STOS, ( opc == 0xAA ? 1 : sz ), "stos", sorb );
13970       break;
13971
13972    case 0xAC: /* LODS, no REP prefix */
13973    case 0xAD:
13974       if (sorb != 0)
13975          goto decode_failure; /* else dis_string_op asserts */
13976       dis_string_op( dis_LODS, ( opc == 0xAC ? 1 : sz ), "lods", sorb );
13977       break;
13978
13979    case 0xAE: /* SCAS, no REP prefix */
13980    case 0xAF:
13981       if (sorb != 0) 
13982          goto decode_failure; /* else dis_string_op asserts */
13983       dis_string_op( dis_SCAS, ( opc == 0xAE ? 1 : sz ), "scas", sorb );
13984       break;
13985
13986
13987    case 0xFC: /* CLD */
13988       stmt( IRStmt_Put( OFFB_DFLAG, mkU32(1)) );
13989       DIP("cld\n");
13990       break;
13991
13992    case 0xFD: /* STD */
13993       stmt( IRStmt_Put( OFFB_DFLAG, mkU32(0xFFFFFFFF)) );
13994       DIP("std\n");
13995       break;
13996
13997    case 0xF8: /* CLC */
13998    case 0xF9: /* STC */
13999    case 0xF5: /* CMC */
14000       t0 = newTemp(Ity_I32);
14001       t1 = newTemp(Ity_I32);
14002       assign( t0, mk_x86g_calculate_eflags_all() );
14003       switch (opc) {
14004          case 0xF8: 
14005             assign( t1, binop(Iop_And32, mkexpr(t0), 
14006                                          mkU32(~X86G_CC_MASK_C)));
14007             DIP("clc\n");
14008             break;
14009          case 0xF9: 
14010             assign( t1, binop(Iop_Or32, mkexpr(t0), 
14011                                         mkU32(X86G_CC_MASK_C)));
14012             DIP("stc\n");
14013             break;
14014          case 0xF5: 
14015             assign( t1, binop(Iop_Xor32, mkexpr(t0), 
14016                                          mkU32(X86G_CC_MASK_C)));
14017             DIP("cmc\n");
14018             break;
14019          default: 
14020             vpanic("disInstr(x86)(clc/stc/cmc)");
14021       }
14022       stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(X86G_CC_OP_COPY) ));
14023       stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0) ));
14024       stmt( IRStmt_Put( OFFB_CC_DEP1, mkexpr(t1) ));
14025       /* Set NDEP even though it isn't used.  This makes redundant-PUT
14026          elimination of previous stores to this field work better. */
14027       stmt( IRStmt_Put( OFFB_CC_NDEP, mkU32(0) ));
14028       break;
14029
14030    case 0xD6: /* SALC */
14031       t0 = newTemp(Ity_I32);
14032       t1 = newTemp(Ity_I32);
14033       assign( t0,  binop(Iop_And32,
14034                          mk_x86g_calculate_eflags_c(),
14035                          mkU32(1)) );
14036       assign( t1, binop(Iop_Sar32, 
14037                         binop(Iop_Shl32, mkexpr(t0), mkU8(31)), 
14038                         mkU8(31)) );
14039       putIReg(1, R_EAX, unop(Iop_32to8, mkexpr(t1)) );
14040       DIP("salc\n");
14041       break;
14042
14043    /* REPNE prefix insn */
14044    case 0xF2: { 
14045       Addr32 eip_orig = guest_EIP_bbstart + delta_start;
14046       if (sorb != 0) goto decode_failure;
14047       abyte = getIByte(delta); delta++;
14048
14049       if (abyte == 0x66) { sz = 2; abyte = getIByte(delta); delta++; }
14050       dres.whatNext = Dis_StopHere;         
14051
14052       switch (abyte) {
14053       /* According to the Intel manual, "repne movs" should never occur, but
14054        * in practice it has happened, so allow for it here... */
14055       case 0xA4: sz = 1;   /* REPNE MOVS<sz> */
14056       case 0xA5: 
14057          dis_REP_op ( X86CondNZ, dis_MOVS, sz, eip_orig,
14058                                  guest_EIP_bbstart+delta, "repne movs" );
14059          break;
14060
14061       case 0xA6: sz = 1;   /* REPNE CMP<sz> */
14062       case 0xA7:
14063          dis_REP_op ( X86CondNZ, dis_CMPS, sz, eip_orig, 
14064                                  guest_EIP_bbstart+delta, "repne cmps" );
14065          break;
14066
14067       case 0xAA: sz = 1;   /* REPNE STOS<sz> */
14068       case 0xAB:
14069          dis_REP_op ( X86CondNZ, dis_STOS, sz, eip_orig, 
14070                                  guest_EIP_bbstart+delta, "repne stos" );
14071          break;
14072
14073       case 0xAE: sz = 1;   /* REPNE SCAS<sz> */
14074       case 0xAF:
14075          dis_REP_op ( X86CondNZ, dis_SCAS, sz, eip_orig,
14076                                  guest_EIP_bbstart+delta, "repne scas" );
14077          break;
14078
14079       default:
14080          goto decode_failure;
14081       }
14082       break;
14083    }
14084
14085    /* REP/REPE prefix insn (for SCAS and CMPS, 0xF3 means REPE,
14086       for the rest, it means REP) */
14087    case 0xF3: { 
14088       Addr32 eip_orig = guest_EIP_bbstart + delta_start;
14089       if (sorb != 0) goto decode_failure;
14090       abyte = getIByte(delta); delta++;
14091
14092       if (abyte == 0x66) { sz = 2; abyte = getIByte(delta); delta++; }
14093       dres.whatNext = Dis_StopHere;
14094
14095       switch (abyte) {
14096       case 0xA4: sz = 1;   /* REP MOVS<sz> */
14097       case 0xA5:
14098          dis_REP_op ( X86CondAlways, dis_MOVS, sz, eip_orig, 
14099                                      guest_EIP_bbstart+delta, "rep movs" );
14100          break;
14101
14102       case 0xA6: sz = 1;   /* REPE CMP<sz> */
14103       case 0xA7:
14104          dis_REP_op ( X86CondZ, dis_CMPS, sz, eip_orig, 
14105                                 guest_EIP_bbstart+delta, "repe cmps" );
14106          break;
14107
14108       case 0xAA: sz = 1;   /* REP STOS<sz> */
14109       case 0xAB:
14110          dis_REP_op ( X86CondAlways, dis_STOS, sz, eip_orig, 
14111                                      guest_EIP_bbstart+delta, "rep stos" );
14112          break;
14113
14114       case 0xAC: sz = 1;   /* REP LODS<sz> */
14115       case 0xAD:
14116          dis_REP_op ( X86CondAlways, dis_LODS, sz, eip_orig, 
14117                                      guest_EIP_bbstart+delta, "rep lods" );
14118          break;
14119
14120       case 0xAE: sz = 1;   /* REPE SCAS<sz> */
14121       case 0xAF: 
14122          dis_REP_op ( X86CondZ, dis_SCAS, sz, eip_orig, 
14123                                 guest_EIP_bbstart+delta, "repe scas" );
14124          break;
14125       
14126       case 0x90:           /* REP NOP (PAUSE) */
14127          /* a hint to the P4 re spin-wait loop */
14128          DIP("rep nop (P4 pause)\n");
14129          /* "observe" the hint.  The Vex client needs to be careful not
14130             to cause very long delays as a result, though. */
14131          jmp_lit(Ijk_Yield, ((Addr32)guest_EIP_bbstart)+delta);
14132          dres.whatNext = Dis_StopHere;
14133          break;
14134
14135       case 0xC3:           /* REP RET -- same as normal ret? */
14136          dis_ret(0);
14137          dres.whatNext = Dis_StopHere;
14138          DIP("rep ret\n");
14139          break;
14140
14141       default:
14142          goto decode_failure;
14143       }
14144       break;
14145    }
14146
14147    /* ------------------------ XCHG ----------------------- */
14148
14149    /* XCHG reg,mem automatically asserts LOCK# even without a LOCK
14150       prefix; hence it must be translated with an IRCAS (at least, the
14151       memory variant). */
14152    case 0x86: /* XCHG Gb,Eb */
14153       sz = 1;
14154       /* Fall through ... */
14155    case 0x87: /* XCHG Gv,Ev */
14156       modrm = getIByte(delta);
14157       ty = szToITy(sz);
14158       t1 = newTemp(ty); t2 = newTemp(ty);
14159       if (epartIsReg(modrm)) {
14160          assign(t1, getIReg(sz, eregOfRM(modrm)));
14161          assign(t2, getIReg(sz, gregOfRM(modrm)));
14162          putIReg(sz, gregOfRM(modrm), mkexpr(t1));
14163          putIReg(sz, eregOfRM(modrm), mkexpr(t2));
14164          delta++;
14165          DIP("xchg%c %s, %s\n", 
14166              nameISize(sz), nameIReg(sz,gregOfRM(modrm)), 
14167                             nameIReg(sz,eregOfRM(modrm)));
14168       } else {
14169          *expect_CAS = True;
14170          addr = disAMode ( &alen, sorb, delta, dis_buf );
14171          assign( t1, loadLE(ty,mkexpr(addr)) );
14172          assign( t2, getIReg(sz,gregOfRM(modrm)) );
14173          casLE( mkexpr(addr),
14174                 mkexpr(t1), mkexpr(t2), guest_EIP_curr_instr );
14175          putIReg( sz, gregOfRM(modrm), mkexpr(t1) );
14176          delta += alen;
14177          DIP("xchg%c %s, %s\n", nameISize(sz), 
14178                                 nameIReg(sz,gregOfRM(modrm)), dis_buf);
14179       }
14180       break;
14181
14182    case 0x90: /* XCHG eAX,eAX */
14183       DIP("nop\n");
14184       break;
14185    case 0x91: /* XCHG eAX,eCX */
14186    case 0x92: /* XCHG eAX,eDX */
14187    case 0x93: /* XCHG eAX,eBX */
14188    case 0x94: /* XCHG eAX,eSP */
14189    case 0x95: /* XCHG eAX,eBP */
14190    case 0x96: /* XCHG eAX,eSI */
14191    case 0x97: /* XCHG eAX,eDI */
14192       codegen_xchg_eAX_Reg ( sz, opc - 0x90 );
14193       break;
14194
14195    /* ------------------------ XLAT ----------------------- */
14196
14197    case 0xD7: /* XLAT */
14198       if (sz != 4) goto decode_failure; /* sz == 2 is also allowed (0x66) */
14199       putIReg( 
14200          1, 
14201          R_EAX/*AL*/,
14202          loadLE(Ity_I8, 
14203                 handleSegOverride( 
14204                    sorb, 
14205                    binop(Iop_Add32, 
14206                          getIReg(4, R_EBX), 
14207                          unop(Iop_8Uto32, getIReg(1, R_EAX/*AL*/))))));
14208
14209       DIP("xlat%c [ebx]\n", nameISize(sz));
14210       break;
14211
14212    /* ------------------------ IN / OUT ----------------------- */
14213
14214    case 0xE4: /* IN imm8, AL */
14215       sz = 1; 
14216       t1 = newTemp(Ity_I32);
14217       abyte = getIByte(delta); delta++;
14218       assign(t1, mkU32( abyte & 0xFF ));
14219       DIP("in%c $%d,%s\n", nameISize(sz), (Int)abyte, nameIReg(sz,R_EAX));
14220       goto do_IN;
14221    case 0xE5: /* IN imm8, eAX */
14222       vassert(sz == 2 || sz == 4);
14223       t1 = newTemp(Ity_I32);
14224       abyte = getIByte(delta); delta++;
14225       assign(t1, mkU32( abyte & 0xFF ));
14226       DIP("in%c $%d,%s\n", nameISize(sz), (Int)abyte, nameIReg(sz,R_EAX));
14227       goto do_IN;
14228    case 0xEC: /* IN %DX, AL */
14229       sz = 1; 
14230       t1 = newTemp(Ity_I32);
14231       assign(t1, unop(Iop_16Uto32, getIReg(2, R_EDX)));
14232       DIP("in%c %s,%s\n", nameISize(sz), nameIReg(2,R_EDX), 
14233                                          nameIReg(sz,R_EAX));
14234       goto do_IN;
14235    case 0xED: /* IN %DX, eAX */
14236       vassert(sz == 2 || sz == 4);
14237       t1 = newTemp(Ity_I32);
14238       assign(t1, unop(Iop_16Uto32, getIReg(2, R_EDX)));
14239       DIP("in%c %s,%s\n", nameISize(sz), nameIReg(2,R_EDX), 
14240                                          nameIReg(sz,R_EAX));
14241       goto do_IN;
14242    do_IN: {
14243       /* At this point, sz indicates the width, and t1 is a 32-bit
14244          value giving port number. */
14245       IRDirty* d;
14246       vassert(sz == 1 || sz == 2 || sz == 4);
14247       ty = szToITy(sz);
14248       t2 = newTemp(Ity_I32);
14249       d = unsafeIRDirty_1_N( 
14250              t2,
14251              0/*regparms*/, 
14252              "x86g_dirtyhelper_IN", 
14253              &x86g_dirtyhelper_IN,
14254              mkIRExprVec_2( mkexpr(t1), mkU32(sz) )
14255           );
14256       /* do the call, dumping the result in t2. */
14257       stmt( IRStmt_Dirty(d) );
14258       putIReg(sz, R_EAX, narrowTo( ty, mkexpr(t2) ) );
14259       break;
14260    }
14261
14262    case 0xE6: /* OUT AL, imm8 */
14263       sz = 1;
14264       t1 = newTemp(Ity_I32);
14265       abyte = getIByte(delta); delta++;
14266       assign( t1, mkU32( abyte & 0xFF ) );
14267       DIP("out%c %s,$%d\n", nameISize(sz), nameIReg(sz,R_EAX), (Int)abyte);
14268       goto do_OUT;
14269    case 0xE7: /* OUT eAX, imm8 */
14270       vassert(sz == 2 || sz == 4);
14271       t1 = newTemp(Ity_I32);
14272       abyte = getIByte(delta); delta++;
14273       assign( t1, mkU32( abyte & 0xFF ) );
14274       DIP("out%c %s,$%d\n", nameISize(sz), nameIReg(sz,R_EAX), (Int)abyte);
14275       goto do_OUT;
14276    case 0xEE: /* OUT AL, %DX */
14277       sz = 1;
14278       t1 = newTemp(Ity_I32);
14279       assign( t1, unop(Iop_16Uto32, getIReg(2, R_EDX)) );
14280       DIP("out%c %s,%s\n", nameISize(sz), nameIReg(sz,R_EAX),
14281                                           nameIReg(2,R_EDX));
14282       goto do_OUT;
14283    case 0xEF: /* OUT eAX, %DX */
14284       vassert(sz == 2 || sz == 4);
14285       t1 = newTemp(Ity_I32);
14286       assign( t1, unop(Iop_16Uto32, getIReg(2, R_EDX)) );
14287       DIP("out%c %s,%s\n", nameISize(sz), nameIReg(sz,R_EAX),
14288                                           nameIReg(2,R_EDX));
14289       goto do_OUT;
14290    do_OUT: {
14291       /* At this point, sz indicates the width, and t1 is a 32-bit
14292          value giving port number. */
14293       IRDirty* d;
14294       vassert(sz == 1 || sz == 2 || sz == 4);
14295       ty = szToITy(sz);
14296       d = unsafeIRDirty_0_N( 
14297              0/*regparms*/, 
14298              "x86g_dirtyhelper_OUT", 
14299              &x86g_dirtyhelper_OUT,
14300              mkIRExprVec_3( mkexpr(t1),
14301                             widenUto32( getIReg(sz, R_EAX) ), 
14302                             mkU32(sz) )
14303           );
14304       stmt( IRStmt_Dirty(d) );
14305       break;
14306    }
14307
14308    /* ------------------------ (Grp1 extensions) ---------- */
14309
14310    case 0x82: /* Grp1 Ib,Eb too.  Apparently this is the same as 
14311                  case 0x80, but only in 32-bit mode. */
14312       /* fallthru */
14313    case 0x80: /* Grp1 Ib,Eb */
14314       modrm = getIByte(delta);
14315       am_sz = lengthAMode(delta);
14316       sz    = 1;
14317       d_sz  = 1;
14318       d32   = getUChar(delta + am_sz);
14319       delta = dis_Grp1 ( sorb, pfx_lock, delta, modrm, am_sz, d_sz, sz, d32 );
14320       break;
14321
14322    case 0x81: /* Grp1 Iv,Ev */
14323       modrm = getIByte(delta);
14324       am_sz = lengthAMode(delta);
14325       d_sz  = sz;
14326       d32   = getUDisp(d_sz, delta + am_sz);
14327       delta = dis_Grp1 ( sorb, pfx_lock, delta, modrm, am_sz, d_sz, sz, d32 );
14328       break;
14329
14330    case 0x83: /* Grp1 Ib,Ev */
14331       modrm = getIByte(delta);
14332       am_sz = lengthAMode(delta);
14333       d_sz  = 1;
14334       d32   = getSDisp8(delta + am_sz);
14335       delta = dis_Grp1 ( sorb, pfx_lock, delta, modrm, am_sz, d_sz, sz, d32 );
14336       break;
14337
14338    /* ------------------------ (Grp2 extensions) ---------- */
14339
14340    case 0xC0: { /* Grp2 Ib,Eb */
14341       Bool decode_OK = True;
14342       modrm = getIByte(delta);
14343       am_sz = lengthAMode(delta);
14344       d_sz  = 1;
14345       d32   = getUChar(delta + am_sz);
14346       sz    = 1;
14347       delta = dis_Grp2 ( sorb, delta, modrm, am_sz, d_sz, sz, 
14348                          mkU8(d32 & 0xFF), NULL, &decode_OK );
14349       if (!decode_OK)
14350          goto decode_failure;
14351       break;
14352    }
14353    case 0xC1: { /* Grp2 Ib,Ev */
14354       Bool decode_OK = True;
14355       modrm = getIByte(delta);
14356       am_sz = lengthAMode(delta);
14357       d_sz  = 1;
14358       d32   = getUChar(delta + am_sz);
14359       delta = dis_Grp2 ( sorb, delta, modrm, am_sz, d_sz, sz, 
14360                          mkU8(d32 & 0xFF), NULL, &decode_OK );
14361       if (!decode_OK)
14362          goto decode_failure;
14363       break;
14364    }
14365    case 0xD0: { /* Grp2 1,Eb */
14366       Bool decode_OK = True;
14367       modrm = getIByte(delta);
14368       am_sz = lengthAMode(delta);
14369       d_sz  = 0;
14370       d32   = 1;
14371       sz    = 1;
14372       delta = dis_Grp2 ( sorb, delta, modrm, am_sz, d_sz, sz, 
14373                          mkU8(d32), NULL, &decode_OK );
14374       if (!decode_OK)
14375          goto decode_failure;
14376       break;
14377    }
14378    case 0xD1: { /* Grp2 1,Ev */
14379       Bool decode_OK = True;
14380       modrm = getUChar(delta);
14381       am_sz = lengthAMode(delta);
14382       d_sz  = 0;
14383       d32   = 1;
14384       delta = dis_Grp2 ( sorb, delta, modrm, am_sz, d_sz, sz, 
14385                          mkU8(d32), NULL, &decode_OK );
14386       if (!decode_OK)
14387          goto decode_failure;
14388       break;
14389    }
14390    case 0xD2: { /* Grp2 CL,Eb */
14391       Bool decode_OK = True;
14392       modrm = getUChar(delta);
14393       am_sz = lengthAMode(delta);
14394       d_sz  = 0;
14395       sz    = 1;
14396       delta = dis_Grp2 ( sorb, delta, modrm, am_sz, d_sz, sz, 
14397                          getIReg(1,R_ECX), "%cl", &decode_OK );
14398       if (!decode_OK)
14399          goto decode_failure;
14400       break;
14401    }
14402    case 0xD3: { /* Grp2 CL,Ev */
14403       Bool decode_OK = True;
14404       modrm = getIByte(delta);
14405       am_sz = lengthAMode(delta);
14406       d_sz  = 0;
14407       delta = dis_Grp2 ( sorb, delta, modrm, am_sz, d_sz, sz, 
14408                          getIReg(1,R_ECX), "%cl", &decode_OK );
14409       if (!decode_OK)
14410          goto decode_failure;
14411       break;
14412    }
14413
14414    /* ------------------------ (Grp3 extensions) ---------- */
14415
14416    case 0xF6: { /* Grp3 Eb */
14417       Bool decode_OK = True;
14418       delta = dis_Grp3 ( sorb, pfx_lock, 1, delta, &decode_OK );
14419       if (!decode_OK)
14420          goto decode_failure;
14421       break;
14422    }
14423    case 0xF7: { /* Grp3 Ev */
14424       Bool decode_OK = True;
14425       delta = dis_Grp3 ( sorb, pfx_lock, sz, delta, &decode_OK );
14426       if (!decode_OK)
14427          goto decode_failure;
14428       break;
14429    }
14430
14431    /* ------------------------ (Grp4 extensions) ---------- */
14432
14433    case 0xFE: { /* Grp4 Eb */
14434       Bool decode_OK = True;
14435       delta = dis_Grp4 ( sorb, pfx_lock, delta, &decode_OK );
14436       if (!decode_OK)
14437          goto decode_failure;
14438       break;
14439    }
14440
14441    /* ------------------------ (Grp5 extensions) ---------- */
14442
14443    case 0xFF: { /* Grp5 Ev */
14444       Bool decode_OK = True;
14445       delta = dis_Grp5 ( sorb, pfx_lock, sz, delta, &dres, &decode_OK );
14446       if (!decode_OK)
14447          goto decode_failure;
14448       break;
14449    }
14450
14451    /* ------------------------ Escapes to 2-byte opcodes -- */
14452
14453    case 0x0F: {
14454       opc = getIByte(delta); delta++;
14455       switch (opc) {
14456
14457       /* =-=-=-=-=-=-=-=-=- Grp8 =-=-=-=-=-=-=-=-=-=-=-= */
14458
14459       case 0xBA: { /* Grp8 Ib,Ev */
14460          Bool decode_OK = False;
14461          modrm = getUChar(delta);
14462          am_sz = lengthAMode(delta);
14463          d32   = getSDisp8(delta + am_sz);
14464          delta = dis_Grp8_Imm ( sorb, pfx_lock, delta, modrm, 
14465                                 am_sz, sz, d32, &decode_OK );
14466          if (!decode_OK)
14467             goto decode_failure;
14468          break;
14469       }
14470
14471       /* =-=-=-=-=-=-=-=-=- BSF/BSR -=-=-=-=-=-=-=-=-=-= */
14472
14473       case 0xBC: /* BSF Gv,Ev */
14474          delta = dis_bs_E_G ( sorb, sz, delta, True );
14475          break;
14476       case 0xBD: /* BSR Gv,Ev */
14477          delta = dis_bs_E_G ( sorb, sz, delta, False );
14478          break;
14479
14480       /* =-=-=-=-=-=-=-=-=- BSWAP -=-=-=-=-=-=-=-=-=-=-= */
14481
14482       case 0xC8: /* BSWAP %eax */
14483       case 0xC9:
14484       case 0xCA:
14485       case 0xCB:
14486       case 0xCC:
14487       case 0xCD:
14488       case 0xCE:
14489       case 0xCF: /* BSWAP %edi */
14490          /* AFAICS from the Intel docs, this only exists at size 4. */
14491          vassert(sz == 4);
14492          t1 = newTemp(Ity_I32);
14493          t2 = newTemp(Ity_I32);
14494          assign( t1, getIReg(4, opc-0xC8) );
14495
14496          assign( t2,
14497             binop(Iop_Or32,
14498                binop(Iop_Shl32, mkexpr(t1), mkU8(24)),
14499             binop(Iop_Or32,
14500                binop(Iop_And32, binop(Iop_Shl32, mkexpr(t1), mkU8(8)), 
14501                                 mkU32(0x00FF0000)),
14502             binop(Iop_Or32,
14503                binop(Iop_And32, binop(Iop_Shr32, mkexpr(t1), mkU8(8)),
14504                                 mkU32(0x0000FF00)),
14505                binop(Iop_And32, binop(Iop_Shr32, mkexpr(t1), mkU8(24)),
14506                                 mkU32(0x000000FF) )
14507             )))
14508          );
14509
14510          putIReg(4, opc-0xC8, mkexpr(t2));
14511          DIP("bswapl %s\n", nameIReg(4, opc-0xC8));
14512          break;
14513
14514       /* =-=-=-=-=-=-=-=-=- BT/BTS/BTR/BTC =-=-=-=-=-=-= */
14515
14516       case 0xA3: /* BT Gv,Ev */
14517          delta = dis_bt_G_E ( vbi, sorb, pfx_lock, sz, delta, BtOpNone );
14518          break;
14519       case 0xB3: /* BTR Gv,Ev */
14520          delta = dis_bt_G_E ( vbi, sorb, pfx_lock, sz, delta, BtOpReset );
14521          break;
14522       case 0xAB: /* BTS Gv,Ev */
14523          delta = dis_bt_G_E ( vbi, sorb, pfx_lock, sz, delta, BtOpSet );
14524          break;
14525       case 0xBB: /* BTC Gv,Ev */
14526          delta = dis_bt_G_E ( vbi, sorb, pfx_lock, sz, delta, BtOpComp );
14527          break;
14528
14529       /* =-=-=-=-=-=-=-=-=- CMOV =-=-=-=-=-=-=-=-=-=-=-= */
14530  
14531       case 0x40:
14532       case 0x41:
14533       case 0x42: /* CMOVBb/CMOVNAEb (cmov below) */
14534       case 0x43: /* CMOVNBb/CMOVAEb (cmov not below) */
14535       case 0x44: /* CMOVZb/CMOVEb (cmov zero) */
14536       case 0x45: /* CMOVNZb/CMOVNEb (cmov not zero) */
14537       case 0x46: /* CMOVBEb/CMOVNAb (cmov below or equal) */
14538       case 0x47: /* CMOVNBEb/CMOVAb (cmov not below or equal) */
14539       case 0x48: /* CMOVSb (cmov negative) */
14540       case 0x49: /* CMOVSb (cmov not negative) */
14541       case 0x4A: /* CMOVP (cmov parity even) */
14542       case 0x4B: /* CMOVNP (cmov parity odd) */
14543       case 0x4C: /* CMOVLb/CMOVNGEb (cmov less) */
14544       case 0x4D: /* CMOVGEb/CMOVNLb (cmov greater or equal) */
14545       case 0x4E: /* CMOVLEb/CMOVNGb (cmov less or equal) */
14546       case 0x4F: /* CMOVGb/CMOVNLEb (cmov greater) */
14547          delta = dis_cmov_E_G(sorb, sz, (X86Condcode)(opc - 0x40), delta);
14548          break;
14549
14550       /* =-=-=-=-=-=-=-=-=- CMPXCHG -=-=-=-=-=-=-=-=-=-= */
14551
14552       case 0xB0: /* CMPXCHG Gb,Eb */
14553          delta = dis_cmpxchg_G_E ( sorb, pfx_lock, 1, delta );
14554          break;
14555       case 0xB1: /* CMPXCHG Gv,Ev */
14556          delta = dis_cmpxchg_G_E ( sorb, pfx_lock, sz, delta );
14557          break;
14558
14559       case 0xC7: { /* CMPXCHG8B Gv (0F C7 /1) */
14560          IRTemp expdHi    = newTemp(Ity_I32);
14561          IRTemp expdLo    = newTemp(Ity_I32);
14562          IRTemp dataHi    = newTemp(Ity_I32);
14563          IRTemp dataLo    = newTemp(Ity_I32);
14564          IRTemp oldHi     = newTemp(Ity_I32);
14565          IRTemp oldLo     = newTemp(Ity_I32);
14566          IRTemp flags_old = newTemp(Ity_I32);
14567          IRTemp flags_new = newTemp(Ity_I32);
14568          IRTemp success   = newTemp(Ity_I1);
14569
14570          /* Translate this using a DCAS, even if there is no LOCK
14571             prefix.  Life is too short to bother with generating two
14572             different translations for the with/without-LOCK-prefix
14573             cases. */
14574          *expect_CAS = True;
14575
14576          /* Decode, and generate address. */
14577          if (sz != 4) goto decode_failure;
14578          modrm = getIByte(delta);
14579          if (epartIsReg(modrm)) goto decode_failure;
14580          if (gregOfRM(modrm) != 1) goto decode_failure;
14581          addr = disAMode ( &alen, sorb, delta, dis_buf );
14582          delta += alen;
14583
14584          /* Get the expected and new values. */
14585          assign( expdHi, getIReg(4,R_EDX) );
14586          assign( expdLo, getIReg(4,R_EAX) );
14587          assign( dataHi, getIReg(4,R_ECX) );
14588          assign( dataLo, getIReg(4,R_EBX) );
14589
14590          /* Do the DCAS */
14591          stmt( IRStmt_CAS(
14592                   mkIRCAS( oldHi, oldLo, 
14593                            Iend_LE, mkexpr(addr), 
14594                            mkexpr(expdHi), mkexpr(expdLo),
14595                            mkexpr(dataHi), mkexpr(dataLo)
14596                )));
14597
14598          /* success when oldHi:oldLo == expdHi:expdLo */
14599          assign( success,
14600                  binop(Iop_CasCmpEQ32,
14601                        binop(Iop_Or32,
14602                              binop(Iop_Xor32, mkexpr(oldHi), mkexpr(expdHi)),
14603                              binop(Iop_Xor32, mkexpr(oldLo), mkexpr(expdLo))
14604                        ),
14605                        mkU32(0)
14606                  ));
14607
14608          /* If the DCAS is successful, that is to say oldHi:oldLo ==
14609             expdHi:expdLo, then put expdHi:expdLo back in EDX:EAX,
14610             which is where they came from originally.  Both the actual
14611             contents of these two regs, and any shadow values, are
14612             unchanged.  If the DCAS fails then we're putting into
14613             EDX:EAX the value seen in memory. */
14614          putIReg(4, R_EDX,
14615                     IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(success)),
14616                                   mkexpr(oldHi),
14617                                   mkexpr(expdHi)
14618                 ));
14619          putIReg(4, R_EAX,
14620                     IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(success)),
14621                                   mkexpr(oldLo),
14622                                   mkexpr(expdLo)
14623                 ));
14624
14625          /* Copy the success bit into the Z flag and leave the others
14626             unchanged */
14627          assign( flags_old, widenUto32(mk_x86g_calculate_eflags_all()));
14628          assign( 
14629             flags_new,
14630             binop(Iop_Or32,
14631                   binop(Iop_And32, mkexpr(flags_old), 
14632                                    mkU32(~X86G_CC_MASK_Z)),
14633                   binop(Iop_Shl32, 
14634                         binop(Iop_And32, 
14635                               unop(Iop_1Uto32, mkexpr(success)), mkU32(1)), 
14636                         mkU8(X86G_CC_SHIFT_Z)) ));
14637
14638          stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(X86G_CC_OP_COPY) ));
14639          stmt( IRStmt_Put( OFFB_CC_DEP1, mkexpr(flags_new) ));
14640          stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0) ));
14641          /* Set NDEP even though it isn't used.  This makes
14642             redundant-PUT elimination of previous stores to this field
14643             work better. */
14644          stmt( IRStmt_Put( OFFB_CC_NDEP, mkU32(0) ));
14645
14646          /* Sheesh.  Aren't you glad it was me and not you that had to
14647             write and validate all this grunge? */
14648
14649          DIP("cmpxchg8b %s\n", dis_buf);
14650          break;
14651       }
14652
14653       /* =-=-=-=-=-=-=-=-=- CPUID -=-=-=-=-=-=-=-=-=-=-= */
14654
14655       case 0xA2: { /* CPUID */
14656          /* Uses dirty helper: 
14657                void dirtyhelper_CPUID_sse[012] ( VexGuestX86State* )
14658             declared to mod eax, wr ebx, ecx, edx
14659          */
14660          IRDirty* d     = NULL;
14661          HChar*   fName = NULL;
14662          void*    fAddr = NULL;
14663          if (archinfo->hwcaps & VEX_HWCAPS_X86_SSE2) {
14664             fName = "x86g_dirtyhelper_CPUID_sse2";
14665             fAddr = &x86g_dirtyhelper_CPUID_sse2; 
14666          } 
14667          else
14668          if (archinfo->hwcaps & VEX_HWCAPS_X86_SSE1) {
14669             fName = "x86g_dirtyhelper_CPUID_sse1";
14670             fAddr = &x86g_dirtyhelper_CPUID_sse1; 
14671          } 
14672          else
14673          if (archinfo->hwcaps == 0/*no SSE*/) {
14674             fName = "x86g_dirtyhelper_CPUID_sse0";
14675             fAddr = &x86g_dirtyhelper_CPUID_sse0; 
14676          } else
14677             vpanic("disInstr(x86)(cpuid)");
14678
14679          vassert(fName); vassert(fAddr);
14680          d = unsafeIRDirty_0_N ( 0/*regparms*/, 
14681                                  fName, fAddr, mkIRExprVec_0() );
14682          /* declare guest state effects */
14683          d->needsBBP = True;
14684          d->nFxState = 4;
14685          d->fxState[0].fx     = Ifx_Modify;
14686          d->fxState[0].offset = OFFB_EAX;
14687          d->fxState[0].size   = 4;
14688          d->fxState[1].fx     = Ifx_Write;
14689          d->fxState[1].offset = OFFB_EBX;
14690          d->fxState[1].size   = 4;
14691          d->fxState[2].fx     = Ifx_Modify;
14692          d->fxState[2].offset = OFFB_ECX;
14693          d->fxState[2].size   = 4;
14694          d->fxState[3].fx     = Ifx_Write;
14695          d->fxState[3].offset = OFFB_EDX;
14696          d->fxState[3].size   = 4;
14697          /* execute the dirty call, side-effecting guest state */
14698          stmt( IRStmt_Dirty(d) );
14699          /* CPUID is a serialising insn.  So, just in case someone is
14700             using it as a memory fence ... */
14701          stmt( IRStmt_MBE(Imbe_Fence) );
14702          DIP("cpuid\n");
14703          break;
14704       }
14705
14706 //--          if (!VG_(cpu_has_feature)(VG_X86_FEAT_CPUID))
14707 //--             goto decode_failure;
14708 //-- 
14709 //--          t1 = newTemp(cb);
14710 //--          t2 = newTemp(cb);
14711 //--          t3 = newTemp(cb);
14712 //--          t4 = newTemp(cb);
14713 //--          uInstr0(cb, CALLM_S, 0);
14714 //-- 
14715 //--          uInstr2(cb, GET,   4, ArchReg, R_EAX, TempReg, t1);
14716 //--          uInstr1(cb, PUSH,  4, TempReg, t1);
14717 //-- 
14718 //--          uInstr2(cb, MOV,   4, Literal, 0, TempReg, t2);
14719 //--          uLiteral(cb, 0);
14720 //--          uInstr1(cb, PUSH,  4, TempReg, t2);
14721 //-- 
14722 //--          uInstr2(cb, MOV,   4, Literal, 0, TempReg, t3);
14723 //--          uLiteral(cb, 0);
14724 //--          uInstr1(cb, PUSH,  4, TempReg, t3);
14725 //-- 
14726 //--          uInstr2(cb, MOV,   4, Literal, 0, TempReg, t4);
14727 //--          uLiteral(cb, 0);
14728 //--          uInstr1(cb, PUSH,  4, TempReg, t4);
14729 //-- 
14730 //--          uInstr1(cb, CALLM, 0, Lit16,   VGOFF_(helper_CPUID));
14731 //--          uFlagsRWU(cb, FlagsEmpty, FlagsEmpty, FlagsEmpty);
14732 //-- 
14733 //--          uInstr1(cb, POP,   4, TempReg, t4);
14734 //--          uInstr2(cb, PUT,   4, TempReg, t4, ArchReg, R_EDX);
14735 //-- 
14736 //--          uInstr1(cb, POP,   4, TempReg, t3);
14737 //--          uInstr2(cb, PUT,   4, TempReg, t3, ArchReg, R_ECX);
14738 //-- 
14739 //--          uInstr1(cb, POP,   4, TempReg, t2);
14740 //--          uInstr2(cb, PUT,   4, TempReg, t2, ArchReg, R_EBX);
14741 //-- 
14742 //--          uInstr1(cb, POP,   4, TempReg, t1);
14743 //--          uInstr2(cb, PUT,   4, TempReg, t1, ArchReg, R_EAX);
14744 //-- 
14745 //--          uInstr0(cb, CALLM_E, 0);
14746 //--          DIP("cpuid\n");
14747 //--          break;
14748 //-- 
14749       /* =-=-=-=-=-=-=-=-=- MOVZX, MOVSX =-=-=-=-=-=-=-= */
14750
14751       case 0xB6: /* MOVZXb Eb,Gv */
14752          if (sz != 2 && sz != 4)
14753             goto decode_failure;
14754          delta = dis_movx_E_G ( sorb, delta, 1, sz, False );
14755          break;
14756
14757       case 0xB7: /* MOVZXw Ew,Gv */
14758          if (sz != 4)
14759             goto decode_failure;
14760          delta = dis_movx_E_G ( sorb, delta, 2, 4, False );
14761          break;
14762
14763       case 0xBE: /* MOVSXb Eb,Gv */
14764          if (sz != 2 && sz != 4)
14765             goto decode_failure;
14766          delta = dis_movx_E_G ( sorb, delta, 1, sz, True );
14767          break;
14768
14769       case 0xBF: /* MOVSXw Ew,Gv */
14770          if (sz != 4 && /* accept movsww, sigh, see #250799 */sz != 2)
14771             goto decode_failure;
14772          delta = dis_movx_E_G ( sorb, delta, 2, sz, True );
14773          break;
14774
14775 //--       /* =-=-=-=-=-=-=-=-=-=-= MOVNTI -=-=-=-=-=-=-=-=-= */
14776 //-- 
14777 //--       case 0xC3: /* MOVNTI Gv,Ev */
14778 //--          vg_assert(sz == 4);
14779 //--          modrm = getUChar(eip);
14780 //--          vg_assert(!epartIsReg(modrm));
14781 //--          t1 = newTemp(cb);
14782 //--          uInstr2(cb, GET, 4, ArchReg, gregOfRM(modrm), TempReg, t1);
14783 //--          pair = disAMode ( cb, sorb, eip, dis_buf );
14784 //--          t2 = LOW24(pair);
14785 //--          eip += HI8(pair);
14786 //--          uInstr2(cb, STORE, 4, TempReg, t1, TempReg, t2);
14787 //--          DIP("movnti %s,%s\n", nameIReg(4,gregOfRM(modrm)), dis_buf);
14788 //--          break;
14789
14790       /* =-=-=-=-=-=-=-=-=- MUL/IMUL =-=-=-=-=-=-=-=-=-= */
14791
14792       case 0xAF: /* IMUL Ev, Gv */
14793          delta = dis_mul_E_G ( sorb, sz, delta );
14794          break;
14795
14796       /* =-=-=-=-=-=-=-=-=- NOPs =-=-=-=-=-=-=-=-=-=-=-= */
14797
14798       case 0x1F:
14799          modrm = getUChar(delta);
14800          if (epartIsReg(modrm)) goto decode_failure;
14801          addr = disAMode ( &alen, sorb, delta, dis_buf );
14802          delta += alen;
14803          DIP("nop%c %s\n", nameISize(sz), dis_buf);
14804          break;
14805
14806       /* =-=-=-=-=-=-=-=-=- Jcond d32 -=-=-=-=-=-=-=-=-= */
14807       case 0x80:
14808       case 0x81:
14809       case 0x82: /* JBb/JNAEb (jump below) */
14810       case 0x83: /* JNBb/JAEb (jump not below) */
14811       case 0x84: /* JZb/JEb (jump zero) */
14812       case 0x85: /* JNZb/JNEb (jump not zero) */
14813       case 0x86: /* JBEb/JNAb (jump below or equal) */
14814       case 0x87: /* JNBEb/JAb (jump not below or equal) */
14815       case 0x88: /* JSb (jump negative) */
14816       case 0x89: /* JSb (jump not negative) */
14817       case 0x8A: /* JP (jump parity even) */
14818       case 0x8B: /* JNP/JPO (jump parity odd) */
14819       case 0x8C: /* JLb/JNGEb (jump less) */
14820       case 0x8D: /* JGEb/JNLb (jump greater or equal) */
14821       case 0x8E: /* JLEb/JNGb (jump less or equal) */
14822       case 0x8F: /* JGb/JNLEb (jump greater) */
14823        { Int    jmpDelta;
14824          HChar* comment  = "";
14825          jmpDelta = (Int)getUDisp32(delta);
14826          d32 = (((Addr32)guest_EIP_bbstart)+delta+4) + jmpDelta;
14827          delta += 4;
14828          if (resteerCisOk
14829              && vex_control.guest_chase_cond
14830              && (Addr32)d32 != (Addr32)guest_EIP_bbstart
14831              && jmpDelta < 0
14832              && resteerOkFn( callback_opaque, (Addr64)(Addr32)d32) ) {
14833             /* Speculation: assume this backward branch is taken.  So
14834                we need to emit a side-exit to the insn following this
14835                one, on the negation of the condition, and continue at
14836                the branch target address (d32).  If we wind up back at
14837                the first instruction of the trace, just stop; it's
14838                better to let the IR loop unroller handle that case.*/
14839             stmt( IRStmt_Exit( 
14840                      mk_x86g_calculate_condition((X86Condcode)
14841                                                  (1 ^ (opc - 0x80))),
14842                      Ijk_Boring,
14843                      IRConst_U32(guest_EIP_bbstart+delta) ) );
14844             dres.whatNext   = Dis_ResteerC;
14845             dres.continueAt = (Addr64)(Addr32)d32;
14846             comment = "(assumed taken)";
14847          }
14848          else
14849          if (resteerCisOk
14850              && vex_control.guest_chase_cond
14851              && (Addr32)d32 != (Addr32)guest_EIP_bbstart
14852              && jmpDelta >= 0
14853              && resteerOkFn( callback_opaque, 
14854                              (Addr64)(Addr32)(guest_EIP_bbstart+delta)) ) {
14855             /* Speculation: assume this forward branch is not taken.
14856                So we need to emit a side-exit to d32 (the dest) and
14857                continue disassembling at the insn immediately
14858                following this one. */
14859             stmt( IRStmt_Exit( 
14860                      mk_x86g_calculate_condition((X86Condcode)(opc - 0x80)),
14861                      Ijk_Boring,
14862                      IRConst_U32(d32) ) );
14863             dres.whatNext   = Dis_ResteerC;
14864             dres.continueAt = (Addr64)(Addr32)(guest_EIP_bbstart+delta);
14865             comment = "(assumed not taken)";
14866          }
14867          else {
14868             /* Conservative default translation - end the block at
14869                this point. */
14870          jcc_01( (X86Condcode)(opc - 0x80), 
14871                     (Addr32)(guest_EIP_bbstart+delta), d32);
14872          dres.whatNext = Dis_StopHere;
14873          }
14874          DIP("j%s-32 0x%x %s\n", name_X86Condcode(opc - 0x80), d32, comment);
14875          break;
14876        }
14877
14878       /* =-=-=-=-=-=-=-=-=- RDTSC -=-=-=-=-=-=-=-=-=-=-= */
14879       case 0x31: { /* RDTSC */
14880          IRTemp   val  = newTemp(Ity_I64);
14881          IRExpr** args = mkIRExprVec_0();
14882          IRDirty* d    = unsafeIRDirty_1_N ( 
14883                             val, 
14884                             0/*regparms*/, 
14885                             "x86g_dirtyhelper_RDTSC", 
14886                             &x86g_dirtyhelper_RDTSC, 
14887                             args 
14888                          );
14889          /* execute the dirty call, dumping the result in val. */
14890          stmt( IRStmt_Dirty(d) );
14891          putIReg(4, R_EDX, unop(Iop_64HIto32, mkexpr(val)));
14892          putIReg(4, R_EAX, unop(Iop_64to32, mkexpr(val)));
14893          DIP("rdtsc\n");
14894          break;
14895       }
14896
14897       /* =-=-=-=-=-=-=-=-=- PUSH/POP Sreg =-=-=-=-=-=-=-=-=-= */
14898
14899       case 0xA1: /* POP %FS */
14900          dis_pop_segreg( R_FS, sz ); break;
14901       case 0xA9: /* POP %GS */
14902          dis_pop_segreg( R_GS, sz ); break;
14903
14904       case 0xA0: /* PUSH %FS */
14905          dis_push_segreg( R_FS, sz ); break;
14906       case 0xA8: /* PUSH %GS */
14907          dis_push_segreg( R_GS, sz ); break;
14908
14909       /* =-=-=-=-=-=-=-=-=- SETcc Eb =-=-=-=-=-=-=-=-=-= */
14910       case 0x90:
14911       case 0x91:
14912       case 0x92: /* set-Bb/set-NAEb (jump below) */
14913       case 0x93: /* set-NBb/set-AEb (jump not below) */
14914       case 0x94: /* set-Zb/set-Eb (jump zero) */
14915       case 0x95: /* set-NZb/set-NEb (jump not zero) */
14916       case 0x96: /* set-BEb/set-NAb (jump below or equal) */
14917       case 0x97: /* set-NBEb/set-Ab (jump not below or equal) */
14918       case 0x98: /* set-Sb (jump negative) */
14919       case 0x99: /* set-Sb (jump not negative) */
14920       case 0x9A: /* set-P (jump parity even) */
14921       case 0x9B: /* set-NP (jump parity odd) */
14922       case 0x9C: /* set-Lb/set-NGEb (jump less) */
14923       case 0x9D: /* set-GEb/set-NLb (jump greater or equal) */
14924       case 0x9E: /* set-LEb/set-NGb (jump less or equal) */
14925       case 0x9F: /* set-Gb/set-NLEb (jump greater) */
14926          t1 = newTemp(Ity_I8);
14927          assign( t1, unop(Iop_1Uto8,mk_x86g_calculate_condition(opc-0x90)) );
14928          modrm = getIByte(delta);
14929          if (epartIsReg(modrm)) {
14930             delta++;
14931             putIReg(1, eregOfRM(modrm), mkexpr(t1));
14932             DIP("set%s %s\n", name_X86Condcode(opc-0x90), 
14933                               nameIReg(1,eregOfRM(modrm)));
14934          } else {
14935            addr = disAMode ( &alen, sorb, delta, dis_buf );
14936            delta += alen;
14937            storeLE( mkexpr(addr), mkexpr(t1) );
14938            DIP("set%s %s\n", name_X86Condcode(opc-0x90), dis_buf);
14939          }
14940          break;
14941
14942       /* =-=-=-=-=-=-=-=-=- SHLD/SHRD -=-=-=-=-=-=-=-=-= */
14943
14944       case 0xA4: /* SHLDv imm8,Gv,Ev */
14945          modrm = getIByte(delta);
14946          d32   = delta + lengthAMode(delta);
14947          vex_sprintf(dis_buf, "$%d", getIByte(d32));
14948          delta = dis_SHLRD_Gv_Ev ( 
14949                   sorb, delta, modrm, sz, 
14950                   mkU8(getIByte(d32)), True, /* literal */
14951                   dis_buf, True );
14952          break;
14953       case 0xA5: /* SHLDv %cl,Gv,Ev */
14954          modrm = getIByte(delta);
14955          delta = dis_SHLRD_Gv_Ev ( 
14956                     sorb, delta, modrm, sz,
14957                     getIReg(1,R_ECX), False, /* not literal */
14958                     "%cl", True );
14959          break;
14960
14961       case 0xAC: /* SHRDv imm8,Gv,Ev */
14962          modrm = getIByte(delta);
14963          d32   = delta + lengthAMode(delta);
14964          vex_sprintf(dis_buf, "$%d", getIByte(d32));
14965          delta = dis_SHLRD_Gv_Ev ( 
14966                     sorb, delta, modrm, sz, 
14967                     mkU8(getIByte(d32)), True, /* literal */
14968                     dis_buf, False );
14969          break;
14970       case 0xAD: /* SHRDv %cl,Gv,Ev */
14971          modrm = getIByte(delta);
14972          delta = dis_SHLRD_Gv_Ev ( 
14973                     sorb, delta, modrm, sz, 
14974                     getIReg(1,R_ECX), False, /* not literal */
14975                     "%cl", False );
14976          break;
14977
14978       /* =-=-=-=-=-=-=-=-=- SYSENTER -=-=-=-=-=-=-=-=-=-= */
14979
14980       case 0x34:
14981          /* Simple implementation needing a long explaination.
14982
14983             sysenter is a kind of syscall entry.  The key thing here
14984             is that the return address is not known -- that is
14985             something that is beyond Vex's knowledge.  So this IR
14986             forces a return to the scheduler, which can do what it
14987             likes to simulate the systenter, but it MUST set this
14988             thread's guest_EIP field with the continuation address
14989             before resuming execution.  If that doesn't happen, the
14990             thread will jump to address zero, which is probably
14991             fatal. 
14992          */
14993
14994          /* Note where we are, so we can back up the guest to this
14995             point if the syscall needs to be restarted. */
14996          stmt( IRStmt_Put( OFFB_IP_AT_SYSCALL,
14997                            mkU32(guest_EIP_curr_instr) ) );
14998          jmp_lit(Ijk_Sys_sysenter, 0/*bogus next EIP value*/);
14999          dres.whatNext = Dis_StopHere;
15000          DIP("sysenter");
15001          break;
15002
15003       /* =-=-=-=-=-=-=-=-=- XADD -=-=-=-=-=-=-=-=-=-= */
15004
15005       case 0xC0: { /* XADD Gb,Eb */
15006          Bool decodeOK;
15007          delta = dis_xadd_G_E ( sorb, pfx_lock, 1, delta, &decodeOK );
15008          if (!decodeOK) goto decode_failure;
15009          break;
15010       }
15011       case 0xC1: { /* XADD Gv,Ev */
15012          Bool decodeOK;
15013          delta = dis_xadd_G_E ( sorb, pfx_lock, sz, delta, &decodeOK );
15014          if (!decodeOK) goto decode_failure;
15015          break;
15016       }
15017
15018       /* =-=-=-=-=-=-=-=-=- MMXery =-=-=-=-=-=-=-=-=-=-= */
15019
15020       case 0x71: 
15021       case 0x72: 
15022       case 0x73: /* PSLLgg/PSRAgg/PSRLgg mmxreg by imm8 */
15023
15024       case 0x6E: /* MOVD (src)ireg-or-mem, (dst)mmxreg */
15025       case 0x7E: /* MOVD (src)mmxreg, (dst)ireg-or-mem */
15026       case 0x7F: /* MOVQ (src)mmxreg, (dst)mmxreg-or-mem */
15027       case 0x6F: /* MOVQ (src)mmxreg-or-mem, (dst)mmxreg */
15028
15029       case 0xFC: 
15030       case 0xFD: 
15031       case 0xFE: /* PADDgg (src)mmxreg-or-mem, (dst)mmxreg */
15032
15033       case 0xEC: 
15034       case 0xED: /* PADDSgg (src)mmxreg-or-mem, (dst)mmxreg */
15035
15036       case 0xDC:
15037       case 0xDD: /* PADDUSgg (src)mmxreg-or-mem, (dst)mmxreg */
15038
15039       case 0xF8: 
15040       case 0xF9: 
15041       case 0xFA: /* PSUBgg (src)mmxreg-or-mem, (dst)mmxreg */
15042
15043       case 0xE8: 
15044       case 0xE9: /* PSUBSgg (src)mmxreg-or-mem, (dst)mmxreg */
15045
15046       case 0xD8: 
15047       case 0xD9: /* PSUBUSgg (src)mmxreg-or-mem, (dst)mmxreg */
15048
15049       case 0xE5: /* PMULHW (src)mmxreg-or-mem, (dst)mmxreg */
15050       case 0xD5: /* PMULLW (src)mmxreg-or-mem, (dst)mmxreg */
15051
15052       case 0xF5: /* PMADDWD (src)mmxreg-or-mem, (dst)mmxreg */
15053
15054       case 0x74: 
15055       case 0x75: 
15056       case 0x76: /* PCMPEQgg (src)mmxreg-or-mem, (dst)mmxreg */
15057
15058       case 0x64: 
15059       case 0x65: 
15060       case 0x66: /* PCMPGTgg (src)mmxreg-or-mem, (dst)mmxreg */
15061
15062       case 0x6B: /* PACKSSDW (src)mmxreg-or-mem, (dst)mmxreg */
15063       case 0x63: /* PACKSSWB (src)mmxreg-or-mem, (dst)mmxreg */
15064       case 0x67: /* PACKUSWB (src)mmxreg-or-mem, (dst)mmxreg */
15065
15066       case 0x68: 
15067       case 0x69: 
15068       case 0x6A: /* PUNPCKHgg (src)mmxreg-or-mem, (dst)mmxreg */
15069
15070       case 0x60: 
15071       case 0x61: 
15072       case 0x62: /* PUNPCKLgg (src)mmxreg-or-mem, (dst)mmxreg */
15073
15074       case 0xDB: /* PAND (src)mmxreg-or-mem, (dst)mmxreg */
15075       case 0xDF: /* PANDN (src)mmxreg-or-mem, (dst)mmxreg */
15076       case 0xEB: /* POR (src)mmxreg-or-mem, (dst)mmxreg */
15077       case 0xEF: /* PXOR (src)mmxreg-or-mem, (dst)mmxreg */
15078
15079       case 0xF1: /* PSLLgg (src)mmxreg-or-mem, (dst)mmxreg */
15080       case 0xF2: 
15081       case 0xF3: 
15082
15083       case 0xD1: /* PSRLgg (src)mmxreg-or-mem, (dst)mmxreg */
15084       case 0xD2: 
15085       case 0xD3: 
15086
15087       case 0xE1: /* PSRAgg (src)mmxreg-or-mem, (dst)mmxreg */
15088       case 0xE2: 
15089       {
15090          Int  delta0    = delta-1;
15091          Bool decode_OK = False;
15092
15093          /* If sz==2 this is SSE, and we assume sse idec has
15094             already spotted those cases by now. */
15095          if (sz != 4)
15096             goto decode_failure;
15097
15098          delta = dis_MMX ( &decode_OK, sorb, sz, delta-1 );
15099          if (!decode_OK) {
15100             delta = delta0;
15101             goto decode_failure;
15102          }
15103          break;
15104       }
15105
15106       case 0x77: /* EMMS */
15107          if (sz != 4)
15108             goto decode_failure;
15109          do_EMMS_preamble();
15110          DIP("emms\n");
15111          break;
15112
15113       /* =-=-=-=-=-=-=-=-=- SGDT and SIDT =-=-=-=-=-=-=-=-=-=-= */
15114       case 0x01: /* 0F 01 /0 -- SGDT */
15115                  /* 0F 01 /1 -- SIDT */
15116       {
15117           /* This is really revolting, but ... since each processor
15118              (core) only has one IDT and one GDT, just let the guest
15119              see it (pass-through semantics).  I can't see any way to
15120              construct a faked-up value, so don't bother to try. */
15121          modrm = getUChar(delta);
15122          addr = disAMode ( &alen, sorb, delta, dis_buf );
15123          delta += alen;
15124          if (epartIsReg(modrm)) goto decode_failure;
15125          if (gregOfRM(modrm) != 0 && gregOfRM(modrm) != 1)
15126             goto decode_failure;
15127          switch (gregOfRM(modrm)) {
15128             case 0: DIP("sgdt %s\n", dis_buf); break;
15129             case 1: DIP("sidt %s\n", dis_buf); break;
15130             default: vassert(0); /*NOTREACHED*/
15131          }
15132
15133          IRDirty* d = unsafeIRDirty_0_N (
15134                           0/*regparms*/,
15135                           "x86g_dirtyhelper_SxDT",
15136                           &x86g_dirtyhelper_SxDT,
15137                           mkIRExprVec_2( mkexpr(addr),
15138                                          mkU32(gregOfRM(modrm)) )
15139                       );
15140          /* declare we're writing memory */
15141          d->mFx   = Ifx_Write;
15142          d->mAddr = mkexpr(addr);
15143          d->mSize = 6;
15144          stmt( IRStmt_Dirty(d) );
15145          break;
15146       }
15147
15148       /* =-=-=-=-=-=-=-=-=- unimp2 =-=-=-=-=-=-=-=-=-=-= */
15149
15150       default:
15151          goto decode_failure;
15152    } /* switch (opc) for the 2-byte opcodes */
15153    goto decode_success;
15154    } /* case 0x0F: of primary opcode */
15155
15156    /* ------------------------ ??? ------------------------ */
15157   
15158   default:
15159   decode_failure:
15160    /* All decode failures end up here. */
15161    vex_printf("vex x86->IR: unhandled instruction bytes: "
15162               "0x%x 0x%x 0x%x 0x%x\n",
15163               (Int)getIByte(delta_start+0),
15164               (Int)getIByte(delta_start+1),
15165               (Int)getIByte(delta_start+2),
15166               (Int)getIByte(delta_start+3) );
15167
15168    /* Tell the dispatcher that this insn cannot be decoded, and so has
15169       not been executed, and (is currently) the next to be executed.
15170       EIP should be up-to-date since it made so at the start of each
15171       insn, but nevertheless be paranoid and update it again right
15172       now. */
15173    stmt( IRStmt_Put( OFFB_EIP, mkU32(guest_EIP_curr_instr) ) );
15174    jmp_lit(Ijk_NoDecode, guest_EIP_curr_instr);
15175    dres.whatNext = Dis_StopHere;
15176    dres.len = 0;
15177    /* We also need to say that a CAS is not expected now, regardless
15178       of what it might have been set to at the start of the function,
15179       since the IR that we've emitted just above (to synthesis a
15180       SIGILL) does not involve any CAS, and presumably no other IR has
15181       been emitted for this (non-decoded) insn. */
15182    *expect_CAS = False;
15183    return dres;
15184
15185    } /* switch (opc) for the main (primary) opcode switch. */
15186
15187   decode_success:
15188    /* All decode successes end up here. */
15189    DIP("\n");
15190    dres.len = delta - delta_start;
15191    return dres;
15192 }
15193
15194 #undef DIP
15195 #undef DIS
15196
15197
15198 /*------------------------------------------------------------*/
15199 /*--- Top-level fn                                         ---*/
15200 /*------------------------------------------------------------*/
15201
15202 /* Disassemble a single instruction into IR.  The instruction
15203    is located in host memory at &guest_code[delta]. */
15204
15205 DisResult disInstr_X86 ( IRSB*        irsb_IN,
15206                          Bool         put_IP,
15207                          Bool         (*resteerOkFn) ( void*, Addr64 ),
15208                          Bool         resteerCisOk,
15209                          void*        callback_opaque,
15210                          UChar*       guest_code_IN,
15211                          Long         delta,
15212                          Addr64       guest_IP,
15213                          VexArch      guest_arch,
15214                          VexArchInfo* archinfo,
15215                          VexAbiInfo*  abiinfo,
15216                          Bool         host_bigendian_IN )
15217 {
15218    Int       i, x1, x2;
15219    Bool      expect_CAS, has_CAS;
15220    DisResult dres;
15221
15222    /* Set globals (see top of this file) */
15223    vassert(guest_arch == VexArchX86);
15224    guest_code           = guest_code_IN;
15225    irsb                 = irsb_IN;
15226    host_is_bigendian    = host_bigendian_IN;
15227    guest_EIP_curr_instr = (Addr32)guest_IP;
15228    guest_EIP_bbstart    = (Addr32)toUInt(guest_IP - delta);
15229
15230    x1 = irsb_IN->stmts_used;
15231    expect_CAS = False;
15232    dres = disInstr_X86_WRK ( &expect_CAS, put_IP, resteerOkFn,
15233                              resteerCisOk,
15234                              callback_opaque,
15235                              delta, archinfo, abiinfo );
15236    x2 = irsb_IN->stmts_used;
15237    vassert(x2 >= x1);
15238
15239    /* See comment at the top of disInstr_X86_WRK for meaning of
15240       expect_CAS.  Here, we (sanity-)check for the presence/absence of
15241       IRCAS as directed by the returned expect_CAS value. */
15242    has_CAS = False;
15243    for (i = x1; i < x2; i++) {
15244       if (irsb_IN->stmts[i]->tag == Ist_CAS)
15245          has_CAS = True;
15246    }
15247
15248    if (expect_CAS != has_CAS) {
15249       /* inconsistency detected.  re-disassemble the instruction so as
15250          to generate a useful error message; then assert. */
15251       vex_traceflags |= VEX_TRACE_FE;
15252       dres = disInstr_X86_WRK ( &expect_CAS, put_IP, resteerOkFn,
15253                                 resteerCisOk,
15254                                 callback_opaque,
15255                                 delta, archinfo, abiinfo );
15256       for (i = x1; i < x2; i++) {
15257          vex_printf("\t\t");
15258          ppIRStmt(irsb_IN->stmts[i]);
15259          vex_printf("\n");
15260       }
15261       /* Failure of this assertion is serious and denotes a bug in
15262          disInstr. */
15263       vpanic("disInstr_X86: inconsistency in LOCK prefix handling");
15264    }
15265
15266    return dres;
15267 }
15268
15269
15270 /*--------------------------------------------------------------------*/
15271 /*--- end                                         guest_x86_toIR.c ---*/
15272 /*--------------------------------------------------------------------*/