]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/valgrind/src/valgrind-3.6.0-svn/VEX/priv/guest_x86_toIR.c
a877a49169dc87cbcb83072b805562ca200cc9a8
[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, mkU32(0) ));
1002 }
1003
1004
1005 /* For the inc/dec case, we store in DEP1 the result value and in NDEP
1006    the former value of the carry flag, which unfortunately we have to
1007    compute. */
1008
1009 static void setFlags_INC_DEC ( Bool inc, IRTemp res, IRType ty )
1010 {
1011    Int ccOp = inc ? X86G_CC_OP_INCB : X86G_CC_OP_DECB;
1012    
1013    ccOp += ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : 2);
1014    vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32);
1015
1016    /* This has to come first, because calculating the C flag 
1017       may require reading all four thunk fields. */
1018    stmt( IRStmt_Put( OFFB_CC_NDEP, mk_x86g_calculate_eflags_c()) );
1019    stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(ccOp)) );
1020    stmt( IRStmt_Put( OFFB_CC_DEP1, widenUto32(mkexpr(res))) );
1021    stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0)) );
1022 }
1023
1024
1025 /* Multiplies are pretty much like add and sub: DEP1 and DEP2 hold the
1026    two arguments. */
1027
1028 static
1029 void setFlags_MUL ( IRType ty, IRTemp arg1, IRTemp arg2, UInt base_op )
1030 {
1031    switch (ty) {
1032       case Ity_I8:
1033          stmt( IRStmt_Put( OFFB_CC_OP, mkU32(base_op+0) ) );
1034          break;
1035       case Ity_I16:
1036          stmt( IRStmt_Put( OFFB_CC_OP, mkU32(base_op+1) ) );
1037          break;
1038       case Ity_I32:
1039          stmt( IRStmt_Put( OFFB_CC_OP, mkU32(base_op+2) ) );
1040          break;
1041       default:
1042          vpanic("setFlags_MUL(x86)");
1043    }
1044    stmt( IRStmt_Put( OFFB_CC_DEP1, widenUto32(mkexpr(arg1)) ));
1045    stmt( IRStmt_Put( OFFB_CC_DEP2, widenUto32(mkexpr(arg2)) ));
1046    /* Set NDEP even though it isn't used.  This makes redundant-PUT
1047       elimination of previous stores to this field work better. */
1048    stmt( IRStmt_Put( OFFB_CC_NDEP, mkU32(0) ));
1049 }
1050
1051
1052 /* -------------- Condition codes. -------------- */
1053
1054 /* Condition codes, using the Intel encoding.  */
1055
1056 static HChar* name_X86Condcode ( X86Condcode cond )
1057 {
1058    switch (cond) {
1059       case X86CondO:      return "o";
1060       case X86CondNO:     return "no";
1061       case X86CondB:      return "b";
1062       case X86CondNB:     return "nb";
1063       case X86CondZ:      return "z";
1064       case X86CondNZ:     return "nz";
1065       case X86CondBE:     return "be";
1066       case X86CondNBE:    return "nbe";
1067       case X86CondS:      return "s";
1068       case X86CondNS:     return "ns";
1069       case X86CondP:      return "p";
1070       case X86CondNP:     return "np";
1071       case X86CondL:      return "l";
1072       case X86CondNL:     return "nl";
1073       case X86CondLE:     return "le";
1074       case X86CondNLE:    return "nle";
1075       case X86CondAlways: return "ALWAYS";
1076       default: vpanic("name_X86Condcode");
1077    }
1078 }
1079
1080 static 
1081 X86Condcode positiveIse_X86Condcode ( X86Condcode  cond,
1082                                       Bool*        needInvert )
1083 {
1084    vassert(cond >= X86CondO && cond <= X86CondNLE);
1085    if (cond & 1) {
1086       *needInvert = True;
1087       return cond-1;
1088    } else {
1089       *needInvert = False;
1090       return cond;
1091    }
1092 }
1093
1094
1095 /* -------------- Helpers for ADD/SUB with carry. -------------- */
1096
1097 /* Given ta1, ta2 and tres, compute tres = ADC(ta1,ta2) and set flags
1098    appropriately.
1099
1100    Optionally, generate a store for the 'tres' value.  This can either
1101    be a normal store, or it can be a cas-with-possible-failure style
1102    store:
1103
1104    if taddr is IRTemp_INVALID, then no store is generated.
1105
1106    if taddr is not IRTemp_INVALID, then a store (using taddr as
1107    the address) is generated:
1108
1109      if texpVal is IRTemp_INVALID then a normal store is
1110      generated, and restart_point must be zero (it is irrelevant).
1111
1112      if texpVal is not IRTemp_INVALID then a cas-style store is
1113      generated.  texpVal is the expected value, restart_point
1114      is the restart point if the store fails, and texpVal must
1115      have the same type as tres.   
1116 */
1117 static void helper_ADC ( Int sz,
1118                          IRTemp tres, IRTemp ta1, IRTemp ta2,
1119                          /* info about optional store: */
1120                          IRTemp taddr, IRTemp texpVal, Addr32 restart_point )
1121 {
1122    UInt    thunkOp;
1123    IRType  ty    = szToITy(sz);
1124    IRTemp  oldc  = newTemp(Ity_I32);
1125    IRTemp  oldcn = newTemp(ty);
1126    IROp    plus  = mkSizedOp(ty, Iop_Add8);
1127    IROp    xor   = mkSizedOp(ty, Iop_Xor8);
1128
1129    vassert(typeOfIRTemp(irsb->tyenv, tres) == ty);
1130    vassert(sz == 1 || sz == 2 || sz == 4);
1131    thunkOp = sz==4 ? X86G_CC_OP_ADCL 
1132                    : (sz==2 ? X86G_CC_OP_ADCW : X86G_CC_OP_ADCB);
1133
1134    /* oldc = old carry flag, 0 or 1 */
1135    assign( oldc,  binop(Iop_And32,
1136                         mk_x86g_calculate_eflags_c(),
1137                         mkU32(1)) );
1138
1139    assign( oldcn, narrowTo(ty, mkexpr(oldc)) );
1140
1141    assign( tres, binop(plus,
1142                        binop(plus,mkexpr(ta1),mkexpr(ta2)),
1143                        mkexpr(oldcn)) );
1144
1145    /* Possibly generate a store of 'tres' to 'taddr'.  See comment at
1146       start of this function. */
1147    if (taddr != IRTemp_INVALID) {
1148       if (texpVal == IRTemp_INVALID) {
1149          vassert(restart_point == 0);
1150          storeLE( mkexpr(taddr), mkexpr(tres) );
1151       } else {
1152          vassert(typeOfIRTemp(irsb->tyenv, texpVal) == ty);
1153          /* .. and hence 'texpVal' has the same type as 'tres'. */
1154          casLE( mkexpr(taddr),
1155                 mkexpr(texpVal), mkexpr(tres), restart_point );
1156       }
1157    }
1158
1159    stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(thunkOp) ) );
1160    stmt( IRStmt_Put( OFFB_CC_DEP1, widenUto32(mkexpr(ta1)) ));
1161    stmt( IRStmt_Put( OFFB_CC_DEP2, widenUto32(binop(xor, mkexpr(ta2), 
1162                                                          mkexpr(oldcn)) )) );
1163    stmt( IRStmt_Put( OFFB_CC_NDEP, mkexpr(oldc) ) );
1164 }
1165
1166
1167 /* Given ta1, ta2 and tres, compute tres = SBB(ta1,ta2) and set flags
1168    appropriately.  As with helper_ADC, possibly generate a store of
1169    the result -- see comments on helper_ADC for details.
1170 */
1171 static void helper_SBB ( Int sz,
1172                          IRTemp tres, IRTemp ta1, IRTemp ta2,
1173                          /* info about optional store: */
1174                          IRTemp taddr, IRTemp texpVal, Addr32 restart_point )
1175 {
1176    UInt    thunkOp;
1177    IRType  ty    = szToITy(sz);
1178    IRTemp  oldc  = newTemp(Ity_I32);
1179    IRTemp  oldcn = newTemp(ty);
1180    IROp    minus = mkSizedOp(ty, Iop_Sub8);
1181    IROp    xor   = mkSizedOp(ty, Iop_Xor8);
1182
1183    vassert(typeOfIRTemp(irsb->tyenv, tres) == ty);
1184    vassert(sz == 1 || sz == 2 || sz == 4);
1185    thunkOp = sz==4 ? X86G_CC_OP_SBBL 
1186                    : (sz==2 ? X86G_CC_OP_SBBW : X86G_CC_OP_SBBB);
1187
1188    /* oldc = old carry flag, 0 or 1 */
1189    assign( oldc, binop(Iop_And32,
1190                        mk_x86g_calculate_eflags_c(),
1191                        mkU32(1)) );
1192
1193    assign( oldcn, narrowTo(ty, mkexpr(oldc)) );
1194
1195    assign( tres, binop(minus,
1196                        binop(minus,mkexpr(ta1),mkexpr(ta2)),
1197                        mkexpr(oldcn)) );
1198
1199    /* Possibly generate a store of 'tres' to 'taddr'.  See comment at
1200       start of this function. */
1201    if (taddr != IRTemp_INVALID) {
1202       if (texpVal == IRTemp_INVALID) {
1203          vassert(restart_point == 0);
1204          storeLE( mkexpr(taddr), mkexpr(tres) );
1205       } else {
1206          vassert(typeOfIRTemp(irsb->tyenv, texpVal) == ty);
1207          /* .. and hence 'texpVal' has the same type as 'tres'. */
1208          casLE( mkexpr(taddr),
1209                 mkexpr(texpVal), mkexpr(tres), restart_point );
1210       }
1211    }
1212
1213    stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(thunkOp) ) );
1214    stmt( IRStmt_Put( OFFB_CC_DEP1, widenUto32(mkexpr(ta1) )) );
1215    stmt( IRStmt_Put( OFFB_CC_DEP2, widenUto32(binop(xor, mkexpr(ta2), 
1216                                                          mkexpr(oldcn)) )) );
1217    stmt( IRStmt_Put( OFFB_CC_NDEP, mkexpr(oldc) ) );
1218 }
1219
1220
1221 /* -------------- Helpers for disassembly printing. -------------- */
1222
1223 static HChar* nameGrp1 ( Int opc_aux )
1224 {
1225    static HChar* grp1_names[8] 
1226      = { "add", "or", "adc", "sbb", "and", "sub", "xor", "cmp" };
1227    if (opc_aux < 0 || opc_aux > 7) vpanic("nameGrp1(x86)");
1228    return grp1_names[opc_aux];
1229 }
1230
1231 static HChar* nameGrp2 ( Int opc_aux )
1232 {
1233    static HChar* grp2_names[8] 
1234      = { "rol", "ror", "rcl", "rcr", "shl", "shr", "shl", "sar" };
1235    if (opc_aux < 0 || opc_aux > 7) vpanic("nameGrp2(x86)");
1236    return grp2_names[opc_aux];
1237 }
1238
1239 static HChar* nameGrp4 ( Int opc_aux )
1240 {
1241    static HChar* grp4_names[8] 
1242      = { "inc", "dec", "???", "???", "???", "???", "???", "???" };
1243    if (opc_aux < 0 || opc_aux > 1) vpanic("nameGrp4(x86)");
1244    return grp4_names[opc_aux];
1245 }
1246
1247 static HChar* nameGrp5 ( Int opc_aux )
1248 {
1249    static HChar* grp5_names[8] 
1250      = { "inc", "dec", "call*", "call*", "jmp*", "jmp*", "push", "???" };
1251    if (opc_aux < 0 || opc_aux > 6) vpanic("nameGrp5(x86)");
1252    return grp5_names[opc_aux];
1253 }
1254
1255 static HChar* nameGrp8 ( Int opc_aux )
1256 {
1257    static HChar* grp8_names[8] 
1258      = { "???", "???", "???", "???", "bt", "bts", "btr", "btc" };
1259    if (opc_aux < 4 || opc_aux > 7) vpanic("nameGrp8(x86)");
1260    return grp8_names[opc_aux];
1261 }
1262
1263 static HChar* nameIReg ( Int size, Int reg )
1264 {
1265    static HChar* ireg32_names[8] 
1266      = { "%eax", "%ecx", "%edx", "%ebx", 
1267          "%esp", "%ebp", "%esi", "%edi" };
1268    static HChar* ireg16_names[8] 
1269      = { "%ax", "%cx", "%dx", "%bx", "%sp", "%bp", "%si", "%di" };
1270    static HChar* ireg8_names[8] 
1271      = { "%al", "%cl", "%dl", "%bl", 
1272          "%ah{sp}", "%ch{bp}", "%dh{si}", "%bh{di}" };
1273    if (reg < 0 || reg > 7) goto bad;
1274    switch (size) {
1275       case 4: return ireg32_names[reg];
1276       case 2: return ireg16_names[reg];
1277       case 1: return ireg8_names[reg];
1278    }
1279   bad:
1280    vpanic("nameIReg(X86)");
1281    return NULL; /*notreached*/
1282 }
1283
1284 static HChar* nameSReg ( UInt sreg )
1285 {
1286    switch (sreg) {
1287       case R_ES: return "%es";
1288       case R_CS: return "%cs";
1289       case R_SS: return "%ss";
1290       case R_DS: return "%ds";
1291       case R_FS: return "%fs";
1292       case R_GS: return "%gs";
1293       default: vpanic("nameSReg(x86)");
1294    }
1295 }
1296
1297 static HChar* nameMMXReg ( Int mmxreg )
1298 {
1299    static HChar* mmx_names[8] 
1300      = { "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7" };
1301    if (mmxreg < 0 || mmxreg > 7) vpanic("nameMMXReg(x86,guest)");
1302    return mmx_names[mmxreg];
1303 }
1304
1305 static HChar* nameXMMReg ( Int xmmreg )
1306 {
1307    static HChar* xmm_names[8] 
1308      = { "%xmm0", "%xmm1", "%xmm2", "%xmm3", 
1309          "%xmm4", "%xmm5", "%xmm6", "%xmm7" };
1310    if (xmmreg < 0 || xmmreg > 7) vpanic("name_of_xmm_reg");
1311    return xmm_names[xmmreg];
1312 }
1313  
1314 static HChar* nameMMXGran ( Int gran )
1315 {
1316    switch (gran) {
1317       case 0: return "b";
1318       case 1: return "w";
1319       case 2: return "d";
1320       case 3: return "q";
1321       default: vpanic("nameMMXGran(x86,guest)");
1322    }
1323 }
1324
1325 static HChar nameISize ( Int size )
1326 {
1327    switch (size) {
1328       case 4: return 'l';
1329       case 2: return 'w';
1330       case 1: return 'b';
1331       default: vpanic("nameISize(x86)");
1332    }
1333 }
1334
1335
1336 /*------------------------------------------------------------*/
1337 /*--- JMP helpers                                          ---*/
1338 /*------------------------------------------------------------*/
1339
1340 static void jmp_lit( IRJumpKind kind, Addr32 d32 )
1341 {
1342    irsb->next     = mkU32(d32);
1343    irsb->jumpkind = kind;
1344 }
1345
1346 static void jmp_treg( IRJumpKind kind, IRTemp t )
1347 {
1348    irsb->next = mkexpr(t);
1349    irsb->jumpkind = kind;
1350 }
1351
1352 static 
1353 void jcc_01( X86Condcode cond, Addr32 d32_false, Addr32 d32_true )
1354 {
1355    Bool        invert;
1356    X86Condcode condPos;
1357    condPos = positiveIse_X86Condcode ( cond, &invert );
1358    if (invert) {
1359       stmt( IRStmt_Exit( mk_x86g_calculate_condition(condPos),
1360                          Ijk_Boring,
1361                          IRConst_U32(d32_false) ) );
1362       irsb->next     = mkU32(d32_true);
1363       irsb->jumpkind = Ijk_Boring;
1364    } else {
1365       stmt( IRStmt_Exit( mk_x86g_calculate_condition(condPos),
1366                          Ijk_Boring,
1367                          IRConst_U32(d32_true) ) );
1368       irsb->next     = mkU32(d32_false);
1369       irsb->jumpkind = Ijk_Boring;
1370    }
1371 }
1372
1373
1374 /*------------------------------------------------------------*/
1375 /*--- Disassembling addressing modes                       ---*/
1376 /*------------------------------------------------------------*/
1377
1378 static 
1379 HChar* sorbTxt ( UChar sorb )
1380 {
1381    switch (sorb) {
1382       case 0:    return ""; /* no override */
1383       case 0x3E: return "%ds";
1384       case 0x26: return "%es:";
1385       case 0x64: return "%fs:";
1386       case 0x65: return "%gs:";
1387       default: vpanic("sorbTxt(x86,guest)");
1388    }
1389 }
1390
1391
1392 /* 'virtual' is an IRExpr* holding a virtual address.  Convert it to a
1393    linear address by adding any required segment override as indicated
1394    by sorb. */
1395 static
1396 IRExpr* handleSegOverride ( UChar sorb, IRExpr* virtual )
1397 {
1398    Int    sreg;
1399    IRType hWordTy;
1400    IRTemp ldt_ptr, gdt_ptr, seg_selector, r64;
1401
1402    if (sorb == 0)
1403       /* the common case - no override */
1404       return virtual;
1405
1406    switch (sorb) {
1407       case 0x3E: sreg = R_DS; break;
1408       case 0x26: sreg = R_ES; break;
1409       case 0x64: sreg = R_FS; break;
1410       case 0x65: sreg = R_GS; break;
1411       default: vpanic("handleSegOverride(x86,guest)");
1412    }
1413
1414    hWordTy = sizeof(HWord)==4 ? Ity_I32 : Ity_I64;
1415
1416    seg_selector = newTemp(Ity_I32);
1417    ldt_ptr      = newTemp(hWordTy);
1418    gdt_ptr      = newTemp(hWordTy);
1419    r64          = newTemp(Ity_I64);
1420
1421    assign( seg_selector, unop(Iop_16Uto32, getSReg(sreg)) );
1422    assign( ldt_ptr, IRExpr_Get( OFFB_LDT, hWordTy ));
1423    assign( gdt_ptr, IRExpr_Get( OFFB_GDT, hWordTy ));
1424
1425    /*
1426    Call this to do the translation and limit checks: 
1427    ULong x86g_use_seg_selector ( HWord ldt, HWord gdt,
1428                                  UInt seg_selector, UInt virtual_addr )
1429    */
1430    assign( 
1431       r64, 
1432       mkIRExprCCall( 
1433          Ity_I64, 
1434          0/*regparms*/, 
1435          "x86g_use_seg_selector", 
1436          &x86g_use_seg_selector, 
1437          mkIRExprVec_4( mkexpr(ldt_ptr), mkexpr(gdt_ptr), 
1438                         mkexpr(seg_selector), virtual)
1439       )
1440    );
1441
1442    /* If the high 32 of the result are non-zero, there was a 
1443       failure in address translation.  In which case, make a
1444       quick exit.
1445    */
1446    stmt( 
1447       IRStmt_Exit(
1448          binop(Iop_CmpNE32, unop(Iop_64HIto32, mkexpr(r64)), mkU32(0)),
1449          Ijk_MapFail,
1450          IRConst_U32( guest_EIP_curr_instr )
1451       )
1452    );
1453
1454    /* otherwise, here's the translated result. */
1455    return unop(Iop_64to32, mkexpr(r64));
1456 }
1457
1458
1459 /* Generate IR to calculate an address indicated by a ModRM and
1460    following SIB bytes.  The expression, and the number of bytes in
1461    the address mode, are returned.  Note that this fn should not be
1462    called if the R/M part of the address denotes a register instead of
1463    memory.  If print_codegen is true, text of the addressing mode is
1464    placed in buf. 
1465
1466    The computed address is stored in a new tempreg, and the
1467    identity of the tempreg is returned.  */
1468
1469 static IRTemp disAMode_copy2tmp ( IRExpr* addr32 )
1470 {
1471    IRTemp tmp = newTemp(Ity_I32);
1472    assign( tmp, addr32 );
1473    return tmp;
1474 }
1475
1476 static 
1477 IRTemp disAMode ( Int* len, UChar sorb, Int delta, HChar* buf )
1478 {
1479    UChar mod_reg_rm = getIByte(delta);
1480    delta++;
1481
1482    buf[0] = (UChar)0;
1483
1484    /* squeeze out the reg field from mod_reg_rm, since a 256-entry
1485       jump table seems a bit excessive. 
1486    */
1487    mod_reg_rm &= 0xC7;                      /* is now XX000YYY */
1488    mod_reg_rm  = toUChar(mod_reg_rm | (mod_reg_rm >> 3));  
1489                                             /* is now XX0XXYYY */
1490    mod_reg_rm &= 0x1F;                      /* is now 000XXYYY */
1491    switch (mod_reg_rm) {
1492
1493       /* (%eax) .. (%edi), not including (%esp) or (%ebp).
1494          --> GET %reg, t 
1495       */
1496       case 0x00: case 0x01: case 0x02: case 0x03: 
1497       /* ! 04 */ /* ! 05 */ case 0x06: case 0x07:
1498          { UChar rm = mod_reg_rm;
1499            DIS(buf, "%s(%s)", sorbTxt(sorb), nameIReg(4,rm));
1500            *len = 1;
1501            return disAMode_copy2tmp(
1502                   handleSegOverride(sorb, getIReg(4,rm)));
1503          }
1504
1505       /* d8(%eax) ... d8(%edi), not including d8(%esp) 
1506          --> GET %reg, t ; ADDL d8, t
1507       */
1508       case 0x08: case 0x09: case 0x0A: case 0x0B: 
1509       /* ! 0C */ case 0x0D: case 0x0E: case 0x0F:
1510          { UChar rm = toUChar(mod_reg_rm & 7);
1511            UInt  d  = getSDisp8(delta);
1512            DIS(buf, "%s%d(%s)", sorbTxt(sorb), (Int)d, nameIReg(4,rm));
1513            *len = 2;
1514            return disAMode_copy2tmp(
1515                   handleSegOverride(sorb,
1516                      binop(Iop_Add32,getIReg(4,rm),mkU32(d))));
1517          }
1518
1519       /* d32(%eax) ... d32(%edi), not including d32(%esp)
1520          --> GET %reg, t ; ADDL d8, t
1521       */
1522       case 0x10: case 0x11: case 0x12: case 0x13: 
1523       /* ! 14 */ case 0x15: case 0x16: case 0x17:
1524          { UChar rm = toUChar(mod_reg_rm & 7);
1525            UInt  d  = getUDisp32(delta);
1526            DIS(buf, "%s0x%x(%s)", sorbTxt(sorb), (Int)d, nameIReg(4,rm));
1527            *len = 5;
1528            return disAMode_copy2tmp(
1529                   handleSegOverride(sorb,
1530                      binop(Iop_Add32,getIReg(4,rm),mkU32(d))));
1531          }
1532
1533       /* a register, %eax .. %edi.  This shouldn't happen. */
1534       case 0x18: case 0x19: case 0x1A: case 0x1B:
1535       case 0x1C: case 0x1D: case 0x1E: case 0x1F:
1536          vpanic("disAMode(x86): not an addr!");
1537
1538       /* a 32-bit literal address
1539          --> MOV d32, tmp 
1540       */
1541       case 0x05: 
1542          { UInt d = getUDisp32(delta);
1543            *len = 5;
1544            DIS(buf, "%s(0x%x)", sorbTxt(sorb), d);
1545            return disAMode_copy2tmp( 
1546                      handleSegOverride(sorb, mkU32(d)));
1547          }
1548
1549       case 0x04: {
1550          /* SIB, with no displacement.  Special cases:
1551             -- %esp cannot act as an index value.  
1552                If index_r indicates %esp, zero is used for the index.
1553             -- when mod is zero and base indicates EBP, base is instead
1554                a 32-bit literal.
1555             It's all madness, I tell you.  Extract %index, %base and 
1556             scale from the SIB byte.  The value denoted is then:
1557                | %index == %ESP && %base == %EBP
1558                = d32 following SIB byte
1559                | %index == %ESP && %base != %EBP
1560                = %base
1561                | %index != %ESP && %base == %EBP
1562                = d32 following SIB byte + (%index << scale)
1563                | %index != %ESP && %base != %ESP
1564                = %base + (%index << scale)
1565
1566             What happens to the souls of CPU architects who dream up such
1567             horrendous schemes, do you suppose?  
1568          */
1569          UChar sib     = getIByte(delta);
1570          UChar scale   = toUChar((sib >> 6) & 3);
1571          UChar index_r = toUChar((sib >> 3) & 7);
1572          UChar base_r  = toUChar(sib & 7);
1573          delta++;
1574
1575          if (index_r != R_ESP && base_r != R_EBP) {
1576             DIS(buf, "%s(%s,%s,%d)", sorbTxt(sorb), 
1577                       nameIReg(4,base_r), nameIReg(4,index_r), 1<<scale);
1578             *len = 2;
1579             return
1580                disAMode_copy2tmp( 
1581                handleSegOverride(sorb,
1582                   binop(Iop_Add32, 
1583                         getIReg(4,base_r),
1584                         binop(Iop_Shl32, getIReg(4,index_r),
1585                               mkU8(scale)))));
1586          }
1587
1588          if (index_r != R_ESP && base_r == R_EBP) {
1589             UInt d = getUDisp32(delta);
1590             DIS(buf, "%s0x%x(,%s,%d)", sorbTxt(sorb), d, 
1591                       nameIReg(4,index_r), 1<<scale);
1592             *len = 6;
1593             return
1594                disAMode_copy2tmp(
1595                handleSegOverride(sorb, 
1596                   binop(Iop_Add32,
1597                         binop(Iop_Shl32, getIReg(4,index_r), mkU8(scale)),
1598                         mkU32(d))));
1599          }
1600
1601          if (index_r == R_ESP && base_r != R_EBP) {
1602             DIS(buf, "%s(%s,,)", sorbTxt(sorb), nameIReg(4,base_r));
1603             *len = 2;
1604             return disAMode_copy2tmp(
1605                    handleSegOverride(sorb, getIReg(4,base_r)));
1606          }
1607
1608          if (index_r == R_ESP && base_r == R_EBP) {
1609             UInt d = getUDisp32(delta);
1610             DIS(buf, "%s0x%x(,,)", sorbTxt(sorb), d);
1611             *len = 6;
1612             return disAMode_copy2tmp(
1613                    handleSegOverride(sorb, mkU32(d)));
1614          }
1615          /*NOTREACHED*/
1616          vassert(0);
1617       }
1618
1619       /* SIB, with 8-bit displacement.  Special cases:
1620          -- %esp cannot act as an index value.  
1621             If index_r indicates %esp, zero is used for the index.
1622          Denoted value is:
1623             | %index == %ESP
1624             = d8 + %base
1625             | %index != %ESP
1626             = d8 + %base + (%index << scale)
1627       */
1628       case 0x0C: {
1629          UChar sib     = getIByte(delta);
1630          UChar scale   = toUChar((sib >> 6) & 3);
1631          UChar index_r = toUChar((sib >> 3) & 7);
1632          UChar base_r  = toUChar(sib & 7);
1633          UInt  d       = getSDisp8(delta+1);
1634
1635          if (index_r == R_ESP) {
1636             DIS(buf, "%s%d(%s,,)", sorbTxt(sorb), 
1637                                    (Int)d, nameIReg(4,base_r));
1638             *len = 3;
1639             return disAMode_copy2tmp(
1640                    handleSegOverride(sorb, 
1641                       binop(Iop_Add32, getIReg(4,base_r), mkU32(d)) ));
1642          } else {
1643             DIS(buf, "%s%d(%s,%s,%d)", sorbTxt(sorb), (Int)d, 
1644                      nameIReg(4,base_r), nameIReg(4,index_r), 1<<scale);
1645             *len = 3;
1646             return 
1647                 disAMode_copy2tmp(
1648                 handleSegOverride(sorb,
1649                   binop(Iop_Add32,
1650                         binop(Iop_Add32, 
1651                               getIReg(4,base_r), 
1652                               binop(Iop_Shl32, 
1653                                     getIReg(4,index_r), mkU8(scale))),
1654                         mkU32(d))));
1655          }
1656          /*NOTREACHED*/
1657          vassert(0);
1658       }
1659
1660       /* SIB, with 32-bit displacement.  Special cases:
1661          -- %esp cannot act as an index value.  
1662             If index_r indicates %esp, zero is used for the index.
1663          Denoted value is:
1664             | %index == %ESP
1665             = d32 + %base
1666             | %index != %ESP
1667             = d32 + %base + (%index << scale)
1668       */
1669       case 0x14: {
1670          UChar sib     = getIByte(delta);
1671          UChar scale   = toUChar((sib >> 6) & 3);
1672          UChar index_r = toUChar((sib >> 3) & 7);
1673          UChar base_r  = toUChar(sib & 7);
1674          UInt d        = getUDisp32(delta+1);
1675
1676          if (index_r == R_ESP) {
1677             DIS(buf, "%s%d(%s,,)", sorbTxt(sorb), 
1678                                    (Int)d, nameIReg(4,base_r));
1679             *len = 6;
1680             return disAMode_copy2tmp(
1681                    handleSegOverride(sorb, 
1682                       binop(Iop_Add32, getIReg(4,base_r), mkU32(d)) ));
1683          } else {
1684             DIS(buf, "%s%d(%s,%s,%d)", sorbTxt(sorb), (Int)d, 
1685                      nameIReg(4,base_r), nameIReg(4,index_r), 1<<scale);
1686             *len = 6;
1687             return 
1688                 disAMode_copy2tmp(
1689                 handleSegOverride(sorb,
1690                   binop(Iop_Add32,
1691                         binop(Iop_Add32, 
1692                               getIReg(4,base_r), 
1693                               binop(Iop_Shl32, 
1694                                     getIReg(4,index_r), mkU8(scale))),
1695                         mkU32(d))));
1696          }
1697          /*NOTREACHED*/
1698          vassert(0);
1699       }
1700
1701       default:
1702          vpanic("disAMode(x86)");
1703          return 0; /*notreached*/
1704    }
1705 }
1706
1707
1708 /* Figure out the number of (insn-stream) bytes constituting the amode
1709    beginning at delta.  Is useful for getting hold of literals beyond
1710    the end of the amode before it has been disassembled.  */
1711
1712 static UInt lengthAMode ( Int delta )
1713 {
1714    UChar mod_reg_rm = getIByte(delta); delta++;
1715
1716    /* squeeze out the reg field from mod_reg_rm, since a 256-entry
1717       jump table seems a bit excessive. 
1718    */
1719    mod_reg_rm &= 0xC7;               /* is now XX000YYY */
1720    mod_reg_rm  = toUChar(mod_reg_rm | (mod_reg_rm >> 3));  
1721                                      /* is now XX0XXYYY */
1722    mod_reg_rm &= 0x1F;               /* is now 000XXYYY */
1723    switch (mod_reg_rm) {
1724
1725       /* (%eax) .. (%edi), not including (%esp) or (%ebp). */
1726       case 0x00: case 0x01: case 0x02: case 0x03: 
1727       /* ! 04 */ /* ! 05 */ case 0x06: case 0x07:
1728          return 1;
1729
1730       /* d8(%eax) ... d8(%edi), not including d8(%esp). */ 
1731       case 0x08: case 0x09: case 0x0A: case 0x0B: 
1732       /* ! 0C */ case 0x0D: case 0x0E: case 0x0F:
1733          return 2;
1734
1735       /* d32(%eax) ... d32(%edi), not including d32(%esp). */
1736       case 0x10: case 0x11: case 0x12: case 0x13: 
1737       /* ! 14 */ case 0x15: case 0x16: case 0x17:
1738          return 5;
1739
1740       /* a register, %eax .. %edi.  (Not an addr, but still handled.) */
1741       case 0x18: case 0x19: case 0x1A: case 0x1B:
1742       case 0x1C: case 0x1D: case 0x1E: case 0x1F:
1743          return 1;
1744
1745       /* a 32-bit literal address. */
1746       case 0x05: return 5;
1747
1748       /* SIB, no displacement.  */
1749       case 0x04: {
1750          UChar sib    = getIByte(delta);
1751          UChar base_r = toUChar(sib & 7);
1752          if (base_r == R_EBP) return 6; else return 2;
1753       }
1754       /* SIB, with 8-bit displacement.  */
1755       case 0x0C: return 3;
1756
1757       /* SIB, with 32-bit displacement.  */
1758       case 0x14: return 6;
1759
1760       default:
1761          vpanic("lengthAMode");
1762          return 0; /*notreached*/
1763    }
1764 }
1765
1766 /*------------------------------------------------------------*/
1767 /*--- Disassembling common idioms                          ---*/
1768 /*------------------------------------------------------------*/
1769
1770 /* Handle binary integer instructions of the form
1771       op E, G  meaning
1772       op reg-or-mem, reg
1773    Is passed the a ptr to the modRM byte, the actual operation, and the
1774    data size.  Returns the address advanced completely over this
1775    instruction.
1776
1777    E(src) is reg-or-mem
1778    G(dst) is reg.
1779
1780    If E is reg, -->    GET %G,  tmp
1781                        OP %E,   tmp
1782                        PUT tmp, %G
1783  
1784    If E is mem and OP is not reversible, 
1785                 -->    (getAddr E) -> tmpa
1786                        LD (tmpa), tmpa
1787                        GET %G, tmp2
1788                        OP tmpa, tmp2
1789                        PUT tmp2, %G
1790
1791    If E is mem and OP is reversible
1792                 -->    (getAddr E) -> tmpa
1793                        LD (tmpa), tmpa
1794                        OP %G, tmpa
1795                        PUT tmpa, %G
1796 */
1797 static
1798 UInt dis_op2_E_G ( UChar       sorb,
1799                    Bool        addSubCarry,
1800                    IROp        op8, 
1801                    Bool        keep,
1802                    Int         size, 
1803                    Int         delta0,
1804                    HChar*      t_x86opc )
1805 {
1806    HChar   dis_buf[50];
1807    Int     len;
1808    IRType  ty   = szToITy(size);
1809    IRTemp  dst1 = newTemp(ty);
1810    IRTemp  src  = newTemp(ty);
1811    IRTemp  dst0 = newTemp(ty);
1812    UChar   rm   = getUChar(delta0);
1813    IRTemp  addr = IRTemp_INVALID;
1814
1815    /* addSubCarry == True indicates the intended operation is
1816       add-with-carry or subtract-with-borrow. */
1817    if (addSubCarry) {
1818       vassert(op8 == Iop_Add8 || op8 == Iop_Sub8);
1819       vassert(keep);
1820    }
1821
1822    if (epartIsReg(rm)) {
1823       /* Specially handle XOR reg,reg, because that doesn't really
1824          depend on reg, and doing the obvious thing potentially
1825          generates a spurious value check failure due to the bogus
1826          dependency.  Ditto SBB reg,reg. */
1827       if ((op8 == Iop_Xor8 || (op8 == Iop_Sub8 && addSubCarry))
1828           && gregOfRM(rm) == eregOfRM(rm)) {
1829          putIReg(size, gregOfRM(rm), mkU(ty,0));
1830       }
1831       assign( dst0, getIReg(size,gregOfRM(rm)) );
1832       assign( src,  getIReg(size,eregOfRM(rm)) );
1833
1834       if (addSubCarry && op8 == Iop_Add8) {
1835          helper_ADC( size, dst1, dst0, src,
1836                      /*no store*/IRTemp_INVALID, IRTemp_INVALID, 0 );
1837          putIReg(size, gregOfRM(rm), mkexpr(dst1));
1838       } else
1839       if (addSubCarry && op8 == Iop_Sub8) {
1840          helper_SBB( size, dst1, dst0, src,
1841                      /*no store*/IRTemp_INVALID, IRTemp_INVALID, 0 );
1842          putIReg(size, gregOfRM(rm), mkexpr(dst1));
1843       } else {
1844          assign( dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)) );
1845          if (isAddSub(op8))
1846             setFlags_DEP1_DEP2(op8, dst0, src, ty);
1847          else
1848             setFlags_DEP1(op8, dst1, ty);
1849          if (keep)
1850             putIReg(size, gregOfRM(rm), mkexpr(dst1));
1851       }
1852
1853       DIP("%s%c %s,%s\n", t_x86opc, nameISize(size), 
1854                           nameIReg(size,eregOfRM(rm)),
1855                           nameIReg(size,gregOfRM(rm)));
1856       return 1+delta0;
1857    } else {
1858       /* E refers to memory */
1859       addr = disAMode ( &len, sorb, delta0, dis_buf);
1860       assign( dst0, getIReg(size,gregOfRM(rm)) );
1861       assign( src,  loadLE(szToITy(size), mkexpr(addr)) );
1862
1863       if (addSubCarry && op8 == Iop_Add8) {
1864          helper_ADC( size, dst1, dst0, src,
1865                      /*no store*/IRTemp_INVALID, IRTemp_INVALID, 0 );
1866          putIReg(size, gregOfRM(rm), mkexpr(dst1));
1867       } else
1868       if (addSubCarry && op8 == Iop_Sub8) {
1869          helper_SBB( size, dst1, dst0, src,
1870                      /*no store*/IRTemp_INVALID, IRTemp_INVALID, 0 );
1871          putIReg(size, gregOfRM(rm), mkexpr(dst1));
1872       } else {
1873          assign( dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)) );
1874          if (isAddSub(op8))
1875             setFlags_DEP1_DEP2(op8, dst0, src, ty);
1876          else
1877             setFlags_DEP1(op8, dst1, ty);
1878          if (keep)
1879             putIReg(size, gregOfRM(rm), mkexpr(dst1));
1880       }
1881
1882       DIP("%s%c %s,%s\n", t_x86opc, nameISize(size), 
1883                           dis_buf,nameIReg(size,gregOfRM(rm)));
1884       return len+delta0;
1885    }
1886 }
1887
1888
1889
1890 /* Handle binary integer instructions of the form
1891       op G, E  meaning
1892       op reg, reg-or-mem
1893    Is passed the a ptr to the modRM byte, the actual operation, and the
1894    data size.  Returns the address advanced completely over this
1895    instruction.
1896
1897    G(src) is reg.
1898    E(dst) is reg-or-mem
1899
1900    If E is reg, -->    GET %E,  tmp
1901                        OP %G,   tmp
1902                        PUT tmp, %E
1903  
1904    If E is mem, -->    (getAddr E) -> tmpa
1905                        LD (tmpa), tmpv
1906                        OP %G, tmpv
1907                        ST tmpv, (tmpa)
1908 */
1909 static
1910 UInt dis_op2_G_E ( UChar       sorb,
1911                    Bool        locked,
1912                    Bool        addSubCarry,
1913                    IROp        op8, 
1914                    Bool        keep,
1915                    Int         size, 
1916                    Int         delta0,
1917                    HChar*      t_x86opc )
1918 {
1919    HChar   dis_buf[50];
1920    Int     len;
1921    IRType  ty   = szToITy(size);
1922    IRTemp  dst1 = newTemp(ty);
1923    IRTemp  src  = newTemp(ty);
1924    IRTemp  dst0 = newTemp(ty);
1925    UChar   rm   = getIByte(delta0);
1926    IRTemp  addr = IRTemp_INVALID;
1927
1928    /* addSubCarry == True indicates the intended operation is
1929       add-with-carry or subtract-with-borrow. */
1930    if (addSubCarry) {
1931       vassert(op8 == Iop_Add8 || op8 == Iop_Sub8);
1932       vassert(keep);
1933    }
1934
1935    if (epartIsReg(rm)) {
1936       /* Specially handle XOR reg,reg, because that doesn't really
1937          depend on reg, and doing the obvious thing potentially
1938          generates a spurious value check failure due to the bogus
1939          dependency.  Ditto SBB reg,reg.*/
1940       if ((op8 == Iop_Xor8 || (op8 == Iop_Sub8 && addSubCarry))
1941           && gregOfRM(rm) == eregOfRM(rm)) {
1942          putIReg(size, eregOfRM(rm), mkU(ty,0));
1943       }
1944       assign(dst0, getIReg(size,eregOfRM(rm)));
1945       assign(src,  getIReg(size,gregOfRM(rm)));
1946
1947       if (addSubCarry && op8 == Iop_Add8) {
1948          helper_ADC( size, dst1, dst0, src,
1949                      /*no store*/IRTemp_INVALID, IRTemp_INVALID, 0 );
1950          putIReg(size, eregOfRM(rm), mkexpr(dst1));
1951       } else
1952       if (addSubCarry && op8 == Iop_Sub8) {
1953          helper_SBB( size, dst1, dst0, src,
1954                      /*no store*/IRTemp_INVALID, IRTemp_INVALID, 0 );
1955          putIReg(size, eregOfRM(rm), mkexpr(dst1));
1956       } else {
1957          assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)));
1958          if (isAddSub(op8))
1959             setFlags_DEP1_DEP2(op8, dst0, src, ty);
1960          else
1961             setFlags_DEP1(op8, dst1, ty);
1962          if (keep)
1963             putIReg(size, eregOfRM(rm), mkexpr(dst1));
1964       }
1965
1966       DIP("%s%c %s,%s\n", t_x86opc, nameISize(size), 
1967                           nameIReg(size,gregOfRM(rm)),
1968                           nameIReg(size,eregOfRM(rm)));
1969       return 1+delta0;
1970    }
1971
1972    /* E refers to memory */    
1973    {
1974       addr = disAMode ( &len, sorb, delta0, dis_buf);
1975       assign(dst0, loadLE(ty,mkexpr(addr)));
1976       assign(src,  getIReg(size,gregOfRM(rm)));
1977
1978       if (addSubCarry && op8 == Iop_Add8) {
1979          if (locked) {
1980             /* cas-style store */
1981             helper_ADC( size, dst1, dst0, src,
1982                         /*store*/addr, dst0/*expVal*/, guest_EIP_curr_instr );
1983          } else {
1984             /* normal store */
1985             helper_ADC( size, dst1, dst0, src,
1986                         /*store*/addr, IRTemp_INVALID, 0 );
1987          }
1988       } else
1989       if (addSubCarry && op8 == Iop_Sub8) {
1990          if (locked) {
1991             /* cas-style store */
1992             helper_SBB( size, dst1, dst0, src,
1993                         /*store*/addr, dst0/*expVal*/, guest_EIP_curr_instr );
1994          } else {
1995             /* normal store */
1996             helper_SBB( size, dst1, dst0, src,
1997                         /*store*/addr, IRTemp_INVALID, 0 );
1998          }
1999       } else {
2000          assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)));
2001          if (keep) {
2002             if (locked) {
2003                if (0) vex_printf("locked case\n" );
2004                casLE( mkexpr(addr),
2005                       mkexpr(dst0)/*expval*/, 
2006                       mkexpr(dst1)/*newval*/, guest_EIP_curr_instr );
2007             } else {
2008                if (0) vex_printf("nonlocked case\n");
2009                storeLE(mkexpr(addr), mkexpr(dst1));
2010             }
2011          }
2012          if (isAddSub(op8))
2013             setFlags_DEP1_DEP2(op8, dst0, src, ty);
2014          else
2015             setFlags_DEP1(op8, dst1, ty);
2016       }
2017
2018       DIP("%s%c %s,%s\n", t_x86opc, nameISize(size), 
2019                           nameIReg(size,gregOfRM(rm)), dis_buf);
2020       return len+delta0;
2021    }
2022 }
2023
2024
2025 /* Handle move instructions of the form
2026       mov E, G  meaning
2027       mov reg-or-mem, reg
2028    Is passed the a ptr to the modRM byte, and the data size.  Returns
2029    the address advanced completely over this instruction.
2030
2031    E(src) is reg-or-mem
2032    G(dst) is reg.
2033
2034    If E is reg, -->    GET %E,  tmpv
2035                        PUT tmpv, %G
2036  
2037    If E is mem  -->    (getAddr E) -> tmpa
2038                        LD (tmpa), tmpb
2039                        PUT tmpb, %G
2040 */
2041 static
2042 UInt dis_mov_E_G ( UChar       sorb,
2043                    Int         size, 
2044                    Int         delta0 )
2045 {
2046    Int len;
2047    UChar rm = getIByte(delta0);
2048    HChar dis_buf[50];
2049
2050    if (epartIsReg(rm)) {
2051       putIReg(size, gregOfRM(rm), getIReg(size, eregOfRM(rm)));
2052       DIP("mov%c %s,%s\n", nameISize(size), 
2053                            nameIReg(size,eregOfRM(rm)),
2054                            nameIReg(size,gregOfRM(rm)));
2055       return 1+delta0;
2056    }
2057
2058    /* E refers to memory */    
2059    {
2060       IRTemp addr = disAMode ( &len, sorb, delta0, dis_buf );
2061       putIReg(size, gregOfRM(rm), loadLE(szToITy(size), mkexpr(addr)));
2062       DIP("mov%c %s,%s\n", nameISize(size), 
2063                            dis_buf,nameIReg(size,gregOfRM(rm)));
2064       return delta0+len;
2065    }
2066 }
2067
2068
2069 /* Handle move instructions of the form
2070       mov G, E  meaning
2071       mov reg, reg-or-mem
2072    Is passed the a ptr to the modRM byte, and the data size.  Returns
2073    the address advanced completely over this instruction.
2074
2075    G(src) is reg.
2076    E(dst) is reg-or-mem
2077
2078    If E is reg, -->    GET %G,  tmp
2079                        PUT tmp, %E
2080  
2081    If E is mem, -->    (getAddr E) -> tmpa
2082                        GET %G, tmpv
2083                        ST tmpv, (tmpa) 
2084 */
2085 static
2086 UInt dis_mov_G_E ( UChar       sorb,
2087                    Int         size, 
2088                    Int         delta0 )
2089 {
2090    Int len;
2091    UChar rm = getIByte(delta0);
2092    HChar dis_buf[50];
2093
2094    if (epartIsReg(rm)) {
2095       putIReg(size, eregOfRM(rm), getIReg(size, gregOfRM(rm)));
2096       DIP("mov%c %s,%s\n", nameISize(size), 
2097                            nameIReg(size,gregOfRM(rm)),
2098                            nameIReg(size,eregOfRM(rm)));
2099       return 1+delta0;
2100    }
2101
2102    /* E refers to memory */    
2103    {
2104       IRTemp addr = disAMode ( &len, sorb, delta0, dis_buf);
2105       storeLE( mkexpr(addr), getIReg(size, gregOfRM(rm)) );
2106       DIP("mov%c %s,%s\n", nameISize(size), 
2107                            nameIReg(size,gregOfRM(rm)), dis_buf);
2108       return len+delta0;
2109    }
2110 }
2111
2112
2113 /* op $immediate, AL/AX/EAX. */
2114 static
2115 UInt dis_op_imm_A ( Int    size,
2116                     Bool   carrying,
2117                     IROp   op8,
2118                     Bool   keep,
2119                     Int    delta,
2120                     HChar* t_x86opc )
2121 {
2122    IRType ty   = szToITy(size);
2123    IRTemp dst0 = newTemp(ty);
2124    IRTemp src  = newTemp(ty);
2125    IRTemp dst1 = newTemp(ty);
2126    UInt lit    = getUDisp(size,delta);
2127    assign(dst0, getIReg(size,R_EAX));
2128    assign(src,  mkU(ty,lit));
2129
2130    if (isAddSub(op8) && !carrying) {
2131       assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)) );
2132       setFlags_DEP1_DEP2(op8, dst0, src, ty);
2133    } 
2134    else
2135    if (isLogic(op8)) {
2136       vassert(!carrying);
2137       assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)) );
2138       setFlags_DEP1(op8, dst1, ty);
2139    } 
2140    else
2141    if (op8 == Iop_Add8 && carrying) {
2142       helper_ADC( size, dst1, dst0, src,
2143                   /*no store*/IRTemp_INVALID, IRTemp_INVALID, 0 );
2144    }
2145    else
2146    if (op8 == Iop_Sub8 && carrying) {
2147       helper_SBB( size, dst1, dst0, src,
2148                   /*no store*/IRTemp_INVALID, IRTemp_INVALID, 0 );
2149    }
2150    else
2151       vpanic("dis_op_imm_A(x86,guest)");
2152
2153    if (keep)
2154       putIReg(size, R_EAX, mkexpr(dst1));
2155
2156    DIP("%s%c $0x%x, %s\n", t_x86opc, nameISize(size), 
2157                            lit, nameIReg(size,R_EAX));
2158    return delta+size;
2159 }
2160
2161
2162 /* Sign- and Zero-extending moves. */
2163 static
2164 UInt dis_movx_E_G ( UChar      sorb,
2165                     Int delta, Int szs, Int szd, Bool sign_extend )
2166 {
2167    UChar rm = getIByte(delta);
2168    if (epartIsReg(rm)) {
2169       putIReg(szd, gregOfRM(rm),
2170                    unop(mkWidenOp(szs,szd,sign_extend), 
2171                         getIReg(szs,eregOfRM(rm))));
2172       DIP("mov%c%c%c %s,%s\n", sign_extend ? 's' : 'z',
2173                                nameISize(szs), nameISize(szd),
2174                                nameIReg(szs,eregOfRM(rm)),
2175                                nameIReg(szd,gregOfRM(rm)));
2176       return 1+delta;
2177    }
2178
2179    /* E refers to memory */    
2180    {
2181       Int    len;
2182       HChar  dis_buf[50];
2183       IRTemp addr = disAMode ( &len, sorb, delta, dis_buf );
2184
2185       putIReg(szd, gregOfRM(rm),
2186                    unop(mkWidenOp(szs,szd,sign_extend), 
2187                         loadLE(szToITy(szs),mkexpr(addr))));
2188       DIP("mov%c%c%c %s,%s\n", sign_extend ? 's' : 'z',
2189                                nameISize(szs), nameISize(szd),
2190                                dis_buf, nameIReg(szd,gregOfRM(rm)));
2191       return len+delta;
2192    }
2193 }
2194
2195
2196 /* Generate code to divide ArchRegs EDX:EAX / DX:AX / AX by the 32 /
2197    16 / 8 bit quantity in the given IRTemp.  */
2198 static
2199 void codegen_div ( Int sz, IRTemp t, Bool signed_divide )
2200 {
2201    IROp   op    = signed_divide ? Iop_DivModS64to32 : Iop_DivModU64to32;
2202    IRTemp src64 = newTemp(Ity_I64);
2203    IRTemp dst64 = newTemp(Ity_I64);
2204    switch (sz) {
2205       case 4:
2206          assign( src64, binop(Iop_32HLto64, 
2207                               getIReg(4,R_EDX), getIReg(4,R_EAX)) );
2208          assign( dst64, binop(op, mkexpr(src64), mkexpr(t)) );
2209          putIReg( 4, R_EAX, unop(Iop_64to32,mkexpr(dst64)) );
2210          putIReg( 4, R_EDX, unop(Iop_64HIto32,mkexpr(dst64)) );
2211          break;
2212       case 2: {
2213          IROp widen3264 = signed_divide ? Iop_32Sto64 : Iop_32Uto64;
2214          IROp widen1632 = signed_divide ? Iop_16Sto32 : Iop_16Uto32;
2215          assign( src64, unop(widen3264,
2216                              binop(Iop_16HLto32, 
2217                                    getIReg(2,R_EDX), getIReg(2,R_EAX))) );
2218          assign( dst64, binop(op, mkexpr(src64), unop(widen1632,mkexpr(t))) );
2219          putIReg( 2, R_EAX, unop(Iop_32to16,unop(Iop_64to32,mkexpr(dst64))) );
2220          putIReg( 2, R_EDX, unop(Iop_32to16,unop(Iop_64HIto32,mkexpr(dst64))) );
2221          break;
2222       }
2223       case 1: {
2224          IROp widen3264 = signed_divide ? Iop_32Sto64 : Iop_32Uto64;
2225          IROp widen1632 = signed_divide ? Iop_16Sto32 : Iop_16Uto32;
2226          IROp widen816  = signed_divide ? Iop_8Sto16  : Iop_8Uto16;
2227          assign( src64, unop(widen3264, unop(widen1632, getIReg(2,R_EAX))) );
2228          assign( dst64, 
2229                  binop(op, mkexpr(src64), 
2230                            unop(widen1632, unop(widen816, mkexpr(t)))) );
2231          putIReg( 1, R_AL, unop(Iop_16to8, unop(Iop_32to16,
2232                            unop(Iop_64to32,mkexpr(dst64)))) );
2233          putIReg( 1, R_AH, unop(Iop_16to8, unop(Iop_32to16,
2234                            unop(Iop_64HIto32,mkexpr(dst64)))) );
2235          break;
2236       }
2237       default: vpanic("codegen_div(x86)");
2238    }
2239 }
2240
2241
2242 static 
2243 UInt dis_Grp1 ( UChar sorb, Bool locked,
2244                 Int delta, UChar modrm, 
2245                 Int am_sz, Int d_sz, Int sz, UInt d32 )
2246 {
2247    Int     len;
2248    HChar   dis_buf[50];
2249    IRType  ty   = szToITy(sz);
2250    IRTemp  dst1 = newTemp(ty);
2251    IRTemp  src  = newTemp(ty);
2252    IRTemp  dst0 = newTemp(ty);
2253    IRTemp  addr = IRTemp_INVALID;
2254    IROp    op8  = Iop_INVALID;
2255    UInt    mask = sz==1 ? 0xFF : (sz==2 ? 0xFFFF : 0xFFFFFFFF);
2256
2257    switch (gregOfRM(modrm)) {
2258       case 0: op8 = Iop_Add8; break;  case 1: op8 = Iop_Or8;  break;
2259       case 2: break;  // ADC
2260       case 3: break;  // SBB
2261       case 4: op8 = Iop_And8; break;  case 5: op8 = Iop_Sub8; break;
2262       case 6: op8 = Iop_Xor8; break;  case 7: op8 = Iop_Sub8; break;
2263       /*NOTREACHED*/
2264       default: vpanic("dis_Grp1: unhandled case");
2265    }
2266
2267    if (epartIsReg(modrm)) {
2268       vassert(am_sz == 1);
2269
2270       assign(dst0, getIReg(sz,eregOfRM(modrm)));
2271       assign(src,  mkU(ty,d32 & mask));
2272
2273       if (gregOfRM(modrm) == 2 /* ADC */) {
2274          helper_ADC( sz, dst1, dst0, src,
2275                      /*no store*/IRTemp_INVALID, IRTemp_INVALID, 0 );
2276       } else 
2277       if (gregOfRM(modrm) == 3 /* SBB */) {
2278          helper_SBB( sz, dst1, dst0, src,
2279                      /*no store*/IRTemp_INVALID, IRTemp_INVALID, 0 );
2280       } else {
2281          assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)));
2282          if (isAddSub(op8))
2283             setFlags_DEP1_DEP2(op8, dst0, src, ty);
2284          else
2285             setFlags_DEP1(op8, dst1, ty);
2286       }
2287
2288       if (gregOfRM(modrm) < 7)
2289          putIReg(sz, eregOfRM(modrm), mkexpr(dst1));
2290
2291       delta += (am_sz + d_sz);
2292       DIP("%s%c $0x%x, %s\n", nameGrp1(gregOfRM(modrm)), nameISize(sz), d32, 
2293                               nameIReg(sz,eregOfRM(modrm)));
2294    } else {
2295       addr = disAMode ( &len, sorb, delta, dis_buf);
2296
2297       assign(dst0, loadLE(ty,mkexpr(addr)));
2298       assign(src, mkU(ty,d32 & mask));
2299
2300       if (gregOfRM(modrm) == 2 /* ADC */) {
2301          if (locked) {
2302             /* cas-style store */
2303             helper_ADC( sz, dst1, dst0, src,
2304                        /*store*/addr, dst0/*expVal*/, guest_EIP_curr_instr );
2305          } else {
2306             /* normal store */
2307             helper_ADC( sz, dst1, dst0, src,
2308                         /*store*/addr, IRTemp_INVALID, 0 );
2309          }
2310       } else 
2311       if (gregOfRM(modrm) == 3 /* SBB */) {
2312          if (locked) {
2313             /* cas-style store */
2314             helper_SBB( sz, dst1, dst0, src,
2315                        /*store*/addr, dst0/*expVal*/, guest_EIP_curr_instr );
2316          } else {
2317             /* normal store */
2318             helper_SBB( sz, dst1, dst0, src,
2319                         /*store*/addr, IRTemp_INVALID, 0 );
2320          }
2321       } else {
2322          assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)));
2323          if (gregOfRM(modrm) < 7) {
2324             if (locked) {
2325                casLE( mkexpr(addr), mkexpr(dst0)/*expVal*/, 
2326                                     mkexpr(dst1)/*newVal*/,
2327                                     guest_EIP_curr_instr );
2328             } else {
2329                storeLE(mkexpr(addr), mkexpr(dst1));
2330             }
2331          }
2332          if (isAddSub(op8))
2333             setFlags_DEP1_DEP2(op8, dst0, src, ty);
2334          else
2335             setFlags_DEP1(op8, dst1, ty);
2336       }
2337
2338       delta += (len+d_sz);
2339       DIP("%s%c $0x%x, %s\n", nameGrp1(gregOfRM(modrm)), nameISize(sz),
2340                               d32, dis_buf);
2341    }
2342    return delta;
2343 }
2344
2345
2346 /* Group 2 extended opcodes.  shift_expr must be an 8-bit typed
2347    expression. */
2348
2349 static
2350 UInt dis_Grp2 ( UChar sorb,
2351                 Int delta, UChar modrm,
2352                 Int am_sz, Int d_sz, Int sz, IRExpr* shift_expr,
2353                 HChar* shift_expr_txt, Bool* decode_OK )
2354 {
2355    /* delta on entry points at the modrm byte. */
2356    HChar  dis_buf[50];
2357    Int    len;
2358    Bool   isShift, isRotate, isRotateC;
2359    IRType ty    = szToITy(sz);
2360    IRTemp dst0  = newTemp(ty);
2361    IRTemp dst1  = newTemp(ty);
2362    IRTemp addr  = IRTemp_INVALID;
2363
2364    *decode_OK = True;
2365
2366    vassert(sz == 1 || sz == 2 || sz == 4);
2367
2368    /* Put value to shift/rotate in dst0. */
2369    if (epartIsReg(modrm)) {
2370       assign(dst0, getIReg(sz, eregOfRM(modrm)));
2371       delta += (am_sz + d_sz);
2372    } else {
2373       addr = disAMode ( &len, sorb, delta, dis_buf);
2374       assign(dst0, loadLE(ty,mkexpr(addr)));
2375       delta += len + d_sz;
2376    }
2377
2378    isShift = False;
2379    switch (gregOfRM(modrm)) { case 4: case 5: case 7: isShift = True; }
2380
2381    isRotate = False;
2382    switch (gregOfRM(modrm)) { case 0: case 1: isRotate = True; }
2383
2384    isRotateC = False;
2385    switch (gregOfRM(modrm)) { case 2: case 3: isRotateC = True; }
2386
2387    if (gregOfRM(modrm) == 6) {
2388       *decode_OK = False;
2389       return delta;
2390    }
2391
2392    if (!isShift && !isRotate && !isRotateC) {
2393       /*NOTREACHED*/
2394       vpanic("dis_Grp2(Reg): unhandled case(x86)");
2395    }
2396
2397    if (isRotateC) {
2398       /* call a helper; these insns are so ridiculous they do not
2399          deserve better */
2400       Bool     left = toBool(gregOfRM(modrm) == 2);
2401       IRTemp   r64  = newTemp(Ity_I64);
2402       IRExpr** args 
2403          = mkIRExprVec_4( widenUto32(mkexpr(dst0)), /* thing to rotate */
2404                           widenUto32(shift_expr),   /* rotate amount */
2405                           widenUto32(mk_x86g_calculate_eflags_all()),
2406                           mkU32(sz) );
2407       assign( r64, mkIRExprCCall(
2408                       Ity_I64, 
2409                       0/*regparm*/, 
2410                       left ? "x86g_calculate_RCL" : "x86g_calculate_RCR", 
2411                       left ? &x86g_calculate_RCL  : &x86g_calculate_RCR,
2412                       args
2413                    )
2414             );
2415       /* new eflags in hi half r64; new value in lo half r64 */
2416       assign( dst1, narrowTo(ty, unop(Iop_64to32, mkexpr(r64))) );
2417       stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(X86G_CC_OP_COPY) ));
2418       stmt( IRStmt_Put( OFFB_CC_DEP1, unop(Iop_64HIto32, mkexpr(r64)) ));
2419       stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0) ));
2420       /* Set NDEP even though it isn't used.  This makes redundant-PUT
2421          elimination of previous stores to this field work better. */
2422       stmt( IRStmt_Put( OFFB_CC_NDEP, mkU32(0) ));
2423    }
2424
2425    if (isShift) {
2426
2427       IRTemp pre32     = newTemp(Ity_I32);
2428       IRTemp res32     = newTemp(Ity_I32);
2429       IRTemp res32ss   = newTemp(Ity_I32);
2430       IRTemp shift_amt = newTemp(Ity_I8);
2431       IROp   op32;
2432
2433       switch (gregOfRM(modrm)) { 
2434          case 4: op32 = Iop_Shl32; break;
2435          case 5: op32 = Iop_Shr32; break;
2436          case 7: op32 = Iop_Sar32; break;
2437          /*NOTREACHED*/
2438          default: vpanic("dis_Grp2:shift"); break;
2439       }
2440
2441       /* Widen the value to be shifted to 32 bits, do the shift, and
2442          narrow back down.  This seems surprisingly long-winded, but
2443          unfortunately the Intel semantics requires that 8/16-bit
2444          shifts give defined results for shift values all the way up
2445          to 31, and this seems the simplest way to do it.  It has the
2446          advantage that the only IR level shifts generated are of 32
2447          bit values, and the shift amount is guaranteed to be in the
2448          range 0 .. 31, thereby observing the IR semantics requiring
2449          all shift values to be in the range 0 .. 2^word_size-1. */
2450
2451       /* shift_amt = shift_expr & 31, regardless of operation size */
2452       assign( shift_amt, binop(Iop_And8, shift_expr, mkU8(31)) );
2453
2454       /* suitably widen the value to be shifted to 32 bits. */
2455       assign( pre32, op32==Iop_Sar32 ? widenSto32(mkexpr(dst0))
2456                                      : widenUto32(mkexpr(dst0)) );
2457
2458       /* res32 = pre32 `shift` shift_amt */
2459       assign( res32, binop(op32, mkexpr(pre32), mkexpr(shift_amt)) );
2460
2461       /* res32ss = pre32 `shift` ((shift_amt - 1) & 31) */
2462       assign( res32ss,
2463               binop(op32,
2464                     mkexpr(pre32), 
2465                     binop(Iop_And8,
2466                           binop(Iop_Sub8,
2467                                 mkexpr(shift_amt), mkU8(1)),
2468                           mkU8(31))) );
2469
2470       /* Build the flags thunk. */
2471       setFlags_DEP1_DEP2_shift(op32, res32, res32ss, ty, shift_amt);
2472
2473       /* Narrow the result back down. */
2474       assign( dst1, narrowTo(ty, mkexpr(res32)) );
2475
2476    } /* if (isShift) */
2477
2478    else 
2479    if (isRotate) {
2480       Int    ccOp      = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : 2);
2481       Bool   left      = toBool(gregOfRM(modrm) == 0);
2482       IRTemp rot_amt   = newTemp(Ity_I8);
2483       IRTemp rot_amt32 = newTemp(Ity_I8);
2484       IRTemp oldFlags  = newTemp(Ity_I32);
2485
2486       /* rot_amt = shift_expr & mask */
2487       /* By masking the rotate amount thusly, the IR-level Shl/Shr
2488          expressions never shift beyond the word size and thus remain
2489          well defined. */
2490       assign(rot_amt32, binop(Iop_And8, shift_expr, mkU8(31)));
2491
2492       if (ty == Ity_I32)
2493          assign(rot_amt, mkexpr(rot_amt32));
2494       else
2495          assign(rot_amt, binop(Iop_And8, mkexpr(rot_amt32), mkU8(8*sz-1)));
2496
2497       if (left) {
2498
2499          /* dst1 = (dst0 << rot_amt) | (dst0 >>u (wordsize-rot_amt)) */
2500          assign(dst1, 
2501             binop( mkSizedOp(ty,Iop_Or8),
2502                    binop( mkSizedOp(ty,Iop_Shl8), 
2503                           mkexpr(dst0),
2504                           mkexpr(rot_amt)
2505                    ),
2506                    binop( mkSizedOp(ty,Iop_Shr8), 
2507                           mkexpr(dst0), 
2508                           binop(Iop_Sub8,mkU8(8*sz), mkexpr(rot_amt))
2509                    )
2510             )
2511          );
2512          ccOp += X86G_CC_OP_ROLB;
2513
2514       } else { /* right */
2515
2516          /* dst1 = (dst0 >>u rot_amt) | (dst0 << (wordsize-rot_amt)) */
2517          assign(dst1, 
2518             binop( mkSizedOp(ty,Iop_Or8),
2519                    binop( mkSizedOp(ty,Iop_Shr8), 
2520                           mkexpr(dst0),
2521                           mkexpr(rot_amt)
2522                    ),
2523                    binop( mkSizedOp(ty,Iop_Shl8), 
2524                           mkexpr(dst0), 
2525                           binop(Iop_Sub8,mkU8(8*sz), mkexpr(rot_amt))
2526                    )
2527             )
2528          );
2529          ccOp += X86G_CC_OP_RORB;
2530
2531       }
2532
2533       /* dst1 now holds the rotated value.  Build flag thunk.  We
2534          need the resulting value for this, and the previous flags.
2535          Except don't set it if the rotate count is zero. */
2536
2537       assign(oldFlags, mk_x86g_calculate_eflags_all());
2538
2539       /* CC_DEP1 is the rotated value.  CC_NDEP is flags before. */
2540       stmt( IRStmt_Put( OFFB_CC_OP,
2541                         IRExpr_Mux0X( mkexpr(rot_amt32),
2542                                       IRExpr_Get(OFFB_CC_OP,Ity_I32),
2543                                       mkU32(ccOp))) );
2544       stmt( IRStmt_Put( OFFB_CC_DEP1, 
2545                         IRExpr_Mux0X( mkexpr(rot_amt32),
2546                                       IRExpr_Get(OFFB_CC_DEP1,Ity_I32),
2547                                       widenUto32(mkexpr(dst1)))) );
2548       stmt( IRStmt_Put( OFFB_CC_DEP2, 
2549                         IRExpr_Mux0X( mkexpr(rot_amt32),
2550                                       IRExpr_Get(OFFB_CC_DEP2,Ity_I32),
2551                                       mkU32(0))) );
2552       stmt( IRStmt_Put( OFFB_CC_NDEP, 
2553                         IRExpr_Mux0X( mkexpr(rot_amt32),
2554                                       IRExpr_Get(OFFB_CC_NDEP,Ity_I32),
2555                                       mkexpr(oldFlags))) );
2556    } /* if (isRotate) */
2557
2558    /* Save result, and finish up. */
2559    if (epartIsReg(modrm)) {
2560       putIReg(sz, eregOfRM(modrm), mkexpr(dst1));
2561       if (vex_traceflags & VEX_TRACE_FE) {
2562          vex_printf("%s%c ",
2563                     nameGrp2(gregOfRM(modrm)), nameISize(sz) );
2564          if (shift_expr_txt)
2565             vex_printf("%s", shift_expr_txt);
2566          else
2567             ppIRExpr(shift_expr);
2568          vex_printf(", %s\n", nameIReg(sz,eregOfRM(modrm)));
2569       }
2570    } else {
2571       storeLE(mkexpr(addr), mkexpr(dst1));
2572       if (vex_traceflags & VEX_TRACE_FE) {
2573          vex_printf("%s%c ",
2574                     nameGrp2(gregOfRM(modrm)), nameISize(sz) );
2575          if (shift_expr_txt)
2576             vex_printf("%s", shift_expr_txt);
2577          else
2578             ppIRExpr(shift_expr);
2579          vex_printf(", %s\n", dis_buf);
2580       }
2581    }
2582    return delta;
2583 }
2584
2585
2586 /* Group 8 extended opcodes (but BT/BTS/BTC/BTR only). */
2587 static
2588 UInt dis_Grp8_Imm ( UChar sorb,
2589                     Bool locked,
2590                     Int delta, UChar modrm,
2591                     Int am_sz, Int sz, UInt src_val,
2592                     Bool* decode_OK )
2593 {
2594    /* src_val denotes a d8.
2595       And delta on entry points at the modrm byte. */
2596
2597    IRType ty     = szToITy(sz);
2598    IRTemp t2     = newTemp(Ity_I32);
2599    IRTemp t2m    = newTemp(Ity_I32);
2600    IRTemp t_addr = IRTemp_INVALID;
2601    HChar  dis_buf[50];
2602    UInt   mask;
2603
2604    /* we're optimists :-) */
2605    *decode_OK = True;
2606
2607    /* Limit src_val -- the bit offset -- to something within a word.
2608       The Intel docs say that literal offsets larger than a word are
2609       masked in this way. */
2610    switch (sz) {
2611       case 2:  src_val &= 15; break;
2612       case 4:  src_val &= 31; break;
2613       default: *decode_OK = False; return delta;
2614    }
2615
2616    /* Invent a mask suitable for the operation. */
2617    switch (gregOfRM(modrm)) {
2618       case 4: /* BT */  mask = 0;               break;
2619       case 5: /* BTS */ mask = 1 << src_val;    break;
2620       case 6: /* BTR */ mask = ~(1 << src_val); break;
2621       case 7: /* BTC */ mask = 1 << src_val;    break;
2622          /* If this needs to be extended, probably simplest to make a
2623             new function to handle the other cases (0 .. 3).  The
2624             Intel docs do however not indicate any use for 0 .. 3, so
2625             we don't expect this to happen. */
2626       default: *decode_OK = False; return delta;
2627    }
2628
2629    /* Fetch the value to be tested and modified into t2, which is
2630       32-bits wide regardless of sz. */
2631    if (epartIsReg(modrm)) {
2632       vassert(am_sz == 1);
2633       assign( t2, widenUto32(getIReg(sz, eregOfRM(modrm))) );
2634       delta += (am_sz + 1);
2635       DIP("%s%c $0x%x, %s\n", nameGrp8(gregOfRM(modrm)), nameISize(sz),
2636                               src_val, nameIReg(sz,eregOfRM(modrm)));
2637    } else {
2638       Int len;
2639       t_addr = disAMode ( &len, sorb, delta, dis_buf);
2640       delta  += (len+1);
2641       assign( t2, widenUto32(loadLE(ty, mkexpr(t_addr))) );
2642       DIP("%s%c $0x%x, %s\n", nameGrp8(gregOfRM(modrm)), nameISize(sz),
2643                               src_val, dis_buf);
2644    }
2645
2646    /* Compute the new value into t2m, if non-BT. */
2647    switch (gregOfRM(modrm)) {
2648       case 4: /* BT */
2649          break;
2650       case 5: /* BTS */
2651          assign( t2m, binop(Iop_Or32, mkU32(mask), mkexpr(t2)) );
2652          break;
2653       case 6: /* BTR */
2654          assign( t2m, binop(Iop_And32, mkU32(mask), mkexpr(t2)) );
2655          break;
2656       case 7: /* BTC */
2657          assign( t2m, binop(Iop_Xor32, mkU32(mask), mkexpr(t2)) );
2658          break;
2659       default: 
2660          /*NOTREACHED*/ /*the previous switch guards this*/
2661          vassert(0);
2662    }
2663
2664    /* Write the result back, if non-BT.  If the CAS fails then we
2665       side-exit from the trace at this point, and so the flag state is
2666       not affected.  This is of course as required. */
2667    if (gregOfRM(modrm) != 4 /* BT */) {
2668       if (epartIsReg(modrm)) {
2669          putIReg(sz, eregOfRM(modrm), narrowTo(ty, mkexpr(t2m)));
2670       } else {
2671          if (locked) {
2672             casLE( mkexpr(t_addr),
2673                    narrowTo(ty, mkexpr(t2))/*expd*/,
2674                    narrowTo(ty, mkexpr(t2m))/*new*/,
2675                    guest_EIP_curr_instr );
2676          } else {
2677             storeLE(mkexpr(t_addr), narrowTo(ty, mkexpr(t2m)));
2678          }
2679       }
2680    }
2681
2682    /* Copy relevant bit from t2 into the carry flag. */
2683    /* Flags: C=selected bit, O,S,Z,A,P undefined, so are set to zero. */
2684    stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(X86G_CC_OP_COPY) ));
2685    stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0) ));
2686    stmt( IRStmt_Put( 
2687             OFFB_CC_DEP1,
2688             binop(Iop_And32,
2689                   binop(Iop_Shr32, mkexpr(t2), mkU8(src_val)),
2690                   mkU32(1))
2691        ));
2692    /* Set NDEP even though it isn't used.  This makes redundant-PUT
2693       elimination of previous stores to this field work better. */
2694    stmt( IRStmt_Put( OFFB_CC_NDEP, mkU32(0) ));
2695
2696    return delta;
2697 }
2698
2699
2700 /* Signed/unsigned widening multiply.  Generate IR to multiply the
2701    value in EAX/AX/AL by the given IRTemp, and park the result in
2702    EDX:EAX/DX:AX/AX.
2703 */
2704 static void codegen_mulL_A_D ( Int sz, Bool syned, 
2705                                IRTemp tmp, HChar* tmp_txt )
2706 {
2707    IRType ty = szToITy(sz);
2708    IRTemp t1 = newTemp(ty);
2709
2710    assign( t1, getIReg(sz, R_EAX) );
2711
2712    switch (ty) {
2713       case Ity_I32: {
2714          IRTemp res64   = newTemp(Ity_I64);
2715          IRTemp resHi   = newTemp(Ity_I32);
2716          IRTemp resLo   = newTemp(Ity_I32);
2717          IROp   mulOp   = syned ? Iop_MullS32 : Iop_MullU32;
2718          UInt   tBaseOp = syned ? X86G_CC_OP_SMULB : X86G_CC_OP_UMULB;
2719          setFlags_MUL ( Ity_I32, t1, tmp, tBaseOp );
2720          assign( res64, binop(mulOp, mkexpr(t1), mkexpr(tmp)) );
2721          assign( resHi, unop(Iop_64HIto32,mkexpr(res64)));
2722          assign( resLo, unop(Iop_64to32,mkexpr(res64)));
2723          putIReg(4, R_EDX, mkexpr(resHi));
2724          putIReg(4, R_EAX, mkexpr(resLo));
2725          break;
2726       }
2727       case Ity_I16: {
2728          IRTemp res32   = newTemp(Ity_I32);
2729          IRTemp resHi   = newTemp(Ity_I16);
2730          IRTemp resLo   = newTemp(Ity_I16);
2731          IROp   mulOp   = syned ? Iop_MullS16 : Iop_MullU16;
2732          UInt   tBaseOp = syned ? X86G_CC_OP_SMULB : X86G_CC_OP_UMULB;
2733          setFlags_MUL ( Ity_I16, t1, tmp, tBaseOp );
2734          assign( res32, binop(mulOp, mkexpr(t1), mkexpr(tmp)) );
2735          assign( resHi, unop(Iop_32HIto16,mkexpr(res32)));
2736          assign( resLo, unop(Iop_32to16,mkexpr(res32)));
2737          putIReg(2, R_EDX, mkexpr(resHi));
2738          putIReg(2, R_EAX, mkexpr(resLo));
2739          break;
2740       }
2741       case Ity_I8: {
2742          IRTemp res16   = newTemp(Ity_I16);
2743          IRTemp resHi   = newTemp(Ity_I8);
2744          IRTemp resLo   = newTemp(Ity_I8);
2745          IROp   mulOp   = syned ? Iop_MullS8 : Iop_MullU8;
2746          UInt   tBaseOp = syned ? X86G_CC_OP_SMULB : X86G_CC_OP_UMULB;
2747          setFlags_MUL ( Ity_I8, t1, tmp, tBaseOp );
2748          assign( res16, binop(mulOp, mkexpr(t1), mkexpr(tmp)) );
2749          assign( resHi, unop(Iop_16HIto8,mkexpr(res16)));
2750          assign( resLo, unop(Iop_16to8,mkexpr(res16)));
2751          putIReg(2, R_EAX, mkexpr(res16));
2752          break;
2753       }
2754       default:
2755          vpanic("codegen_mulL_A_D(x86)");
2756    }
2757    DIP("%s%c %s\n", syned ? "imul" : "mul", nameISize(sz), tmp_txt);
2758 }
2759
2760
2761 /* Group 3 extended opcodes. */
2762 static 
2763 UInt dis_Grp3 ( UChar sorb, Bool locked, Int sz, Int delta, Bool* decode_OK )
2764 {
2765    UInt    d32;
2766    UChar   modrm;
2767    HChar   dis_buf[50];
2768    Int     len;
2769    IRTemp  addr;
2770    IRType  ty = szToITy(sz);
2771    IRTemp  t1 = newTemp(ty);
2772    IRTemp dst1, src, dst0;
2773
2774    *decode_OK = True; /* may change this later */
2775
2776    modrm = getIByte(delta);
2777
2778    if (locked && (gregOfRM(modrm) != 2 && gregOfRM(modrm) != 3)) {
2779       /* LOCK prefix only allowed with not and neg subopcodes */
2780       *decode_OK = False;
2781       return delta;
2782    }
2783
2784    if (epartIsReg(modrm)) {
2785       switch (gregOfRM(modrm)) {
2786          case 0: { /* TEST */
2787             delta++; d32 = getUDisp(sz, delta); delta += sz;
2788             dst1 = newTemp(ty);
2789             assign(dst1, binop(mkSizedOp(ty,Iop_And8),
2790                                getIReg(sz,eregOfRM(modrm)),
2791                                mkU(ty,d32)));
2792             setFlags_DEP1( Iop_And8, dst1, ty );
2793             DIP("test%c $0x%x, %s\n", nameISize(sz), d32, 
2794                                       nameIReg(sz, eregOfRM(modrm)));
2795             break;
2796          }
2797          case 1: /* UNDEFINED */
2798            /* The Intel docs imply this insn is undefined and binutils
2799               agrees.  Unfortunately Core 2 will run it (with who
2800               knows what result?)  sandpile.org reckons it's an alias
2801               for case 0.  We play safe. */
2802            *decode_OK = False;
2803            break;
2804          case 2: /* NOT */
2805             delta++;
2806             putIReg(sz, eregOfRM(modrm),
2807                         unop(mkSizedOp(ty,Iop_Not8),
2808                              getIReg(sz, eregOfRM(modrm))));
2809             DIP("not%c %s\n", nameISize(sz), nameIReg(sz, eregOfRM(modrm)));
2810             break;
2811          case 3: /* NEG */
2812             delta++;
2813             dst0 = newTemp(ty);
2814             src  = newTemp(ty);
2815             dst1 = newTemp(ty);
2816             assign(dst0, mkU(ty,0));
2817             assign(src,  getIReg(sz,eregOfRM(modrm)));
2818             assign(dst1, binop(mkSizedOp(ty,Iop_Sub8), mkexpr(dst0), mkexpr(src)));
2819             setFlags_DEP1_DEP2(Iop_Sub8, dst0, src, ty);
2820             putIReg(sz, eregOfRM(modrm), mkexpr(dst1));
2821             DIP("neg%c %s\n", nameISize(sz), nameIReg(sz, eregOfRM(modrm)));
2822             break;
2823          case 4: /* MUL (unsigned widening) */
2824             delta++;
2825             src = newTemp(ty);
2826             assign(src, getIReg(sz,eregOfRM(modrm)));
2827             codegen_mulL_A_D ( sz, False, src, nameIReg(sz,eregOfRM(modrm)) );
2828             break;
2829          case 5: /* IMUL (signed widening) */
2830             delta++;
2831             src = newTemp(ty);
2832             assign(src, getIReg(sz,eregOfRM(modrm)));
2833             codegen_mulL_A_D ( sz, True, src, nameIReg(sz,eregOfRM(modrm)) );
2834             break;
2835          case 6: /* DIV */
2836             delta++;
2837             assign( t1, getIReg(sz, eregOfRM(modrm)) );
2838             codegen_div ( sz, t1, False );
2839             DIP("div%c %s\n", nameISize(sz), nameIReg(sz, eregOfRM(modrm)));
2840             break;
2841          case 7: /* IDIV */
2842             delta++;
2843             assign( t1, getIReg(sz, eregOfRM(modrm)) );
2844             codegen_div ( sz, t1, True );
2845             DIP("idiv%c %s\n", nameISize(sz), nameIReg(sz, eregOfRM(modrm)));
2846             break;
2847          default: 
2848             /* This can't happen - gregOfRM should return 0 .. 7 only */
2849             vpanic("Grp3(x86)");
2850       }
2851    } else {
2852       addr = disAMode ( &len, sorb, delta, dis_buf );
2853       t1   = newTemp(ty);
2854       delta += len;
2855       assign(t1, loadLE(ty,mkexpr(addr)));
2856       switch (gregOfRM(modrm)) {
2857          case 0: { /* TEST */
2858             d32 = getUDisp(sz, delta); delta += sz;
2859             dst1 = newTemp(ty);
2860             assign(dst1, binop(mkSizedOp(ty,Iop_And8),
2861                                mkexpr(t1), mkU(ty,d32)));
2862             setFlags_DEP1( Iop_And8, dst1, ty );
2863             DIP("test%c $0x%x, %s\n", nameISize(sz), d32, dis_buf);
2864             break;
2865          }
2866          case 1: /* UNDEFINED */
2867            /* See comment above on R case */
2868            *decode_OK = False;
2869            break;
2870          case 2: /* NOT */
2871             dst1 = newTemp(ty);
2872             assign(dst1, unop(mkSizedOp(ty,Iop_Not8), mkexpr(t1)));
2873             if (locked) {
2874                casLE( mkexpr(addr), mkexpr(t1)/*expd*/, mkexpr(dst1)/*new*/,
2875                                     guest_EIP_curr_instr );
2876             } else {
2877                storeLE( mkexpr(addr), mkexpr(dst1) );
2878             }
2879             DIP("not%c %s\n", nameISize(sz), dis_buf);
2880             break;
2881          case 3: /* NEG */
2882             dst0 = newTemp(ty);
2883             src  = newTemp(ty);
2884             dst1 = newTemp(ty);
2885             assign(dst0, mkU(ty,0));
2886             assign(src,  mkexpr(t1));
2887             assign(dst1, binop(mkSizedOp(ty,Iop_Sub8),
2888                                mkexpr(dst0), mkexpr(src)));
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             setFlags_DEP1_DEP2(Iop_Sub8, dst0, src, ty);
2896             DIP("neg%c %s\n", nameISize(sz), dis_buf);
2897             break;
2898          case 4: /* MUL */
2899             codegen_mulL_A_D ( sz, False, t1, dis_buf );
2900             break;
2901          case 5: /* IMUL */
2902             codegen_mulL_A_D ( sz, True, t1, dis_buf );
2903             break;
2904          case 6: /* DIV */
2905             codegen_div ( sz, t1, False );
2906             DIP("div%c %s\n", nameISize(sz), dis_buf);
2907             break;
2908          case 7: /* IDIV */
2909             codegen_div ( sz, t1, True );
2910             DIP("idiv%c %s\n", nameISize(sz), dis_buf);
2911             break;
2912          default: 
2913             /* This can't happen - gregOfRM should return 0 .. 7 only */
2914             vpanic("Grp3(x86)");
2915       }
2916    }
2917    return delta;
2918 }
2919
2920
2921 /* Group 4 extended opcodes. */
2922 static
2923 UInt dis_Grp4 ( UChar sorb, Bool locked, Int delta, Bool* decode_OK )
2924 {
2925    Int   alen;
2926    UChar modrm;
2927    HChar dis_buf[50];
2928    IRType ty = Ity_I8;
2929    IRTemp t1 = newTemp(ty);
2930    IRTemp t2 = newTemp(ty);
2931
2932    *decode_OK = True;
2933
2934    modrm = getIByte(delta);
2935
2936    if (locked && (gregOfRM(modrm) != 0 && gregOfRM(modrm) != 1)) {
2937       /* LOCK prefix only allowed with inc and dec subopcodes */
2938       *decode_OK = False;
2939       return delta;
2940    }
2941
2942    if (epartIsReg(modrm)) {
2943       assign(t1, getIReg(1, eregOfRM(modrm)));
2944       switch (gregOfRM(modrm)) {
2945          case 0: /* INC */
2946             assign(t2, binop(Iop_Add8, mkexpr(t1), mkU8(1)));
2947             putIReg(1, eregOfRM(modrm), mkexpr(t2));
2948             setFlags_INC_DEC( True, t2, ty );
2949             break;
2950          case 1: /* DEC */
2951             assign(t2, binop(Iop_Sub8, mkexpr(t1), mkU8(1)));
2952             putIReg(1, eregOfRM(modrm), mkexpr(t2));
2953             setFlags_INC_DEC( False, t2, ty );
2954             break;
2955          default: 
2956             *decode_OK = False;
2957             return delta;
2958       }
2959       delta++;
2960       DIP("%sb %s\n", nameGrp4(gregOfRM(modrm)),
2961                       nameIReg(1, eregOfRM(modrm)));
2962    } else {
2963       IRTemp addr = disAMode ( &alen, sorb, delta, dis_buf );
2964       assign( t1, loadLE(ty, mkexpr(addr)) );
2965       switch (gregOfRM(modrm)) {
2966          case 0: /* INC */
2967             assign(t2, binop(Iop_Add8, mkexpr(t1), mkU8(1)));
2968             if (locked) {
2969                casLE( mkexpr(addr), mkexpr(t1)/*expd*/, mkexpr(t2)/*new*/, 
2970                       guest_EIP_curr_instr );
2971             } else {
2972                storeLE( mkexpr(addr), mkexpr(t2) );
2973             }
2974             setFlags_INC_DEC( True, t2, ty );
2975             break;
2976          case 1: /* DEC */
2977             assign(t2, binop(Iop_Sub8, mkexpr(t1), mkU8(1)));
2978             if (locked) {
2979                casLE( mkexpr(addr), mkexpr(t1)/*expd*/, mkexpr(t2)/*new*/, 
2980                       guest_EIP_curr_instr );
2981             } else {
2982                storeLE( mkexpr(addr), mkexpr(t2) );
2983             }
2984             setFlags_INC_DEC( False, t2, ty );
2985             break;
2986          default: 
2987             *decode_OK = False;
2988             return delta;
2989       }
2990       delta += alen;
2991       DIP("%sb %s\n", nameGrp4(gregOfRM(modrm)), dis_buf);
2992    }
2993    return delta;
2994 }
2995
2996
2997 /* Group 5 extended opcodes. */
2998 static
2999 UInt dis_Grp5 ( UChar sorb, Bool locked, Int sz, Int delta, 
3000                 DisResult* dres, Bool* decode_OK )
3001 {
3002    Int     len;
3003    UChar   modrm;
3004    HChar   dis_buf[50];
3005    IRTemp  addr = IRTemp_INVALID;
3006    IRType  ty = szToITy(sz);
3007    IRTemp  t1 = newTemp(ty);
3008    IRTemp  t2 = IRTemp_INVALID;
3009
3010    *decode_OK = True;
3011
3012    modrm = getIByte(delta);
3013
3014    if (locked && (gregOfRM(modrm) != 0 && gregOfRM(modrm) != 1)) {
3015       /* LOCK prefix only allowed with inc and dec subopcodes */
3016       *decode_OK = False;
3017       return delta;
3018    }
3019
3020    if (epartIsReg(modrm)) {
3021       assign(t1, getIReg(sz,eregOfRM(modrm)));
3022       switch (gregOfRM(modrm)) {
3023          case 0: /* INC */ 
3024             vassert(sz == 2 || sz == 4);
3025             t2 = newTemp(ty);
3026             assign(t2, binop(mkSizedOp(ty,Iop_Add8),
3027                              mkexpr(t1), mkU(ty,1)));
3028             setFlags_INC_DEC( True, t2, ty );
3029             putIReg(sz,eregOfRM(modrm),mkexpr(t2));
3030             break;
3031          case 1: /* DEC */ 
3032             vassert(sz == 2 || sz == 4);
3033             t2 = newTemp(ty);
3034             assign(t2, binop(mkSizedOp(ty,Iop_Sub8),
3035                              mkexpr(t1), mkU(ty,1)));
3036             setFlags_INC_DEC( False, t2, ty );
3037             putIReg(sz,eregOfRM(modrm),mkexpr(t2));
3038             break;
3039          case 2: /* call Ev */
3040             vassert(sz == 4);
3041             t2 = newTemp(Ity_I32);
3042             assign(t2, binop(Iop_Sub32, getIReg(4,R_ESP), mkU32(4)));
3043             putIReg(4, R_ESP, mkexpr(t2));
3044             storeLE( mkexpr(t2), mkU32(guest_EIP_bbstart+delta+1));
3045             jmp_treg(Ijk_Call,t1);
3046             dres->whatNext = Dis_StopHere;
3047             break;
3048          case 4: /* jmp Ev */
3049             vassert(sz == 4);
3050             jmp_treg(Ijk_Boring,t1);
3051             dres->whatNext = Dis_StopHere;
3052             break;
3053          case 6: /* PUSH Ev */
3054             vassert(sz == 4 || sz == 2);
3055             t2 = newTemp(Ity_I32);
3056             assign( t2, binop(Iop_Sub32,getIReg(4,R_ESP),mkU32(sz)) );
3057             putIReg(4, R_ESP, mkexpr(t2) );
3058             storeLE( mkexpr(t2), mkexpr(t1) );
3059             break;
3060          default: 
3061             *decode_OK = False;
3062             return delta;
3063       }
3064       delta++;
3065       DIP("%s%c %s\n", nameGrp5(gregOfRM(modrm)),
3066                        nameISize(sz), nameIReg(sz, eregOfRM(modrm)));
3067    } else {
3068       addr = disAMode ( &len, sorb, delta, dis_buf );
3069       assign(t1, loadLE(ty,mkexpr(addr)));
3070       switch (gregOfRM(modrm)) {
3071          case 0: /* INC */ 
3072             t2 = newTemp(ty);
3073             assign(t2, binop(mkSizedOp(ty,Iop_Add8),
3074                              mkexpr(t1), mkU(ty,1)));
3075             if (locked) {
3076                casLE( mkexpr(addr),
3077                       mkexpr(t1), mkexpr(t2), guest_EIP_curr_instr );
3078             } else {
3079                storeLE(mkexpr(addr),mkexpr(t2));
3080             }
3081             setFlags_INC_DEC( True, t2, ty );
3082             break;
3083          case 1: /* DEC */ 
3084             t2 = newTemp(ty);
3085             assign(t2, binop(mkSizedOp(ty,Iop_Sub8),
3086                              mkexpr(t1), mkU(ty,1)));
3087             if (locked) {
3088                casLE( mkexpr(addr),
3089                       mkexpr(t1), mkexpr(t2), guest_EIP_curr_instr );
3090             } else {
3091                storeLE(mkexpr(addr),mkexpr(t2));
3092             }
3093             setFlags_INC_DEC( False, t2, ty );
3094             break;
3095          case 2: /* call Ev */
3096             vassert(sz == 4);
3097             t2 = newTemp(Ity_I32);
3098             assign(t2, binop(Iop_Sub32, getIReg(4,R_ESP), mkU32(4)));
3099             putIReg(4, R_ESP, mkexpr(t2));
3100             storeLE( mkexpr(t2), mkU32(guest_EIP_bbstart+delta+len));
3101             jmp_treg(Ijk_Call,t1);
3102             dres->whatNext = Dis_StopHere;
3103             break;
3104          case 4: /* JMP Ev */
3105             vassert(sz == 4);
3106             jmp_treg(Ijk_Boring,t1);
3107             dres->whatNext = Dis_StopHere;
3108             break;
3109          case 6: /* PUSH Ev */
3110             vassert(sz == 4 || sz == 2);
3111             t2 = newTemp(Ity_I32);
3112             assign( t2, binop(Iop_Sub32,getIReg(4,R_ESP),mkU32(sz)) );
3113             putIReg(4, R_ESP, mkexpr(t2) );
3114             storeLE( mkexpr(t2), mkexpr(t1) );
3115             break;
3116          default: 
3117             *decode_OK = False;
3118             return delta;
3119       }
3120       delta += len;
3121       DIP("%s%c %s\n", nameGrp5(gregOfRM(modrm)),
3122                        nameISize(sz), dis_buf);
3123    }
3124    return delta;
3125 }
3126
3127
3128 /*------------------------------------------------------------*/
3129 /*--- Disassembling string ops (including REP prefixes)    ---*/
3130 /*------------------------------------------------------------*/
3131
3132 /* Code shared by all the string ops */
3133 static
3134 void dis_string_op_increment(Int sz, Int t_inc)
3135 {
3136    if (sz == 4 || sz == 2) {
3137       assign( t_inc, 
3138               binop(Iop_Shl32, IRExpr_Get( OFFB_DFLAG, Ity_I32 ),
3139                                mkU8(sz/2) ) );
3140    } else {
3141       assign( t_inc, 
3142               IRExpr_Get( OFFB_DFLAG, Ity_I32 ) );
3143    }
3144 }
3145
3146 static
3147 void dis_string_op( void (*dis_OP)( Int, IRTemp ), 
3148                     Int sz, HChar* name, UChar sorb )
3149 {
3150    IRTemp t_inc = newTemp(Ity_I32);
3151    vassert(sorb == 0); /* hmm.  so what was the point of passing it in? */
3152    dis_string_op_increment(sz, t_inc);
3153    dis_OP( sz, t_inc );
3154    DIP("%s%c\n", name, nameISize(sz));
3155 }
3156
3157 static 
3158 void dis_MOVS ( Int sz, IRTemp t_inc )
3159 {
3160    IRType ty = szToITy(sz);
3161    IRTemp td = newTemp(Ity_I32);   /* EDI */
3162    IRTemp ts = newTemp(Ity_I32);   /* ESI */
3163
3164    assign( td, getIReg(4, R_EDI) );
3165    assign( ts, getIReg(4, R_ESI) );
3166
3167    storeLE( mkexpr(td), loadLE(ty,mkexpr(ts)) );
3168
3169    putIReg( 4, R_EDI, binop(Iop_Add32, mkexpr(td), mkexpr(t_inc)) );
3170    putIReg( 4, R_ESI, binop(Iop_Add32, mkexpr(ts), mkexpr(t_inc)) );
3171 }
3172
3173 static 
3174 void dis_LODS ( Int sz, IRTemp t_inc )
3175 {
3176    IRType ty = szToITy(sz);
3177    IRTemp ts = newTemp(Ity_I32);   /* ESI */
3178
3179    assign( ts, getIReg(4, R_ESI) );
3180
3181    putIReg( sz, R_EAX, loadLE(ty, mkexpr(ts)) );
3182
3183    putIReg( 4, R_ESI, binop(Iop_Add32, mkexpr(ts), mkexpr(t_inc)) );
3184 }
3185
3186 static 
3187 void dis_STOS ( Int sz, IRTemp t_inc )
3188 {
3189    IRType ty = szToITy(sz);
3190    IRTemp ta = newTemp(ty);        /* EAX */
3191    IRTemp td = newTemp(Ity_I32);   /* EDI */
3192
3193    assign( ta, getIReg(sz, R_EAX) );
3194    assign( td, getIReg(4, R_EDI) );
3195
3196    storeLE( mkexpr(td), mkexpr(ta) );
3197
3198    putIReg( 4, R_EDI, binop(Iop_Add32, mkexpr(td), mkexpr(t_inc)) );
3199 }
3200
3201 static 
3202 void dis_CMPS ( Int sz, IRTemp t_inc )
3203 {
3204    IRType ty  = szToITy(sz);
3205    IRTemp tdv = newTemp(ty);      /* (EDI) */
3206    IRTemp tsv = newTemp(ty);      /* (ESI) */
3207    IRTemp td  = newTemp(Ity_I32); /*  EDI  */
3208    IRTemp ts  = newTemp(Ity_I32); /*  ESI  */
3209
3210    assign( td, getIReg(4, R_EDI) );
3211    assign( ts, getIReg(4, R_ESI) );
3212
3213    assign( tdv, loadLE(ty,mkexpr(td)) );
3214    assign( tsv, loadLE(ty,mkexpr(ts)) );
3215
3216    setFlags_DEP1_DEP2 ( Iop_Sub8, tsv, tdv, ty );
3217
3218    putIReg(4, R_EDI, binop(Iop_Add32, mkexpr(td), mkexpr(t_inc)) );
3219    putIReg(4, R_ESI, binop(Iop_Add32, mkexpr(ts), mkexpr(t_inc)) );
3220 }
3221
3222 static 
3223 void dis_SCAS ( Int sz, IRTemp t_inc )
3224 {
3225    IRType ty  = szToITy(sz);
3226    IRTemp ta  = newTemp(ty);       /*  EAX  */
3227    IRTemp td  = newTemp(Ity_I32);  /*  EDI  */
3228    IRTemp tdv = newTemp(ty);       /* (EDI) */
3229
3230    assign( ta, getIReg(sz, R_EAX) );
3231    assign( td, getIReg(4, R_EDI) );
3232
3233    assign( tdv, loadLE(ty,mkexpr(td)) );
3234    setFlags_DEP1_DEP2 ( Iop_Sub8, ta, tdv, ty );
3235
3236    putIReg(4, R_EDI, binop(Iop_Add32, mkexpr(td), mkexpr(t_inc)) );
3237 }
3238
3239
3240 /* Wrap the appropriate string op inside a REP/REPE/REPNE.
3241    We assume the insn is the last one in the basic block, and so emit a jump
3242    to the next insn, rather than just falling through. */
3243 static 
3244 void dis_REP_op ( X86Condcode cond,
3245                   void (*dis_OP)(Int, IRTemp),
3246                   Int sz, Addr32 eip, Addr32 eip_next, HChar* name )
3247 {
3248    IRTemp t_inc = newTemp(Ity_I32);
3249    IRTemp tc    = newTemp(Ity_I32);  /*  ECX  */
3250
3251    assign( tc, getIReg(4,R_ECX) );
3252
3253    stmt( IRStmt_Exit( binop(Iop_CmpEQ32,mkexpr(tc),mkU32(0)),
3254                       Ijk_Boring,
3255                       IRConst_U32(eip_next) ) );
3256
3257    putIReg(4, R_ECX, binop(Iop_Sub32, mkexpr(tc), mkU32(1)) );
3258
3259    dis_string_op_increment(sz, t_inc);
3260    dis_OP (sz, t_inc);
3261
3262    if (cond == X86CondAlways) {
3263       jmp_lit(Ijk_Boring,eip);
3264    } else {
3265       stmt( IRStmt_Exit( mk_x86g_calculate_condition(cond),
3266                          Ijk_Boring,
3267                          IRConst_U32(eip) ) );
3268       jmp_lit(Ijk_Boring,eip_next);
3269    }
3270    DIP("%s%c\n", name, nameISize(sz));
3271 }
3272
3273
3274 /*------------------------------------------------------------*/
3275 /*--- Arithmetic, etc.                                     ---*/
3276 /*------------------------------------------------------------*/
3277
3278 /* IMUL E, G.  Supplied eip points to the modR/M byte. */
3279 static
3280 UInt dis_mul_E_G ( UChar       sorb,
3281                    Int         size, 
3282                    Int         delta0 )
3283 {
3284    Int    alen;
3285    HChar  dis_buf[50];
3286    UChar  rm = getIByte(delta0);
3287    IRType ty = szToITy(size);
3288    IRTemp te = newTemp(ty);
3289    IRTemp tg = newTemp(ty);
3290    IRTemp resLo = newTemp(ty);
3291
3292    assign( tg, getIReg(size, gregOfRM(rm)) );
3293    if (epartIsReg(rm)) {
3294       assign( te, getIReg(size, eregOfRM(rm)) );
3295    } else {
3296       IRTemp addr = disAMode( &alen, sorb, delta0, dis_buf );
3297       assign( te, loadLE(ty,mkexpr(addr)) );
3298    }
3299
3300    setFlags_MUL ( ty, te, tg, X86G_CC_OP_SMULB );
3301
3302    assign( resLo, binop( mkSizedOp(ty, Iop_Mul8), mkexpr(te), mkexpr(tg) ) );
3303
3304    putIReg(size, gregOfRM(rm), mkexpr(resLo) );
3305
3306    if (epartIsReg(rm)) {
3307       DIP("imul%c %s, %s\n", nameISize(size), 
3308                              nameIReg(size,eregOfRM(rm)),
3309                              nameIReg(size,gregOfRM(rm)));
3310       return 1+delta0;
3311    } else {
3312       DIP("imul%c %s, %s\n", nameISize(size), 
3313                              dis_buf, nameIReg(size,gregOfRM(rm)));
3314       return alen+delta0;
3315    }
3316 }
3317
3318
3319 /* IMUL I * E -> G.  Supplied eip points to the modR/M byte. */
3320 static
3321 UInt dis_imul_I_E_G ( UChar       sorb,
3322                       Int         size, 
3323                       Int         delta,
3324                       Int         litsize )
3325 {
3326    Int    d32, alen;
3327    HChar  dis_buf[50];
3328    UChar  rm = getIByte(delta);
3329    IRType ty = szToITy(size);
3330    IRTemp te = newTemp(ty);
3331    IRTemp tl = newTemp(ty);
3332    IRTemp resLo = newTemp(ty);
3333
3334    vassert(size == 1 || size == 2 || size == 4);
3335
3336    if (epartIsReg(rm)) {
3337       assign(te, getIReg(size, eregOfRM(rm)));
3338       delta++;
3339    } else {
3340       IRTemp addr = disAMode( &alen, sorb, delta, dis_buf );
3341       assign(te, loadLE(ty, mkexpr(addr)));
3342       delta += alen;
3343    }
3344    d32 = getSDisp(litsize,delta);
3345    delta += litsize;
3346
3347    if (size == 1) d32 &= 0xFF;
3348    if (size == 2) d32 &= 0xFFFF;
3349
3350    assign(tl, mkU(ty,d32));
3351
3352    assign( resLo, binop( mkSizedOp(ty, Iop_Mul8), mkexpr(te), mkexpr(tl) ));
3353
3354    setFlags_MUL ( ty, te, tl, X86G_CC_OP_SMULB );
3355
3356    putIReg(size, gregOfRM(rm), mkexpr(resLo));
3357
3358    DIP("imul %d, %s, %s\n", d32, 
3359        ( epartIsReg(rm) ? nameIReg(size,eregOfRM(rm)) : dis_buf ),
3360        nameIReg(size,gregOfRM(rm)) );
3361    return delta;
3362 }
3363
3364
3365 /*------------------------------------------------------------*/
3366 /*---                                                      ---*/
3367 /*--- x87 FLOATING POINT INSTRUCTIONS                      ---*/
3368 /*---                                                      ---*/
3369 /*------------------------------------------------------------*/
3370
3371 /* --- Helper functions for dealing with the register stack. --- */
3372
3373 /* --- Set the emulation-warning pseudo-register. --- */
3374
3375 static void put_emwarn ( IRExpr* e /* :: Ity_I32 */ )
3376 {
3377    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I32);
3378    stmt( IRStmt_Put( OFFB_EMWARN, e ) );
3379 }
3380
3381 /* --- Produce an IRExpr* denoting a 64-bit QNaN. --- */
3382
3383 static IRExpr* mkQNaN64 ( void )
3384 {
3385   /* QNaN is 0 2047 1 0(51times) 
3386      == 0b 11111111111b 1 0(51times)
3387      == 0x7FF8 0000 0000 0000
3388    */
3389    return IRExpr_Const(IRConst_F64i(0x7FF8000000000000ULL));
3390 }
3391
3392 /* --------- Get/put the top-of-stack pointer. --------- */
3393
3394 static IRExpr* get_ftop ( void )
3395 {
3396    return IRExpr_Get( OFFB_FTOP, Ity_I32 );
3397 }
3398
3399 static void put_ftop ( IRExpr* e )
3400 {
3401    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I32);
3402    stmt( IRStmt_Put( OFFB_FTOP, e ) );
3403 }
3404
3405 /* --------- Get/put the C3210 bits. --------- */
3406
3407 static IRExpr* get_C3210 ( void )
3408 {
3409    return IRExpr_Get( OFFB_FC3210, Ity_I32 );
3410 }
3411
3412 static void put_C3210 ( IRExpr* e )
3413 {
3414    stmt( IRStmt_Put( OFFB_FC3210, e ) );
3415 }
3416
3417 /* --------- Get/put the FPU rounding mode. --------- */
3418 static IRExpr* /* :: Ity_I32 */ get_fpround ( void )
3419 {
3420    return IRExpr_Get( OFFB_FPROUND, Ity_I32 );
3421 }
3422
3423 static void put_fpround ( IRExpr* /* :: Ity_I32 */ e )
3424 {
3425    stmt( IRStmt_Put( OFFB_FPROUND, e ) );
3426 }
3427
3428
3429 /* --------- Synthesise a 2-bit FPU rounding mode. --------- */
3430 /* Produces a value in 0 .. 3, which is encoded as per the type
3431    IRRoundingMode.  Since the guest_FPROUND value is also encoded as
3432    per IRRoundingMode, we merely need to get it and mask it for
3433    safety.
3434 */
3435 static IRExpr* /* :: Ity_I32 */ get_roundingmode ( void )
3436 {
3437    return binop( Iop_And32, get_fpround(), mkU32(3) );
3438 }
3439
3440 static IRExpr* /* :: Ity_I32 */ get_FAKE_roundingmode ( void )
3441 {
3442    return mkU32(Irrm_NEAREST);
3443 }
3444
3445
3446 /* --------- Get/set FP register tag bytes. --------- */
3447
3448 /* Given i, and some expression e, generate 'ST_TAG(i) = e'. */
3449
3450 static void put_ST_TAG ( Int i, IRExpr* value )
3451 {
3452    IRRegArray* descr;
3453    vassert(typeOfIRExpr(irsb->tyenv, value) == Ity_I8);
3454    descr = mkIRRegArray( OFFB_FPTAGS, Ity_I8, 8 );
3455    stmt( IRStmt_PutI( descr, get_ftop(), i, value ) );
3456 }
3457
3458 /* Given i, generate an expression yielding 'ST_TAG(i)'.  This will be
3459    zero to indicate "Empty" and nonzero to indicate "NonEmpty".  */
3460
3461 static IRExpr* get_ST_TAG ( Int i )
3462 {
3463    IRRegArray* descr = mkIRRegArray( OFFB_FPTAGS, Ity_I8, 8 );
3464    return IRExpr_GetI( descr, get_ftop(), i );
3465 }
3466
3467
3468 /* --------- Get/set FP registers. --------- */
3469
3470 /* Given i, and some expression e, emit 'ST(i) = e' and set the
3471    register's tag to indicate the register is full.  The previous
3472    state of the register is not checked. */
3473
3474 static void put_ST_UNCHECKED ( Int i, IRExpr* value )
3475 {
3476    IRRegArray* descr;
3477    vassert(typeOfIRExpr(irsb->tyenv, value) == Ity_F64);
3478    descr = mkIRRegArray( OFFB_FPREGS, Ity_F64, 8 );
3479    stmt( IRStmt_PutI( descr, get_ftop(), i, value ) );
3480    /* Mark the register as in-use. */
3481    put_ST_TAG(i, mkU8(1));
3482 }
3483
3484 /* Given i, and some expression e, emit
3485       ST(i) = is_full(i) ? NaN : e
3486    and set the tag accordingly.
3487 */
3488
3489 static void put_ST ( Int i, IRExpr* value )
3490 {
3491    put_ST_UNCHECKED( i,
3492                      IRExpr_Mux0X( get_ST_TAG(i),
3493                                    /* 0 means empty */
3494                                    value,
3495                                    /* non-0 means full */
3496                                    mkQNaN64()
3497                    )
3498    );
3499 }
3500
3501
3502 /* Given i, generate an expression yielding 'ST(i)'. */
3503
3504 static IRExpr* get_ST_UNCHECKED ( Int i )
3505 {
3506    IRRegArray* descr = mkIRRegArray( OFFB_FPREGS, Ity_F64, 8 );
3507    return IRExpr_GetI( descr, get_ftop(), i );
3508 }
3509
3510
3511 /* Given i, generate an expression yielding 
3512   is_full(i) ? ST(i) : NaN
3513 */
3514
3515 static IRExpr* get_ST ( Int i )
3516 {
3517    return
3518       IRExpr_Mux0X( get_ST_TAG(i),
3519                     /* 0 means empty */
3520                     mkQNaN64(),
3521                     /* non-0 means full */
3522                     get_ST_UNCHECKED(i));
3523 }
3524
3525
3526 /* Adjust FTOP downwards by one register. */
3527
3528 static void fp_push ( void )
3529 {
3530    put_ftop( binop(Iop_Sub32, get_ftop(), mkU32(1)) );
3531 }
3532
3533 /* Adjust FTOP upwards by one register, and mark the vacated register
3534    as empty.  */
3535
3536 static void fp_pop ( void )
3537 {
3538    put_ST_TAG(0, mkU8(0));
3539    put_ftop( binop(Iop_Add32, get_ftop(), mkU32(1)) );
3540 }
3541
3542 /* Clear the C2 bit of the FPU status register, for
3543    sin/cos/tan/sincos. */
3544
3545 static void clear_C2 ( void )
3546 {
3547    put_C3210( binop(Iop_And32, get_C3210(), mkU32(~X86G_FC_MASK_C2)) );
3548 }
3549
3550 /* Invent a plausible-looking FPU status word value:
3551       ((ftop & 7) << 11) | (c3210 & 0x4700)
3552  */
3553 static IRExpr* get_FPU_sw ( void )
3554 {
3555    return
3556       unop(Iop_32to16,
3557            binop(Iop_Or32,
3558                  binop(Iop_Shl32, 
3559                        binop(Iop_And32, get_ftop(), mkU32(7)), 
3560                              mkU8(11)),
3561                        binop(Iop_And32, get_C3210(), mkU32(0x4700))
3562       ));
3563 }
3564
3565
3566 /* ------------------------------------------------------- */
3567 /* Given all that stack-mangling junk, we can now go ahead
3568    and describe FP instructions. 
3569 */
3570
3571 /* ST(0) = ST(0) `op` mem64/32(addr)
3572    Need to check ST(0)'s tag on read, but not on write.
3573 */
3574 static
3575 void fp_do_op_mem_ST_0 ( IRTemp addr, HChar* op_txt, HChar* dis_buf, 
3576                          IROp op, Bool dbl )
3577 {
3578    DIP("f%s%c %s\n", op_txt, dbl?'l':'s', dis_buf);
3579    if (dbl) {
3580       put_ST_UNCHECKED(0, 
3581          triop( op, 
3582                 get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
3583                 get_ST(0), 
3584                 loadLE(Ity_F64,mkexpr(addr))
3585          ));
3586    } else {
3587       put_ST_UNCHECKED(0, 
3588          triop( op, 
3589                 get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
3590                 get_ST(0), 
3591                 unop(Iop_F32toF64, loadLE(Ity_F32,mkexpr(addr)))
3592          ));
3593    }
3594 }
3595
3596
3597 /* ST(0) = mem64/32(addr) `op` ST(0)
3598    Need to check ST(0)'s tag on read, but not on write.
3599 */
3600 static
3601 void fp_do_oprev_mem_ST_0 ( IRTemp addr, HChar* op_txt, HChar* dis_buf, 
3602                             IROp op, Bool dbl )
3603 {
3604    DIP("f%s%c %s\n", op_txt, dbl?'l':'s', dis_buf);
3605    if (dbl) {
3606       put_ST_UNCHECKED(0, 
3607          triop( op, 
3608                 get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
3609                 loadLE(Ity_F64,mkexpr(addr)),
3610                 get_ST(0)
3611          ));
3612    } else {
3613       put_ST_UNCHECKED(0, 
3614          triop( op, 
3615                 get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
3616                 unop(Iop_F32toF64, loadLE(Ity_F32,mkexpr(addr))),
3617                 get_ST(0)
3618          ));
3619    }
3620 }
3621
3622
3623 /* ST(dst) = ST(dst) `op` ST(src).
3624    Check dst and src tags when reading but not on write.
3625 */
3626 static
3627 void fp_do_op_ST_ST ( HChar* op_txt, IROp op, UInt st_src, UInt st_dst,
3628                       Bool pop_after )
3629 {
3630    DIP("f%s%s st(%d), st(%d)\n", op_txt, pop_after?"p":"", 
3631                                  (Int)st_src, (Int)st_dst );
3632    put_ST_UNCHECKED( 
3633       st_dst, 
3634       triop( op, 
3635              get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
3636              get_ST(st_dst), 
3637              get_ST(st_src) ) 
3638    );
3639    if (pop_after)
3640       fp_pop();
3641 }
3642
3643 /* ST(dst) = ST(src) `op` ST(dst).
3644    Check dst and src tags when reading but not on write.
3645 */
3646 static
3647 void fp_do_oprev_ST_ST ( HChar* op_txt, IROp op, UInt st_src, UInt st_dst,
3648                          Bool pop_after )
3649 {
3650    DIP("f%s%s st(%d), st(%d)\n", op_txt, pop_after?"p":"",
3651                                  (Int)st_src, (Int)st_dst );
3652    put_ST_UNCHECKED( 
3653       st_dst, 
3654       triop( op, 
3655              get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
3656              get_ST(st_src), 
3657              get_ST(st_dst) ) 
3658    );
3659    if (pop_after)
3660       fp_pop();
3661 }
3662
3663 /* %eflags(Z,P,C) = UCOMI( st(0), st(i) ) */
3664 static void fp_do_ucomi_ST0_STi ( UInt i, Bool pop_after )
3665 {
3666    DIP("fucomi%s %%st(0),%%st(%d)\n", pop_after ? "p" : "", (Int)i );
3667    /* This is a bit of a hack (and isn't really right).  It sets
3668       Z,P,C,O correctly, but forces A and S to zero, whereas the Intel
3669       documentation implies A and S are unchanged. 
3670    */
3671    /* It's also fishy in that it is used both for COMIP and
3672       UCOMIP, and they aren't the same (although similar). */
3673    stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(X86G_CC_OP_COPY) ));
3674    stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0) ));
3675    stmt( IRStmt_Put( OFFB_CC_DEP1,
3676                      binop( Iop_And32,
3677                             binop(Iop_CmpF64, get_ST(0), get_ST(i)),
3678                             mkU32(0x45)
3679        )));
3680    /* Set NDEP even though it isn't used.  This makes redundant-PUT
3681       elimination of previous stores to this field work better. */
3682    stmt( IRStmt_Put( OFFB_CC_NDEP, mkU32(0) ));
3683    if (pop_after)
3684       fp_pop();
3685 }
3686
3687
3688 static
3689 UInt dis_FPU ( Bool* decode_ok, UChar sorb, Int delta )
3690 {
3691    Int    len;
3692    UInt   r_src, r_dst;
3693    HChar  dis_buf[50];
3694    IRTemp t1, t2;
3695
3696    /* On entry, delta points at the second byte of the insn (the modrm
3697       byte).*/
3698    UChar first_opcode = getIByte(delta-1);
3699    UChar modrm        = getIByte(delta+0);
3700
3701    /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xD8 opcodes +-+-+-+-+-+-+-+ */
3702
3703    if (first_opcode == 0xD8) {
3704       if (modrm < 0xC0) {
3705
3706          /* bits 5,4,3 are an opcode extension, and the modRM also
3707            specifies an address. */
3708          IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
3709          delta += len;
3710
3711          switch (gregOfRM(modrm)) {
3712
3713             case 0: /* FADD single-real */
3714                fp_do_op_mem_ST_0 ( addr, "add", dis_buf, Iop_AddF64, False );
3715                break;
3716
3717             case 1: /* FMUL single-real */
3718                fp_do_op_mem_ST_0 ( addr, "mul", dis_buf, Iop_MulF64, False );
3719                break;
3720
3721             case 2: /* FCOM single-real */
3722                DIP("fcoms %s\n", dis_buf);
3723                /* This forces C1 to zero, which isn't right. */
3724                put_C3210( 
3725                    binop( Iop_And32,
3726                           binop(Iop_Shl32, 
3727                                 binop(Iop_CmpF64, 
3728                                       get_ST(0),
3729                                       unop(Iop_F32toF64, 
3730                                            loadLE(Ity_F32,mkexpr(addr)))),
3731                                 mkU8(8)),
3732                           mkU32(0x4500)
3733                    ));
3734                break;  
3735
3736             case 3: /* FCOMP single-real */
3737                DIP("fcomps %s\n", dis_buf);
3738                /* This forces C1 to zero, which isn't right. */
3739                put_C3210( 
3740                    binop( Iop_And32,
3741                           binop(Iop_Shl32, 
3742                                 binop(Iop_CmpF64, 
3743                                       get_ST(0),
3744                                       unop(Iop_F32toF64, 
3745                                            loadLE(Ity_F32,mkexpr(addr)))),
3746                                 mkU8(8)),
3747                           mkU32(0x4500)
3748                    ));
3749                fp_pop();
3750                break;  
3751
3752             case 4: /* FSUB single-real */
3753                fp_do_op_mem_ST_0 ( addr, "sub", dis_buf, Iop_SubF64, False );
3754                break;
3755
3756             case 5: /* FSUBR single-real */
3757                fp_do_oprev_mem_ST_0 ( addr, "subr", dis_buf, Iop_SubF64, False );
3758                break;
3759
3760             case 6: /* FDIV single-real */
3761                fp_do_op_mem_ST_0 ( addr, "div", dis_buf, Iop_DivF64, False );
3762                break;
3763
3764             case 7: /* FDIVR single-real */
3765                fp_do_oprev_mem_ST_0 ( addr, "divr", dis_buf, Iop_DivF64, False );
3766                break;
3767
3768             default:
3769                vex_printf("unhandled opc_aux = 0x%2x\n", gregOfRM(modrm));
3770                vex_printf("first_opcode == 0xD8\n");
3771                goto decode_fail;
3772          }
3773       } else {
3774          delta++;
3775          switch (modrm) {
3776
3777             case 0xC0 ... 0xC7: /* FADD %st(?),%st(0) */
3778                fp_do_op_ST_ST ( "add", Iop_AddF64, modrm - 0xC0, 0, False );
3779                break;
3780
3781             case 0xC8 ... 0xCF: /* FMUL %st(?),%st(0) */
3782                fp_do_op_ST_ST ( "mul", Iop_MulF64, modrm - 0xC8, 0, False );
3783                break;
3784
3785             /* Dunno if this is right */
3786             case 0xD0 ... 0xD7: /* FCOM %st(?),%st(0) */
3787                r_dst = (UInt)modrm - 0xD0;
3788                DIP("fcom %%st(0),%%st(%d)\n", (Int)r_dst);
3789                /* This forces C1 to zero, which isn't right. */
3790                put_C3210( 
3791                    binop( Iop_And32,
3792                           binop(Iop_Shl32, 
3793                                 binop(Iop_CmpF64, get_ST(0), get_ST(r_dst)),
3794                                 mkU8(8)),
3795                           mkU32(0x4500)
3796                    ));
3797                break;
3798
3799             /* Dunno if this is right */
3800             case 0xD8 ... 0xDF: /* FCOMP %st(?),%st(0) */
3801                r_dst = (UInt)modrm - 0xD8;
3802                DIP("fcomp %%st(0),%%st(%d)\n", (Int)r_dst);
3803                /* This forces C1 to zero, which isn't right. */
3804                put_C3210( 
3805                    binop( Iop_And32,
3806                           binop(Iop_Shl32, 
3807                                 binop(Iop_CmpF64, get_ST(0), get_ST(r_dst)),
3808                                 mkU8(8)),
3809                           mkU32(0x4500)
3810                    ));
3811                fp_pop();
3812                break;
3813
3814             case 0xE0 ... 0xE7: /* FSUB %st(?),%st(0) */
3815                fp_do_op_ST_ST ( "sub", Iop_SubF64, modrm - 0xE0, 0, False );
3816                break;
3817
3818             case 0xE8 ... 0xEF: /* FSUBR %st(?),%st(0) */
3819                fp_do_oprev_ST_ST ( "subr", Iop_SubF64, modrm - 0xE8, 0, False );
3820                break;
3821
3822             case 0xF0 ... 0xF7: /* FDIV %st(?),%st(0) */
3823                fp_do_op_ST_ST ( "div", Iop_DivF64, modrm - 0xF0, 0, False );
3824                break;
3825
3826             case 0xF8 ... 0xFF: /* FDIVR %st(?),%st(0) */
3827                fp_do_oprev_ST_ST ( "divr", Iop_DivF64, modrm - 0xF8, 0, False );
3828                break;
3829
3830             default:
3831                goto decode_fail;
3832          }
3833       }
3834    }
3835
3836    /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xD9 opcodes +-+-+-+-+-+-+-+ */
3837    else
3838    if (first_opcode == 0xD9) {
3839       if (modrm < 0xC0) {
3840
3841          /* bits 5,4,3 are an opcode extension, and the modRM also
3842             specifies an address. */
3843          IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
3844          delta += len;
3845
3846          switch (gregOfRM(modrm)) {
3847
3848             case 0: /* FLD single-real */
3849                DIP("flds %s\n", dis_buf);
3850                fp_push();
3851                put_ST(0, unop(Iop_F32toF64,
3852                               loadLE(Ity_F32, mkexpr(addr))));
3853                break;
3854
3855             case 2: /* FST single-real */
3856                DIP("fsts %s\n", dis_buf);
3857                storeLE(mkexpr(addr),
3858                        binop(Iop_F64toF32, get_roundingmode(), get_ST(0)));
3859                break;
3860
3861             case 3: /* FSTP single-real */
3862                DIP("fstps %s\n", dis_buf);
3863                storeLE(mkexpr(addr), 
3864                        binop(Iop_F64toF32, get_roundingmode(), get_ST(0)));
3865                fp_pop();
3866                break;
3867
3868             case 4: { /* FLDENV m28 */
3869                /* Uses dirty helper: 
3870                      VexEmWarn x86g_do_FLDENV ( VexGuestX86State*, HWord ) */
3871                IRTemp   ew = newTemp(Ity_I32);
3872                IRDirty* d  = unsafeIRDirty_0_N ( 
3873                                 0/*regparms*/, 
3874                                 "x86g_dirtyhelper_FLDENV", 
3875                                 &x86g_dirtyhelper_FLDENV,
3876                                 mkIRExprVec_1( mkexpr(addr) )
3877                              );
3878                d->needsBBP = True;
3879                d->tmp      = ew;
3880                /* declare we're reading memory */
3881                d->mFx   = Ifx_Read;
3882                d->mAddr = mkexpr(addr);
3883                d->mSize = 28;
3884
3885                /* declare we're writing guest state */
3886                d->nFxState = 4;
3887
3888                d->fxState[0].fx     = Ifx_Write;
3889                d->fxState[0].offset = OFFB_FTOP;
3890                d->fxState[0].size   = sizeof(UInt);
3891
3892                d->fxState[1].fx     = Ifx_Write;
3893                d->fxState[1].offset = OFFB_FPTAGS;
3894                d->fxState[1].size   = 8 * sizeof(UChar);
3895
3896                d->fxState[2].fx     = Ifx_Write;
3897                d->fxState[2].offset = OFFB_FPROUND;
3898                d->fxState[2].size   = sizeof(UInt);
3899
3900                d->fxState[3].fx     = Ifx_Write;
3901                d->fxState[3].offset = OFFB_FC3210;
3902                d->fxState[3].size   = sizeof(UInt);
3903
3904                stmt( IRStmt_Dirty(d) );
3905
3906                /* ew contains any emulation warning we may need to
3907                   issue.  If needed, side-exit to the next insn,
3908                   reporting the warning, so that Valgrind's dispatcher
3909                   sees the warning. */
3910                put_emwarn( mkexpr(ew) );
3911                stmt( 
3912                   IRStmt_Exit(
3913                      binop(Iop_CmpNE32, mkexpr(ew), mkU32(0)),
3914                      Ijk_EmWarn,
3915                      IRConst_U32( ((Addr32)guest_EIP_bbstart)+delta)
3916                   )
3917                );
3918
3919                DIP("fldenv %s\n", dis_buf);
3920                break;
3921             }
3922
3923             case 5: {/* FLDCW */
3924                /* The only thing we observe in the control word is the
3925                   rounding mode.  Therefore, pass the 16-bit value
3926                   (x87 native-format control word) to a clean helper,
3927                   getting back a 64-bit value, the lower half of which
3928                   is the FPROUND value to store, and the upper half of
3929                   which is the emulation-warning token which may be
3930                   generated.
3931                */
3932                /* ULong x86h_check_fldcw ( UInt ); */
3933                IRTemp t64 = newTemp(Ity_I64);
3934                IRTemp ew = newTemp(Ity_I32);
3935                DIP("fldcw %s\n", dis_buf);
3936                assign( t64, mkIRExprCCall(
3937                                Ity_I64, 0/*regparms*/, 
3938                                "x86g_check_fldcw",
3939                                &x86g_check_fldcw, 
3940                                mkIRExprVec_1( 
3941                                   unop( Iop_16Uto32, 
3942                                         loadLE(Ity_I16, mkexpr(addr)))
3943                                )
3944                             )
3945                      );
3946
3947                put_fpround( unop(Iop_64to32, mkexpr(t64)) );
3948                assign( ew, unop(Iop_64HIto32, mkexpr(t64) ) );
3949                put_emwarn( mkexpr(ew) );
3950                /* Finally, if an emulation warning was reported,
3951                   side-exit to the next insn, reporting the warning,
3952                   so that Valgrind's dispatcher sees the warning. */
3953                stmt( 
3954                   IRStmt_Exit(
3955                      binop(Iop_CmpNE32, mkexpr(ew), mkU32(0)),
3956                      Ijk_EmWarn,
3957                      IRConst_U32( ((Addr32)guest_EIP_bbstart)+delta)
3958                   )
3959                );
3960                break;
3961             }
3962
3963             case 6: { /* FNSTENV m28 */
3964                /* Uses dirty helper: 
3965                      void x86g_do_FSTENV ( VexGuestX86State*, HWord ) */
3966                IRDirty* d = unsafeIRDirty_0_N ( 
3967                                0/*regparms*/, 
3968                                "x86g_dirtyhelper_FSTENV", 
3969                                &x86g_dirtyhelper_FSTENV,
3970                                mkIRExprVec_1( mkexpr(addr) )
3971                             );
3972                d->needsBBP = True;
3973                /* declare we're writing memory */
3974                d->mFx   = Ifx_Write;
3975                d->mAddr = mkexpr(addr);
3976                d->mSize = 28;
3977
3978                /* declare we're reading guest state */
3979                d->nFxState = 4;
3980
3981                d->fxState[0].fx     = Ifx_Read;
3982                d->fxState[0].offset = OFFB_FTOP;
3983                d->fxState[0].size   = sizeof(UInt);
3984
3985                d->fxState[1].fx     = Ifx_Read;
3986                d->fxState[1].offset = OFFB_FPTAGS;
3987                d->fxState[1].size   = 8 * sizeof(UChar);
3988
3989                d->fxState[2].fx     = Ifx_Read;
3990                d->fxState[2].offset = OFFB_FPROUND;
3991                d->fxState[2].size   = sizeof(UInt);
3992
3993                d->fxState[3].fx     = Ifx_Read;
3994                d->fxState[3].offset = OFFB_FC3210;
3995                d->fxState[3].size   = sizeof(UInt);
3996
3997                stmt( IRStmt_Dirty(d) );
3998
3999                DIP("fnstenv %s\n", dis_buf);
4000                break;
4001             }
4002
4003             case 7: /* FNSTCW */
4004               /* Fake up a native x87 FPU control word.  The only
4005                  thing it depends on is FPROUND[1:0], so call a clean
4006                  helper to cook it up. */
4007                /* UInt x86h_create_fpucw ( UInt fpround ) */
4008                DIP("fnstcw %s\n", dis_buf);
4009                storeLE(
4010                   mkexpr(addr), 
4011                   unop( Iop_32to16, 
4012                         mkIRExprCCall(
4013                            Ity_I32, 0/*regp*/,
4014                            "x86g_create_fpucw", &x86g_create_fpucw, 
4015                            mkIRExprVec_1( get_fpround() ) 
4016                         ) 
4017                   ) 
4018                );
4019                break;
4020
4021             default:
4022                vex_printf("unhandled opc_aux = 0x%2x\n", gregOfRM(modrm));
4023                vex_printf("first_opcode == 0xD9\n");
4024                goto decode_fail;
4025          }
4026
4027       } else {
4028          delta++;
4029          switch (modrm) {
4030
4031             case 0xC0 ... 0xC7: /* FLD %st(?) */
4032                r_src = (UInt)modrm - 0xC0;
4033                DIP("fld %%st(%d)\n", (Int)r_src);
4034                t1 = newTemp(Ity_F64);
4035                assign(t1, get_ST(r_src));
4036                fp_push();
4037                put_ST(0, mkexpr(t1));
4038                break;
4039
4040             case 0xC8 ... 0xCF: /* FXCH %st(?) */
4041                r_src = (UInt)modrm - 0xC8;
4042                DIP("fxch %%st(%d)\n", (Int)r_src);
4043                t1 = newTemp(Ity_F64);
4044                t2 = newTemp(Ity_F64);
4045                assign(t1, get_ST(0));
4046                assign(t2, get_ST(r_src));
4047                put_ST_UNCHECKED(0, mkexpr(t2));
4048                put_ST_UNCHECKED(r_src, mkexpr(t1));
4049                break;
4050
4051             case 0xE0: /* FCHS */
4052                DIP("fchs\n");
4053                put_ST_UNCHECKED(0, unop(Iop_NegF64, get_ST(0)));
4054                break;
4055
4056             case 0xE1: /* FABS */
4057                DIP("fabs\n");
4058                put_ST_UNCHECKED(0, unop(Iop_AbsF64, get_ST(0)));
4059                break;
4060
4061             case 0xE4: /* FTST */
4062                DIP("ftst\n");
4063                /* This forces C1 to zero, which isn't right. */
4064                /* Well, in fact the Intel docs say (bizarrely): "C1 is
4065                   set to 0 if stack underflow occurred; otherwise, set
4066                   to 0" which is pretty nonsensical.  I guess it's a
4067                    typo. */
4068                put_C3210( 
4069                    binop( Iop_And32,
4070                           binop(Iop_Shl32, 
4071                                 binop(Iop_CmpF64, 
4072                                       get_ST(0),
4073                                       IRExpr_Const(IRConst_F64i(0x0ULL))),
4074                                 mkU8(8)),
4075                           mkU32(0x4500)
4076                    ));
4077                break;
4078
4079             case 0xE5: { /* FXAM */
4080                /* This is an interesting one.  It examines %st(0),
4081                   regardless of whether the tag says it's empty or not.
4082                   Here, just pass both the tag (in our format) and the
4083                   value (as a double, actually a ULong) to a helper
4084                   function. */
4085                IRExpr** args
4086                   = mkIRExprVec_2( unop(Iop_8Uto32, get_ST_TAG(0)),
4087                                    unop(Iop_ReinterpF64asI64, 
4088                                         get_ST_UNCHECKED(0)) );
4089                put_C3210(mkIRExprCCall(
4090                             Ity_I32, 
4091                             0/*regparm*/, 
4092                             "x86g_calculate_FXAM", &x86g_calculate_FXAM,
4093                             args
4094                         ));
4095                DIP("fxam\n");
4096                break;
4097             }
4098
4099             case 0xE8: /* FLD1 */
4100                DIP("fld1\n");
4101                fp_push();
4102                /* put_ST(0, IRExpr_Const(IRConst_F64(1.0))); */
4103                put_ST(0, IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)));
4104                break;
4105
4106             case 0xE9: /* FLDL2T */
4107                DIP("fldl2t\n");
4108                fp_push();
4109                /* put_ST(0, IRExpr_Const(IRConst_F64(3.32192809488736234781))); */
4110                put_ST(0, IRExpr_Const(IRConst_F64i(0x400a934f0979a371ULL)));
4111                break;
4112
4113             case 0xEA: /* FLDL2E */
4114                DIP("fldl2e\n");
4115                fp_push();
4116                /* put_ST(0, IRExpr_Const(IRConst_F64(1.44269504088896340739))); */
4117                put_ST(0, IRExpr_Const(IRConst_F64i(0x3ff71547652b82feULL)));
4118                break;
4119
4120             case 0xEB: /* FLDPI */
4121                DIP("fldpi\n");
4122                fp_push();
4123                /* put_ST(0, IRExpr_Const(IRConst_F64(3.14159265358979323851))); */
4124                put_ST(0, IRExpr_Const(IRConst_F64i(0x400921fb54442d18ULL)));
4125                break;
4126
4127             case 0xEC: /* FLDLG2 */
4128                DIP("fldlg2\n");
4129                fp_push();
4130                /* put_ST(0, IRExpr_Const(IRConst_F64(0.301029995663981143))); */
4131                put_ST(0, IRExpr_Const(IRConst_F64i(0x3fd34413509f79ffULL)));
4132                break;
4133
4134             case 0xED: /* FLDLN2 */
4135                DIP("fldln2\n");
4136                fp_push();
4137                /* put_ST(0, IRExpr_Const(IRConst_F64(0.69314718055994530942))); */
4138                put_ST(0, IRExpr_Const(IRConst_F64i(0x3fe62e42fefa39efULL)));
4139                break;
4140
4141             case 0xEE: /* FLDZ */
4142                DIP("fldz\n");
4143                fp_push();
4144                /* put_ST(0, IRExpr_Const(IRConst_F64(0.0))); */
4145                put_ST(0, IRExpr_Const(IRConst_F64i(0x0000000000000000ULL)));
4146                break;
4147
4148             case 0xF0: /* F2XM1 */
4149                DIP("f2xm1\n");
4150                put_ST_UNCHECKED(0, 
4151                   binop(Iop_2xm1F64, 
4152                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
4153                         get_ST(0)));
4154                break;
4155
4156             case 0xF1: /* FYL2X */
4157                DIP("fyl2x\n");
4158                put_ST_UNCHECKED(1, 
4159                   triop(Iop_Yl2xF64,
4160                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
4161                         get_ST(1), 
4162                         get_ST(0)));
4163                fp_pop();
4164                break;
4165
4166             case 0xF2: /* FPTAN */
4167                DIP("ftan\n");
4168                put_ST_UNCHECKED(0, 
4169                   binop(Iop_TanF64, 
4170                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
4171                         get_ST(0)));
4172                fp_push();
4173                put_ST(0, IRExpr_Const(IRConst_F64(1.0)));
4174                clear_C2(); /* HACK */
4175                break;
4176
4177             case 0xF3: /* FPATAN */
4178                DIP("fpatan\n");
4179                put_ST_UNCHECKED(1, 
4180                   triop(Iop_AtanF64,
4181                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
4182                         get_ST(1), 
4183                         get_ST(0)));
4184                fp_pop();
4185                break;
4186
4187             case 0xF4: { /* FXTRACT */
4188                IRTemp argF = newTemp(Ity_F64);
4189                IRTemp sigF = newTemp(Ity_F64);
4190                IRTemp expF = newTemp(Ity_F64);
4191                IRTemp argI = newTemp(Ity_I64);
4192                IRTemp sigI = newTemp(Ity_I64);
4193                IRTemp expI = newTemp(Ity_I64);
4194                DIP("fxtract\n");
4195                assign( argF, get_ST(0) );
4196                assign( argI, unop(Iop_ReinterpF64asI64, mkexpr(argF)));
4197                assign( sigI, 
4198                        mkIRExprCCall(
4199                           Ity_I64, 0/*regparms*/, 
4200                           "x86amd64g_calculate_FXTRACT", 
4201                           &x86amd64g_calculate_FXTRACT, 
4202                           mkIRExprVec_2( mkexpr(argI), 
4203                                          mkIRExpr_HWord(0)/*sig*/ )) 
4204                );
4205                assign( expI, 
4206                        mkIRExprCCall(
4207                           Ity_I64, 0/*regparms*/, 
4208                           "x86amd64g_calculate_FXTRACT", 
4209                           &x86amd64g_calculate_FXTRACT, 
4210                           mkIRExprVec_2( mkexpr(argI), 
4211                                          mkIRExpr_HWord(1)/*exp*/ )) 
4212                );
4213                assign( sigF, unop(Iop_ReinterpI64asF64, mkexpr(sigI)) );
4214                assign( expF, unop(Iop_ReinterpI64asF64, mkexpr(expI)) );
4215                /* exponent */
4216                put_ST_UNCHECKED(0, mkexpr(expF) );
4217                fp_push();
4218                /* significand */
4219                put_ST(0, mkexpr(sigF) );
4220                break;
4221             }
4222
4223             case 0xF5: { /* FPREM1 -- IEEE compliant */
4224                IRTemp a1 = newTemp(Ity_F64);
4225                IRTemp a2 = newTemp(Ity_F64);
4226                DIP("fprem1\n");
4227                /* Do FPREM1 twice, once to get the remainder, and once
4228                   to get the C3210 flag values. */
4229                assign( a1, get_ST(0) );
4230                assign( a2, get_ST(1) );
4231                put_ST_UNCHECKED(0, 
4232                   triop(Iop_PRem1F64,
4233                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
4234                         mkexpr(a1), 
4235                         mkexpr(a2)));
4236                put_C3210(
4237                   triop(Iop_PRem1C3210F64,
4238                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
4239                         mkexpr(a1), 
4240                         mkexpr(a2)) );
4241                break;
4242             }
4243
4244             case 0xF7: /* FINCSTP */
4245                DIP("fprem\n");
4246                put_ftop( binop(Iop_Add32, get_ftop(), mkU32(1)) );
4247                break;
4248
4249             case 0xF8: { /* FPREM -- not IEEE compliant */
4250                IRTemp a1 = newTemp(Ity_F64);
4251                IRTemp a2 = newTemp(Ity_F64);
4252                DIP("fprem\n");
4253                /* Do FPREM twice, once to get the remainder, and once
4254                   to get the C3210 flag values. */
4255                assign( a1, get_ST(0) );
4256                assign( a2, get_ST(1) );
4257                put_ST_UNCHECKED(0, 
4258                   triop(Iop_PRemF64,
4259                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
4260                         mkexpr(a1), 
4261                         mkexpr(a2)));
4262                put_C3210( 
4263                   triop(Iop_PRemC3210F64,
4264                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
4265                         mkexpr(a1), 
4266                         mkexpr(a2)) );
4267                break;
4268             }
4269
4270             case 0xF9: /* FYL2XP1 */
4271                DIP("fyl2xp1\n");
4272                put_ST_UNCHECKED(1, 
4273                   triop(Iop_Yl2xp1F64,
4274                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
4275                         get_ST(1), 
4276                         get_ST(0)));
4277                fp_pop();
4278                break;
4279
4280             case 0xFA: /* FSQRT */
4281                DIP("fsqrt\n");
4282                put_ST_UNCHECKED(0, 
4283                   binop(Iop_SqrtF64, 
4284                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
4285                         get_ST(0)));
4286                break;
4287
4288             case 0xFB: { /* FSINCOS */
4289                IRTemp a1 = newTemp(Ity_F64);
4290                assign( a1, get_ST(0) );
4291                DIP("fsincos\n");
4292                put_ST_UNCHECKED(0, 
4293                   binop(Iop_SinF64, 
4294                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
4295                         mkexpr(a1)));
4296                fp_push();
4297                put_ST(0, 
4298                   binop(Iop_CosF64,
4299                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
4300                         mkexpr(a1)));
4301                clear_C2(); /* HACK */
4302                break;
4303             }
4304
4305             case 0xFC: /* FRNDINT */
4306                DIP("frndint\n");
4307                put_ST_UNCHECKED(0,
4308                   binop(Iop_RoundF64toInt, get_roundingmode(), get_ST(0)) );
4309                break;
4310
4311             case 0xFD: /* FSCALE */
4312                DIP("fscale\n");
4313                put_ST_UNCHECKED(0, 
4314                   triop(Iop_ScaleF64,
4315                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
4316                         get_ST(0), 
4317                         get_ST(1)));
4318                break;
4319
4320             case 0xFE: /* FSIN */
4321                DIP("fsin\n");
4322                put_ST_UNCHECKED(0, 
4323                   binop(Iop_SinF64, 
4324                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
4325                         get_ST(0)));
4326                clear_C2(); /* HACK */
4327                break;
4328
4329             case 0xFF: /* FCOS */
4330                DIP("fcos\n");
4331                put_ST_UNCHECKED(0, 
4332                   binop(Iop_CosF64, 
4333                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
4334                         get_ST(0)));
4335                clear_C2(); /* HACK */
4336                break;
4337
4338             default:
4339                goto decode_fail;
4340          }
4341       }
4342    }
4343
4344    /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDA opcodes +-+-+-+-+-+-+-+ */
4345    else
4346    if (first_opcode == 0xDA) {
4347
4348       if (modrm < 0xC0) {
4349
4350          /* bits 5,4,3 are an opcode extension, and the modRM also
4351             specifies an address. */
4352          IROp   fop;
4353          IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
4354          delta += len;
4355          switch (gregOfRM(modrm)) {
4356
4357             case 0: /* FIADD m32int */ /* ST(0) += m32int */
4358                DIP("fiaddl %s\n", dis_buf);
4359                fop = Iop_AddF64;
4360                goto do_fop_m32;
4361
4362             case 1: /* FIMUL m32int */ /* ST(0) *= m32int */
4363                DIP("fimull %s\n", dis_buf);
4364                fop = Iop_MulF64;
4365                goto do_fop_m32;
4366
4367             case 2: /* FICOM m32int */
4368                DIP("ficoml %s\n", dis_buf);
4369                /* This forces C1 to zero, which isn't right. */
4370                put_C3210( 
4371                    binop( Iop_And32,
4372                           binop(Iop_Shl32, 
4373                                 binop(Iop_CmpF64, 
4374                                       get_ST(0),
4375                                       unop(Iop_I32StoF64, 
4376                                            loadLE(Ity_I32,mkexpr(addr)))),
4377                                 mkU8(8)),
4378                           mkU32(0x4500)
4379                    ));
4380                break;
4381
4382             case 3: /* FICOMP m32int */
4383                DIP("ficompl %s\n", dis_buf);
4384                /* This forces C1 to zero, which isn't right. */
4385                put_C3210( 
4386                    binop( Iop_And32,
4387                           binop(Iop_Shl32, 
4388                                 binop(Iop_CmpF64, 
4389                                       get_ST(0),
4390                                       unop(Iop_I32StoF64, 
4391                                            loadLE(Ity_I32,mkexpr(addr)))),
4392                                 mkU8(8)),
4393                           mkU32(0x4500)
4394                    ));
4395                fp_pop();
4396                break;
4397
4398             case 4: /* FISUB m32int */ /* ST(0) -= m32int */
4399                DIP("fisubl %s\n", dis_buf);
4400                fop = Iop_SubF64;
4401                goto do_fop_m32;
4402
4403             case 5: /* FISUBR m32int */ /* ST(0) = m32int - ST(0) */
4404                DIP("fisubrl %s\n", dis_buf);
4405                fop = Iop_SubF64;
4406                goto do_foprev_m32;
4407
4408             case 6: /* FIDIV m32int */ /* ST(0) /= m32int */
4409                DIP("fidivl %s\n", dis_buf);
4410                fop = Iop_DivF64;
4411                goto do_fop_m32;
4412
4413             case 7: /* FIDIVR m32int */ /* ST(0) = m32int / ST(0) */
4414                DIP("fidivrl %s\n", dis_buf);
4415                fop = Iop_DivF64;
4416                goto do_foprev_m32;
4417
4418             do_fop_m32:
4419                put_ST_UNCHECKED(0, 
4420                   triop(fop, 
4421                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
4422                         get_ST(0),
4423                         unop(Iop_I32StoF64,
4424                              loadLE(Ity_I32, mkexpr(addr)))));
4425                break;
4426
4427             do_foprev_m32:
4428                put_ST_UNCHECKED(0, 
4429                   triop(fop, 
4430                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
4431                         unop(Iop_I32StoF64,
4432                              loadLE(Ity_I32, mkexpr(addr))),
4433                         get_ST(0)));
4434                break;
4435
4436             default:
4437                vex_printf("unhandled opc_aux = 0x%2x\n", gregOfRM(modrm));
4438                vex_printf("first_opcode == 0xDA\n");
4439                goto decode_fail;
4440          }
4441
4442       } else {
4443
4444          delta++;
4445          switch (modrm) {
4446
4447             case 0xC0 ... 0xC7: /* FCMOVB ST(i), ST(0) */
4448                r_src = (UInt)modrm - 0xC0;
4449                DIP("fcmovb %%st(%d), %%st(0)\n", (Int)r_src);
4450                put_ST_UNCHECKED(0, 
4451                                 IRExpr_Mux0X( 
4452                                     unop(Iop_1Uto8,
4453                                          mk_x86g_calculate_condition(X86CondB)), 
4454                                     get_ST(0), get_ST(r_src)) );
4455                break;
4456
4457             case 0xC8 ... 0xCF: /* FCMOVE(Z) ST(i), ST(0) */
4458                r_src = (UInt)modrm - 0xC8;
4459                DIP("fcmovz %%st(%d), %%st(0)\n", (Int)r_src);
4460                put_ST_UNCHECKED(0, 
4461                                 IRExpr_Mux0X( 
4462                                     unop(Iop_1Uto8,
4463                                          mk_x86g_calculate_condition(X86CondZ)), 
4464                                     get_ST(0), get_ST(r_src)) );
4465                break;
4466
4467             case 0xD0 ... 0xD7: /* FCMOVBE ST(i), ST(0) */
4468                r_src = (UInt)modrm - 0xD0;
4469                DIP("fcmovbe %%st(%d), %%st(0)\n", (Int)r_src);
4470                put_ST_UNCHECKED(0, 
4471                                 IRExpr_Mux0X( 
4472                                     unop(Iop_1Uto8,
4473                                          mk_x86g_calculate_condition(X86CondBE)), 
4474                                     get_ST(0), get_ST(r_src)) );
4475                break;
4476
4477             case 0xD8 ... 0xDF: /* FCMOVU ST(i), ST(0) */
4478                r_src = (UInt)modrm - 0xD8;
4479                DIP("fcmovu %%st(%d), %%st(0)\n", (Int)r_src);
4480                put_ST_UNCHECKED(0, 
4481                                 IRExpr_Mux0X( 
4482                                     unop(Iop_1Uto8,
4483                                          mk_x86g_calculate_condition(X86CondP)), 
4484                                     get_ST(0), get_ST(r_src)) );
4485                break;
4486
4487             case 0xE9: /* FUCOMPP %st(0),%st(1) */
4488                DIP("fucompp %%st(0),%%st(1)\n");
4489                /* This forces C1 to zero, which isn't right. */
4490                put_C3210( 
4491                    binop( Iop_And32,
4492                           binop(Iop_Shl32, 
4493                                 binop(Iop_CmpF64, get_ST(0), get_ST(1)),
4494                                 mkU8(8)),
4495                           mkU32(0x4500)
4496                    ));
4497                fp_pop();
4498                fp_pop();
4499                break;
4500
4501             default:
4502                goto decode_fail;
4503          }
4504
4505       }
4506    }
4507
4508    /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDB opcodes +-+-+-+-+-+-+-+ */
4509    else
4510    if (first_opcode == 0xDB) {
4511       if (modrm < 0xC0) {
4512
4513          /* bits 5,4,3 are an opcode extension, and the modRM also
4514             specifies an address. */
4515          IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
4516          delta += len;
4517
4518          switch (gregOfRM(modrm)) {
4519
4520             case 0: /* FILD m32int */
4521                DIP("fildl %s\n", dis_buf);
4522                fp_push();
4523                put_ST(0, unop(Iop_I32StoF64,
4524                               loadLE(Ity_I32, mkexpr(addr))));
4525                break;
4526
4527             case 1: /* FISTTPL m32 (SSE3) */
4528                DIP("fisttpl %s\n", dis_buf);
4529                storeLE( mkexpr(addr), 
4530                         binop(Iop_F64toI32S, mkU32(Irrm_ZERO), get_ST(0)) );
4531                fp_pop();
4532                break;
4533
4534             case 2: /* FIST m32 */
4535                DIP("fistl %s\n", dis_buf);
4536                storeLE( mkexpr(addr), 
4537                         binop(Iop_F64toI32S, get_roundingmode(), get_ST(0)) );
4538                break;
4539
4540             case 3: /* FISTP m32 */
4541                DIP("fistpl %s\n", dis_buf);
4542                storeLE( mkexpr(addr), 
4543                         binop(Iop_F64toI32S, get_roundingmode(), get_ST(0)) );
4544                fp_pop();
4545                break;
4546
4547             case 5: { /* FLD extended-real */
4548                /* Uses dirty helper: 
4549                      ULong x86g_loadF80le ( UInt )
4550                   addr holds the address.  First, do a dirty call to
4551                   get hold of the data. */
4552                IRTemp   val  = newTemp(Ity_I64);
4553                IRExpr** args = mkIRExprVec_1 ( mkexpr(addr) );
4554
4555                IRDirty* d = unsafeIRDirty_1_N ( 
4556                                val, 
4557                                0/*regparms*/, 
4558                                "x86g_dirtyhelper_loadF80le", 
4559                                &x86g_dirtyhelper_loadF80le, 
4560                                args 
4561                             );
4562                /* declare that we're reading memory */
4563                d->mFx   = Ifx_Read;
4564                d->mAddr = mkexpr(addr);
4565                d->mSize = 10;
4566
4567                /* execute the dirty call, dumping the result in val. */
4568                stmt( IRStmt_Dirty(d) );
4569                fp_push();
4570                put_ST(0, unop(Iop_ReinterpI64asF64, mkexpr(val)));
4571
4572                DIP("fldt %s\n", dis_buf);
4573                break;
4574             }
4575
4576             case 7: { /* FSTP extended-real */
4577                /* Uses dirty helper: void x86g_storeF80le ( UInt, ULong ) */
4578                IRExpr** args 
4579                   = mkIRExprVec_2( mkexpr(addr), 
4580                                    unop(Iop_ReinterpF64asI64, get_ST(0)) );
4581
4582                IRDirty* d = unsafeIRDirty_0_N ( 
4583                                0/*regparms*/, 
4584                                "x86g_dirtyhelper_storeF80le", 
4585                                &x86g_dirtyhelper_storeF80le,
4586                                args 
4587                             );
4588                /* declare we're writing memory */
4589                d->mFx   = Ifx_Write;
4590                d->mAddr = mkexpr(addr);
4591                d->mSize = 10;
4592
4593                /* execute the dirty call. */
4594                stmt( IRStmt_Dirty(d) );
4595                fp_pop();
4596
4597                DIP("fstpt\n %s", dis_buf);
4598                break;
4599             }
4600
4601             default:
4602                vex_printf("unhandled opc_aux = 0x%2x\n", gregOfRM(modrm));
4603                vex_printf("first_opcode == 0xDB\n");
4604                goto decode_fail;
4605          }
4606
4607       } else {
4608
4609          delta++;
4610          switch (modrm) {
4611
4612             case 0xC0 ... 0xC7: /* FCMOVNB ST(i), ST(0) */
4613                r_src = (UInt)modrm - 0xC0;
4614                DIP("fcmovnb %%st(%d), %%st(0)\n", (Int)r_src);
4615                put_ST_UNCHECKED(0, 
4616                                 IRExpr_Mux0X( 
4617                                     unop(Iop_1Uto8,
4618                                          mk_x86g_calculate_condition(X86CondNB)), 
4619                                     get_ST(0), get_ST(r_src)) );
4620                break;
4621
4622             case 0xC8 ... 0xCF: /* FCMOVNE(NZ) ST(i), ST(0) */
4623                r_src = (UInt)modrm - 0xC8;
4624                DIP("fcmovnz %%st(%d), %%st(0)\n", (Int)r_src);
4625                put_ST_UNCHECKED(0, 
4626                                 IRExpr_Mux0X( 
4627                                     unop(Iop_1Uto8,
4628                                          mk_x86g_calculate_condition(X86CondNZ)), 
4629                                     get_ST(0), get_ST(r_src)) );
4630                break;
4631
4632             case 0xD0 ... 0xD7: /* FCMOVNBE ST(i), ST(0) */
4633                r_src = (UInt)modrm - 0xD0;
4634                DIP("fcmovnbe %%st(%d), %%st(0)\n", (Int)r_src);
4635                put_ST_UNCHECKED(0, 
4636                                 IRExpr_Mux0X( 
4637                                     unop(Iop_1Uto8,
4638                                          mk_x86g_calculate_condition(X86CondNBE)), 
4639                                     get_ST(0), get_ST(r_src)) );
4640                break;
4641
4642             case 0xD8 ... 0xDF: /* FCMOVNU ST(i), ST(0) */
4643                r_src = (UInt)modrm - 0xD8;
4644                DIP("fcmovnu %%st(%d), %%st(0)\n", (Int)r_src);
4645                put_ST_UNCHECKED(0, 
4646                                 IRExpr_Mux0X( 
4647                                     unop(Iop_1Uto8,
4648                                          mk_x86g_calculate_condition(X86CondNP)), 
4649                                     get_ST(0), get_ST(r_src)) );
4650                break;
4651
4652             case 0xE2:
4653                DIP("fnclex\n");
4654                break;
4655
4656             case 0xE3: {
4657                /* Uses dirty helper: 
4658                      void x86g_do_FINIT ( VexGuestX86State* ) */
4659                IRDirty* d  = unsafeIRDirty_0_N ( 
4660                                 0/*regparms*/, 
4661                                 "x86g_dirtyhelper_FINIT", 
4662                                 &x86g_dirtyhelper_FINIT,
4663                                 mkIRExprVec_0()
4664                              );
4665                d->needsBBP = True;
4666
4667                /* declare we're writing guest state */
4668                d->nFxState = 5;
4669
4670                d->fxState[0].fx     = Ifx_Write;
4671                d->fxState[0].offset = OFFB_FTOP;
4672                d->fxState[0].size   = sizeof(UInt);
4673
4674                d->fxState[1].fx     = Ifx_Write;
4675                d->fxState[1].offset = OFFB_FPREGS;
4676                d->fxState[1].size   = 8 * sizeof(ULong);
4677
4678                d->fxState[2].fx     = Ifx_Write;
4679                d->fxState[2].offset = OFFB_FPTAGS;
4680                d->fxState[2].size   = 8 * sizeof(UChar);
4681
4682                d->fxState[3].fx     = Ifx_Write;
4683                d->fxState[3].offset = OFFB_FPROUND;
4684                d->fxState[3].size   = sizeof(UInt);
4685
4686                d->fxState[4].fx     = Ifx_Write;
4687                d->fxState[4].offset = OFFB_FC3210;
4688                d->fxState[4].size   = sizeof(UInt);
4689
4690                stmt( IRStmt_Dirty(d) );
4691
4692                DIP("fninit\n");
4693                break;
4694             }
4695
4696             case 0xE8 ... 0xEF: /* FUCOMI %st(0),%st(?) */
4697                fp_do_ucomi_ST0_STi( (UInt)modrm - 0xE8, False );
4698                break;
4699
4700             case 0xF0 ... 0xF7: /* FCOMI %st(0),%st(?) */
4701                fp_do_ucomi_ST0_STi( (UInt)modrm - 0xF0, False );
4702                break;
4703
4704             default:
4705                goto decode_fail;
4706          }
4707       }
4708    }
4709
4710    /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDC opcodes +-+-+-+-+-+-+-+ */
4711    else
4712    if (first_opcode == 0xDC) {
4713       if (modrm < 0xC0) {
4714
4715          /* bits 5,4,3 are an opcode extension, and the modRM also
4716             specifies an address. */
4717          IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
4718          delta += len;
4719
4720          switch (gregOfRM(modrm)) {
4721
4722             case 0: /* FADD double-real */
4723                fp_do_op_mem_ST_0 ( addr, "add", dis_buf, Iop_AddF64, True );
4724                break;
4725
4726             case 1: /* FMUL double-real */
4727                fp_do_op_mem_ST_0 ( addr, "mul", dis_buf, Iop_MulF64, True );
4728                break;
4729
4730             case 2: /* FCOM double-real */
4731                DIP("fcoml %s\n", dis_buf);
4732                /* This forces C1 to zero, which isn't right. */
4733                put_C3210( 
4734                    binop( Iop_And32,
4735                           binop(Iop_Shl32, 
4736                                 binop(Iop_CmpF64, 
4737                                       get_ST(0),
4738                                       loadLE(Ity_F64,mkexpr(addr))),
4739                                 mkU8(8)),
4740                           mkU32(0x4500)
4741                    ));
4742                break;  
4743
4744             case 3: /* FCOMP double-real */
4745                DIP("fcompl %s\n", dis_buf);
4746                /* This forces C1 to zero, which isn't right. */
4747                put_C3210( 
4748                    binop( Iop_And32,
4749                           binop(Iop_Shl32, 
4750                                 binop(Iop_CmpF64, 
4751                                       get_ST(0),
4752                                       loadLE(Ity_F64,mkexpr(addr))),
4753                                 mkU8(8)),
4754                           mkU32(0x4500)
4755                    ));
4756                fp_pop();
4757                break;  
4758
4759             case 4: /* FSUB double-real */
4760                fp_do_op_mem_ST_0 ( addr, "sub", dis_buf, Iop_SubF64, True );
4761                break;
4762
4763             case 5: /* FSUBR double-real */
4764                fp_do_oprev_mem_ST_0 ( addr, "subr", dis_buf, Iop_SubF64, True );
4765                break;
4766
4767             case 6: /* FDIV double-real */
4768                fp_do_op_mem_ST_0 ( addr, "div", dis_buf, Iop_DivF64, True );
4769                break;
4770
4771             case 7: /* FDIVR double-real */
4772                fp_do_oprev_mem_ST_0 ( addr, "divr", dis_buf, Iop_DivF64, True );
4773                break;
4774
4775             default:
4776                vex_printf("unhandled opc_aux = 0x%2x\n", gregOfRM(modrm));
4777                vex_printf("first_opcode == 0xDC\n");
4778                goto decode_fail;
4779          }
4780
4781       } else {
4782
4783          delta++;
4784          switch (modrm) {
4785
4786             case 0xC0 ... 0xC7: /* FADD %st(0),%st(?) */
4787                fp_do_op_ST_ST ( "add", Iop_AddF64, 0, modrm - 0xC0, False );
4788                break;
4789
4790             case 0xC8 ... 0xCF: /* FMUL %st(0),%st(?) */
4791                fp_do_op_ST_ST ( "mul", Iop_MulF64, 0, modrm - 0xC8, False );
4792                break;
4793
4794             case 0xE0 ... 0xE7: /* FSUBR %st(0),%st(?) */
4795                fp_do_oprev_ST_ST ( "subr", Iop_SubF64, 0, modrm - 0xE0, False );
4796                break;
4797
4798             case 0xE8 ... 0xEF: /* FSUB %st(0),%st(?) */
4799                fp_do_op_ST_ST ( "sub", Iop_SubF64, 0, modrm - 0xE8, False );
4800                break;
4801
4802             case 0xF0 ... 0xF7: /* FDIVR %st(0),%st(?) */
4803                fp_do_oprev_ST_ST ( "divr", Iop_DivF64, 0, modrm - 0xF0, False );
4804                break;
4805
4806             case 0xF8 ... 0xFF: /* FDIV %st(0),%st(?) */
4807                fp_do_op_ST_ST ( "div", Iop_DivF64, 0, modrm - 0xF8, False );
4808                break;
4809
4810             default:
4811                goto decode_fail;
4812          }
4813
4814       }
4815    }
4816
4817    /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDD opcodes +-+-+-+-+-+-+-+ */
4818    else
4819    if (first_opcode == 0xDD) {
4820
4821       if (modrm < 0xC0) {
4822
4823          /* bits 5,4,3 are an opcode extension, and the modRM also
4824             specifies an address. */
4825          IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
4826          delta += len;
4827
4828          switch (gregOfRM(modrm)) {
4829
4830             case 0: /* FLD double-real */
4831                DIP("fldl %s\n", dis_buf);
4832                fp_push();
4833                put_ST(0, loadLE(Ity_F64, mkexpr(addr)));
4834                break;
4835
4836             case 1: /* FISTTPQ m64 (SSE3) */
4837                DIP("fistppll %s\n", dis_buf);
4838                storeLE( mkexpr(addr), 
4839                         binop(Iop_F64toI64S, mkU32(Irrm_ZERO), get_ST(0)) );
4840                fp_pop();
4841                break;
4842
4843             case 2: /* FST double-real */
4844                DIP("fstl %s\n", dis_buf);
4845                storeLE(mkexpr(addr), get_ST(0));
4846                break;
4847
4848             case 3: /* FSTP double-real */
4849                DIP("fstpl %s\n", dis_buf);
4850                storeLE(mkexpr(addr), get_ST(0));
4851                fp_pop();
4852                break;
4853
4854             case 4: { /* FRSTOR m108 */
4855                /* Uses dirty helper: 
4856                      VexEmWarn x86g_do_FRSTOR ( VexGuestX86State*, Addr32 ) */
4857                IRTemp   ew = newTemp(Ity_I32);
4858                IRDirty* d  = unsafeIRDirty_0_N ( 
4859                                 0/*regparms*/, 
4860                                 "x86g_dirtyhelper_FRSTOR", 
4861                                 &x86g_dirtyhelper_FRSTOR,
4862                                 mkIRExprVec_1( mkexpr(addr) )
4863                              );
4864                d->needsBBP = True;
4865                d->tmp      = ew;
4866                /* declare we're reading memory */
4867                d->mFx   = Ifx_Read;
4868                d->mAddr = mkexpr(addr);
4869                d->mSize = 108;
4870
4871                /* declare we're writing guest state */
4872                d->nFxState = 5;
4873
4874                d->fxState[0].fx     = Ifx_Write;
4875                d->fxState[0].offset = OFFB_FTOP;
4876                d->fxState[0].size   = sizeof(UInt);
4877
4878                d->fxState[1].fx     = Ifx_Write;
4879                d->fxState[1].offset = OFFB_FPREGS;
4880                d->fxState[1].size   = 8 * sizeof(ULong);
4881
4882                d->fxState[2].fx     = Ifx_Write;
4883                d->fxState[2].offset = OFFB_FPTAGS;
4884                d->fxState[2].size   = 8 * sizeof(UChar);
4885
4886                d->fxState[3].fx     = Ifx_Write;
4887                d->fxState[3].offset = OFFB_FPROUND;
4888                d->fxState[3].size   = sizeof(UInt);
4889
4890                d->fxState[4].fx     = Ifx_Write;
4891                d->fxState[4].offset = OFFB_FC3210;
4892                d->fxState[4].size   = sizeof(UInt);
4893
4894                stmt( IRStmt_Dirty(d) );
4895
4896                /* ew contains any emulation warning we may need to
4897                   issue.  If needed, side-exit to the next insn,
4898                   reporting the warning, so that Valgrind's dispatcher
4899                   sees the warning. */
4900                put_emwarn( mkexpr(ew) );
4901                stmt( 
4902                   IRStmt_Exit(
4903                      binop(Iop_CmpNE32, mkexpr(ew), mkU32(0)),
4904                      Ijk_EmWarn,
4905                      IRConst_U32( ((Addr32)guest_EIP_bbstart)+delta)
4906                   )
4907                );
4908
4909                DIP("frstor %s\n", dis_buf);
4910                break;
4911             }
4912
4913             case 6: { /* FNSAVE m108 */
4914                /* Uses dirty helper: 
4915                      void x86g_do_FSAVE ( VexGuestX86State*, UInt ) */
4916                IRDirty* d = unsafeIRDirty_0_N ( 
4917                                0/*regparms*/, 
4918                                "x86g_dirtyhelper_FSAVE", 
4919                                &x86g_dirtyhelper_FSAVE,
4920                                mkIRExprVec_1( mkexpr(addr) )
4921                             );
4922                d->needsBBP = True;
4923                /* declare we're writing memory */
4924                d->mFx   = Ifx_Write;
4925                d->mAddr = mkexpr(addr);
4926                d->mSize = 108;
4927
4928                /* declare we're reading guest state */
4929                d->nFxState = 5;
4930
4931                d->fxState[0].fx     = Ifx_Read;
4932                d->fxState[0].offset = OFFB_FTOP;
4933                d->fxState[0].size   = sizeof(UInt);
4934
4935                d->fxState[1].fx     = Ifx_Read;
4936                d->fxState[1].offset = OFFB_FPREGS;
4937                d->fxState[1].size   = 8 * sizeof(ULong);
4938
4939                d->fxState[2].fx     = Ifx_Read;
4940                d->fxState[2].offset = OFFB_FPTAGS;
4941                d->fxState[2].size   = 8 * sizeof(UChar);
4942
4943                d->fxState[3].fx     = Ifx_Read;
4944                d->fxState[3].offset = OFFB_FPROUND;
4945                d->fxState[3].size   = sizeof(UInt);
4946
4947                d->fxState[4].fx     = Ifx_Read;
4948                d->fxState[4].offset = OFFB_FC3210;
4949                d->fxState[4].size   = sizeof(UInt);
4950
4951                stmt( IRStmt_Dirty(d) );
4952
4953                DIP("fnsave %s\n", dis_buf);
4954                break;
4955             }
4956
4957             case 7: { /* FNSTSW m16 */
4958                IRExpr* sw = get_FPU_sw();
4959                vassert(typeOfIRExpr(irsb->tyenv, sw) == Ity_I16);
4960                storeLE( mkexpr(addr), sw );
4961                DIP("fnstsw %s\n", dis_buf);
4962                break;
4963             }
4964
4965             default:
4966                vex_printf("unhandled opc_aux = 0x%2x\n", gregOfRM(modrm));
4967                vex_printf("first_opcode == 0xDD\n");
4968                goto decode_fail;
4969          }
4970       } else {
4971          delta++;
4972          switch (modrm) {
4973
4974             case 0xC0 ... 0xC7: /* FFREE %st(?) */
4975                r_dst = (UInt)modrm - 0xC0;
4976                DIP("ffree %%st(%d)\n", (Int)r_dst);
4977                put_ST_TAG ( r_dst, mkU8(0) );
4978                break;
4979
4980             case 0xD0 ... 0xD7: /* FST %st(0),%st(?) */
4981                r_dst = (UInt)modrm - 0xD0;
4982                DIP("fst %%st(0),%%st(%d)\n", (Int)r_dst);
4983                /* P4 manual says: "If the destination operand is a
4984                   non-empty register, the invalid-operation exception
4985                   is not generated.  Hence put_ST_UNCHECKED. */
4986                put_ST_UNCHECKED(r_dst, get_ST(0));
4987                break;
4988
4989             case 0xD8 ... 0xDF: /* FSTP %st(0),%st(?) */
4990                r_dst = (UInt)modrm - 0xD8;
4991                DIP("fstp %%st(0),%%st(%d)\n", (Int)r_dst);
4992                /* P4 manual says: "If the destination operand is a
4993                   non-empty register, the invalid-operation exception
4994                   is not generated.  Hence put_ST_UNCHECKED. */
4995                put_ST_UNCHECKED(r_dst, get_ST(0));
4996                fp_pop();
4997                break;
4998
4999             case 0xE0 ... 0xE7: /* FUCOM %st(0),%st(?) */
5000                r_dst = (UInt)modrm - 0xE0;
5001                DIP("fucom %%st(0),%%st(%d)\n", (Int)r_dst);
5002                /* This forces C1 to zero, which isn't right. */
5003                put_C3210( 
5004                    binop( Iop_And32,
5005                           binop(Iop_Shl32, 
5006                                 binop(Iop_CmpF64, get_ST(0), get_ST(r_dst)),
5007                                 mkU8(8)),
5008                           mkU32(0x4500)
5009                    ));
5010                break;
5011
5012             case 0xE8 ... 0xEF: /* FUCOMP %st(0),%st(?) */
5013                r_dst = (UInt)modrm - 0xE8;
5014                DIP("fucomp %%st(0),%%st(%d)\n", (Int)r_dst);
5015                /* This forces C1 to zero, which isn't right. */
5016                put_C3210( 
5017                    binop( Iop_And32,
5018                           binop(Iop_Shl32, 
5019                                 binop(Iop_CmpF64, get_ST(0), get_ST(r_dst)),
5020                                 mkU8(8)),
5021                           mkU32(0x4500)
5022                    ));
5023                fp_pop();
5024                break;
5025
5026             default:
5027                goto decode_fail;
5028          }
5029       }
5030    }
5031
5032    /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDE opcodes +-+-+-+-+-+-+-+ */
5033    else
5034    if (first_opcode == 0xDE) {
5035
5036       if (modrm < 0xC0) {
5037
5038          /* bits 5,4,3 are an opcode extension, and the modRM also
5039             specifies an address. */
5040          IROp   fop;
5041          IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
5042          delta += len;
5043
5044          switch (gregOfRM(modrm)) {
5045
5046             case 0: /* FIADD m16int */ /* ST(0) += m16int */
5047                DIP("fiaddw %s\n", dis_buf);
5048                fop = Iop_AddF64;
5049                goto do_fop_m16;
5050
5051             case 1: /* FIMUL m16int */ /* ST(0) *= m16int */
5052                DIP("fimulw %s\n", dis_buf);
5053                fop = Iop_MulF64;
5054                goto do_fop_m16;
5055
5056             case 2: /* FICOM m16int */
5057                DIP("ficomw %s\n", dis_buf);
5058                /* This forces C1 to zero, which isn't right. */
5059                put_C3210( 
5060                    binop( Iop_And32,
5061                           binop(Iop_Shl32, 
5062                                 binop(Iop_CmpF64, 
5063                                       get_ST(0),
5064                                       unop(Iop_I32StoF64, 
5065                                          unop(Iop_16Sto32,
5066                                            loadLE(Ity_I16,mkexpr(addr))))),
5067                                 mkU8(8)),
5068                           mkU32(0x4500)
5069                    ));
5070                break;
5071
5072             case 3: /* FICOMP m16int */
5073                DIP("ficompw %s\n", dis_buf);
5074                /* This forces C1 to zero, which isn't right. */
5075                put_C3210( 
5076                    binop( Iop_And32,
5077                           binop(Iop_Shl32, 
5078                                 binop(Iop_CmpF64, 
5079                                       get_ST(0),
5080                                       unop(Iop_I32StoF64, 
5081                                          unop(Iop_16Sto32,
5082                                               loadLE(Ity_I16,mkexpr(addr))))),
5083                                 mkU8(8)),
5084                           mkU32(0x4500)
5085                    ));
5086                fp_pop();
5087                break;
5088
5089             case 4: /* FISUB m16int */ /* ST(0) -= m16int */
5090                DIP("fisubw %s\n", dis_buf);
5091                fop = Iop_SubF64;
5092                goto do_fop_m16;
5093
5094             case 5: /* FISUBR m16int */ /* ST(0) = m16int - ST(0) */
5095                DIP("fisubrw %s\n", dis_buf);
5096                fop = Iop_SubF64;
5097                goto do_foprev_m16;
5098
5099             case 6: /* FIDIV m16int */ /* ST(0) /= m16int */
5100                DIP("fisubw %s\n", dis_buf);
5101                fop = Iop_DivF64;
5102                goto do_fop_m16;
5103
5104             case 7: /* FIDIVR m16int */ /* ST(0) = m16int / ST(0) */
5105                DIP("fidivrw %s\n", dis_buf);
5106                fop = Iop_DivF64;
5107                goto do_foprev_m16;
5108
5109             do_fop_m16:
5110                put_ST_UNCHECKED(0, 
5111                   triop(fop, 
5112                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
5113                         get_ST(0),
5114                         unop(Iop_I32StoF64,
5115                              unop(Iop_16Sto32, 
5116                                   loadLE(Ity_I16, mkexpr(addr))))));
5117                break;
5118
5119             do_foprev_m16:
5120                put_ST_UNCHECKED(0, 
5121                   triop(fop, 
5122                         get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
5123                         unop(Iop_I32StoF64,
5124                              unop(Iop_16Sto32, 
5125                                   loadLE(Ity_I16, mkexpr(addr)))),
5126                         get_ST(0)));
5127                break;
5128
5129             default:
5130                vex_printf("unhandled opc_aux = 0x%2x\n", gregOfRM(modrm));
5131                vex_printf("first_opcode == 0xDE\n");
5132                goto decode_fail;
5133          }
5134
5135       } else {
5136
5137          delta++;
5138          switch (modrm) {
5139
5140             case 0xC0 ... 0xC7: /* FADDP %st(0),%st(?) */
5141                fp_do_op_ST_ST ( "add", Iop_AddF64, 0, modrm - 0xC0, True );
5142                break;
5143
5144             case 0xC8 ... 0xCF: /* FMULP %st(0),%st(?) */
5145                fp_do_op_ST_ST ( "mul", Iop_MulF64, 0, modrm - 0xC8, True );
5146                break;
5147
5148             case 0xD9: /* FCOMPP %st(0),%st(1) */
5149                DIP("fuompp %%st(0),%%st(1)\n");
5150                /* This forces C1 to zero, which isn't right. */
5151                put_C3210( 
5152                    binop( Iop_And32,
5153                           binop(Iop_Shl32, 
5154                                 binop(Iop_CmpF64, get_ST(0), get_ST(1)),
5155                                 mkU8(8)),
5156                           mkU32(0x4500)
5157                    ));
5158                fp_pop();
5159                fp_pop();
5160                break;
5161
5162             case 0xE0 ... 0xE7: /* FSUBRP %st(0),%st(?) */
5163                fp_do_oprev_ST_ST ( "subr", Iop_SubF64, 0,  modrm - 0xE0, True );
5164                break;
5165
5166             case 0xE8 ... 0xEF: /* FSUBP %st(0),%st(?) */
5167                fp_do_op_ST_ST ( "sub", Iop_SubF64, 0,  modrm - 0xE8, True );
5168                break;
5169
5170             case 0xF0 ... 0xF7: /* FDIVRP %st(0),%st(?) */
5171                fp_do_oprev_ST_ST ( "divr", Iop_DivF64, 0, modrm - 0xF0, True );
5172                break;
5173
5174             case 0xF8 ... 0xFF: /* FDIVP %st(0),%st(?) */
5175                fp_do_op_ST_ST ( "div", Iop_DivF64, 0, modrm - 0xF8, True );
5176                break;
5177
5178             default: 
5179                goto decode_fail;
5180          }
5181
5182       }
5183    }
5184
5185    /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDF opcodes +-+-+-+-+-+-+-+ */
5186    else
5187    if (first_opcode == 0xDF) {
5188
5189       if (modrm < 0xC0) {
5190
5191          /* bits 5,4,3 are an opcode extension, and the modRM also
5192             specifies an address. */
5193          IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
5194          delta += len;
5195
5196          switch (gregOfRM(modrm)) {
5197
5198             case 0: /* FILD m16int */
5199                DIP("fildw %s\n", dis_buf);
5200                fp_push();
5201                put_ST(0, unop(Iop_I32StoF64,
5202                               unop(Iop_16Sto32,
5203                                    loadLE(Ity_I16, mkexpr(addr)))));
5204                break;
5205
5206             case 1: /* FISTTPS m16 (SSE3) */
5207                DIP("fisttps %s\n", dis_buf);
5208                storeLE( mkexpr(addr), 
5209                         binop(Iop_F64toI16S, mkU32(Irrm_ZERO), get_ST(0)) );
5210                fp_pop();
5211                break;
5212
5213             case 2: /* FIST m16 */
5214                DIP("fistp %s\n", dis_buf);
5215                storeLE( mkexpr(addr), 
5216                         binop(Iop_F64toI16S, get_roundingmode(), get_ST(0)) );
5217                break;
5218
5219             case 3: /* FISTP m16 */
5220                DIP("fistps %s\n", dis_buf);
5221                storeLE( mkexpr(addr), 
5222                         binop(Iop_F64toI16S, get_roundingmode(), get_ST(0)) );
5223                fp_pop();
5224                break;
5225
5226             case 5: /* FILD m64 */
5227                DIP("fildll %s\n", dis_buf);
5228                fp_push();
5229                put_ST(0, binop(Iop_I64StoF64,
5230                                get_roundingmode(),
5231                                loadLE(Ity_I64, mkexpr(addr))));
5232                break;
5233
5234             case 7: /* FISTP m64 */
5235                DIP("fistpll %s\n", dis_buf);
5236                storeLE( mkexpr(addr), 
5237                         binop(Iop_F64toI64S, get_roundingmode(), get_ST(0)) );
5238                fp_pop();
5239                break;
5240
5241             default:
5242                vex_printf("unhandled opc_aux = 0x%2x\n", gregOfRM(modrm));
5243                vex_printf("first_opcode == 0xDF\n");
5244                goto decode_fail;
5245          }
5246
5247       } else {
5248
5249          delta++;
5250          switch (modrm) {
5251
5252             case 0xC0: /* FFREEP %st(0) */
5253                DIP("ffreep %%st(%d)\n", 0);
5254                put_ST_TAG ( 0, mkU8(0) );
5255                fp_pop();
5256                break;
5257
5258             case 0xE0: /* FNSTSW %ax */
5259                DIP("fnstsw %%ax\n");
5260                /* Get the FPU status word value and dump it in %AX. */
5261                if (0) {
5262                   /* The obvious thing to do is simply dump the 16-bit
5263                      status word value in %AX.  However, due to a
5264                      limitation in Memcheck's origin tracking
5265                      machinery, this causes Memcheck not to track the
5266                      origin of any undefinedness into %AH (only into
5267                      %AL/%AX/%EAX), which means origins are lost in
5268                      the sequence "fnstsw %ax; test $M,%ah; jcond .." */
5269                   putIReg(2, R_EAX, get_FPU_sw());
5270                } else {
5271                   /* So a somewhat lame kludge is to make it very
5272                      clear to Memcheck that the value is written to
5273                      both %AH and %AL.  This generates marginally
5274                      worse code, but I don't think it matters much. */
5275                   IRTemp t16 = newTemp(Ity_I16);
5276                   assign(t16, get_FPU_sw());
5277                   putIReg( 1, R_AL, unop(Iop_16to8, mkexpr(t16)) );
5278                   putIReg( 1, R_AH, unop(Iop_16HIto8, mkexpr(t16)) );
5279                }
5280                break;
5281
5282             case 0xE8 ... 0xEF: /* FUCOMIP %st(0),%st(?) */
5283                fp_do_ucomi_ST0_STi( (UInt)modrm - 0xE8, True );
5284                break;
5285
5286             case 0xF0 ... 0xF7: /* FCOMIP %st(0),%st(?) */
5287                /* not really right since COMIP != UCOMIP */
5288                fp_do_ucomi_ST0_STi( (UInt)modrm - 0xF0, True );
5289                break;
5290
5291             default: 
5292                goto decode_fail;
5293          }
5294       }
5295
5296    }
5297
5298    else
5299    vpanic("dis_FPU(x86): invalid primary opcode");
5300
5301    *decode_ok = True;
5302    return delta;
5303
5304   decode_fail:
5305    *decode_ok = False;
5306    return delta;
5307 }
5308
5309
5310 /*------------------------------------------------------------*/
5311 /*---                                                      ---*/
5312 /*--- MMX INSTRUCTIONS                                     ---*/
5313 /*---                                                      ---*/
5314 /*------------------------------------------------------------*/
5315
5316 /* Effect of MMX insns on x87 FPU state (table 11-2 of 
5317    IA32 arch manual, volume 3):
5318
5319    Read from, or write to MMX register (viz, any insn except EMMS):
5320    * All tags set to Valid (non-empty) -- FPTAGS[i] := nonzero
5321    * FP stack pointer set to zero
5322
5323    EMMS:
5324    * All tags set to Invalid (empty) -- FPTAGS[i] := zero
5325    * FP stack pointer set to zero
5326 */
5327
5328 static void do_MMX_preamble ( void )
5329 {
5330    Int         i;
5331    IRRegArray* descr = mkIRRegArray( OFFB_FPTAGS, Ity_I8, 8 );
5332    IRExpr*     zero  = mkU32(0);
5333    IRExpr*     tag1  = mkU8(1);
5334    put_ftop(zero);
5335    for (i = 0; i < 8; i++)
5336       stmt( IRStmt_PutI( descr, zero, i, tag1 ) );
5337 }
5338
5339 static void do_EMMS_preamble ( void )
5340 {
5341    Int         i;
5342    IRRegArray* descr = mkIRRegArray( OFFB_FPTAGS, Ity_I8, 8 );
5343    IRExpr*     zero  = mkU32(0);
5344    IRExpr*     tag0  = mkU8(0);
5345    put_ftop(zero);
5346    for (i = 0; i < 8; i++)
5347       stmt( IRStmt_PutI( descr, zero, i, tag0 ) );
5348 }
5349
5350
5351 static IRExpr* getMMXReg ( UInt archreg )
5352 {
5353    vassert(archreg < 8);
5354    return IRExpr_Get( OFFB_FPREGS + 8 * archreg, Ity_I64 );
5355 }
5356
5357
5358 static void putMMXReg ( UInt archreg, IRExpr* e )
5359 {
5360    vassert(archreg < 8);
5361    vassert(typeOfIRExpr(irsb->tyenv,e) == Ity_I64);
5362    stmt( IRStmt_Put( OFFB_FPREGS + 8 * archreg, e ) );
5363 }
5364
5365
5366 /* Helper for non-shift MMX insns.  Note this is incomplete in the
5367    sense that it does not first call do_MMX_preamble() -- that is the
5368    responsibility of its caller. */
5369
5370 static 
5371 UInt dis_MMXop_regmem_to_reg ( UChar  sorb,
5372                                Int    delta,
5373                                UChar  opc,
5374                                HChar* name,
5375                                Bool   show_granularity )
5376 {
5377    HChar   dis_buf[50];
5378    UChar   modrm = getIByte(delta);
5379    Bool    isReg = epartIsReg(modrm);
5380    IRExpr* argL  = NULL;
5381    IRExpr* argR  = NULL;
5382    IRExpr* argG  = NULL;
5383    IRExpr* argE  = NULL;
5384    IRTemp  res   = newTemp(Ity_I64);
5385
5386    Bool    invG  = False;
5387    IROp    op    = Iop_INVALID;
5388    void*   hAddr = NULL;
5389    HChar*  hName = NULL;
5390    Bool    eLeft = False;
5391
5392 #  define XXX(_name) do { hAddr = &_name; hName = #_name; } while (0)
5393
5394    switch (opc) {
5395       /* Original MMX ones */
5396       case 0xFC: op = Iop_Add8x8; break;
5397       case 0xFD: op = Iop_Add16x4; break;
5398       case 0xFE: op = Iop_Add32x2; break;
5399
5400       case 0xEC: op = Iop_QAdd8Sx8; break;
5401       case 0xED: op = Iop_QAdd16Sx4; break;
5402
5403       case 0xDC: op = Iop_QAdd8Ux8; break;
5404       case 0xDD: op = Iop_QAdd16Ux4; break;
5405
5406       case 0xF8: op = Iop_Sub8x8;  break;
5407       case 0xF9: op = Iop_Sub16x4; break;
5408       case 0xFA: op = Iop_Sub32x2; break;
5409
5410       case 0xE8: op = Iop_QSub8Sx8; break;
5411       case 0xE9: op = Iop_QSub16Sx4; break;
5412
5413       case 0xD8: op = Iop_QSub8Ux8; break;
5414       case 0xD9: op = Iop_QSub16Ux4; break;
5415
5416       case 0xE5: op = Iop_MulHi16Sx4; break;
5417       case 0xD5: op = Iop_Mul16x4; break;
5418       case 0xF5: XXX(x86g_calculate_mmx_pmaddwd); break;
5419
5420       case 0x74: op = Iop_CmpEQ8x8; break;
5421       case 0x75: op = Iop_CmpEQ16x4; break;
5422       case 0x76: op = Iop_CmpEQ32x2; break;
5423
5424       case 0x64: op = Iop_CmpGT8Sx8; break;
5425       case 0x65: op = Iop_CmpGT16Sx4; break;
5426       case 0x66: op = Iop_CmpGT32Sx2; break;
5427
5428       case 0x6B: op = Iop_QNarrow32Sx2; eLeft = True; break;
5429       case 0x63: op = Iop_QNarrow16Sx4; eLeft = True; break;
5430       case 0x67: op = Iop_QNarrow16Ux4; eLeft = True; break;
5431
5432       case 0x68: op = Iop_InterleaveHI8x8;  eLeft = True; break;
5433       case 0x69: op = Iop_InterleaveHI16x4; eLeft = True; break;
5434       case 0x6A: op = Iop_InterleaveHI32x2; eLeft = True; break;
5435
5436       case 0x60: op = Iop_InterleaveLO8x8;  eLeft = True; break;
5437       case 0x61: op = Iop_InterleaveLO16x4; eLeft = True; break;
5438       case 0x62: op = Iop_InterleaveLO32x2; eLeft = True; break;
5439
5440       case 0xDB: op = Iop_And64; break;
5441       case 0xDF: op = Iop_And64; invG = True; break;
5442       case 0xEB: op = Iop_Or64; break;
5443       case 0xEF: /* Possibly do better here if argL and argR are the
5444                     same reg */
5445                  op = Iop_Xor64; break;
5446
5447       /* Introduced in SSE1 */
5448       case 0xE0: op = Iop_Avg8Ux8;    break;
5449       case 0xE3: op = Iop_Avg16Ux4;   break;
5450       case 0xEE: op = Iop_Max16Sx4;   break;
5451       case 0xDE: op = Iop_Max8Ux8;    break;
5452       case 0xEA: op = Iop_Min16Sx4;   break;
5453       case 0xDA: op = Iop_Min8Ux8;    break;
5454       case 0xE4: op = Iop_MulHi16Ux4; break;
5455       case 0xF6: XXX(x86g_calculate_mmx_psadbw); break;
5456
5457       /* Introduced in SSE2 */
5458       case 0xD4: op = Iop_Add64; break;
5459       case 0xFB: op = Iop_Sub64; break;
5460
5461       default: 
5462          vex_printf("\n0x%x\n", (Int)opc);
5463          vpanic("dis_MMXop_regmem_to_reg");
5464    }
5465
5466 #  undef XXX
5467
5468    argG = getMMXReg(gregOfRM(modrm));
5469    if (invG)
5470       argG = unop(Iop_Not64, argG);
5471
5472    if (isReg) {
5473       delta++;
5474       argE = getMMXReg(eregOfRM(modrm));
5475    } else {
5476       Int    len;
5477       IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
5478       delta += len;
5479       argE = loadLE(Ity_I64, mkexpr(addr));
5480    }
5481
5482    if (eLeft) {
5483       argL = argE;
5484       argR = argG;
5485    } else {
5486       argL = argG;
5487       argR = argE;
5488    }
5489
5490    if (op != Iop_INVALID) {
5491       vassert(hName == NULL);
5492       vassert(hAddr == NULL);
5493       assign(res, binop(op, argL, argR));
5494    } else {
5495       vassert(hName != NULL);
5496       vassert(hAddr != NULL);
5497       assign( res, 
5498               mkIRExprCCall(
5499                  Ity_I64, 
5500                  0/*regparms*/, hName, hAddr,
5501                  mkIRExprVec_2( argL, argR )
5502               ) 
5503             );
5504    }
5505
5506    putMMXReg( gregOfRM(modrm), mkexpr(res) );
5507
5508    DIP("%s%s %s, %s\n", 
5509        name, show_granularity ? nameMMXGran(opc & 3) : "",
5510        ( isReg ? nameMMXReg(eregOfRM(modrm)) : dis_buf ),
5511        nameMMXReg(gregOfRM(modrm)) );
5512
5513    return delta;
5514 }
5515
5516
5517 /* Vector by scalar shift of G by the amount specified at the bottom
5518    of E.  This is a straight copy of dis_SSE_shiftG_byE. */
5519
5520 static UInt dis_MMX_shiftG_byE ( UChar sorb, Int delta, 
5521                                  HChar* opname, IROp op )
5522 {
5523    HChar   dis_buf[50];
5524    Int     alen, size;
5525    IRTemp  addr;
5526    Bool    shl, shr, sar;
5527    UChar   rm   = getIByte(delta);
5528    IRTemp  g0   = newTemp(Ity_I64);
5529    IRTemp  g1   = newTemp(Ity_I64);
5530    IRTemp  amt  = newTemp(Ity_I32);
5531    IRTemp  amt8 = newTemp(Ity_I8);
5532
5533    if (epartIsReg(rm)) {
5534       assign( amt, unop(Iop_64to32, getMMXReg(eregOfRM(rm))) );
5535       DIP("%s %s,%s\n", opname,
5536                         nameMMXReg(eregOfRM(rm)),
5537                         nameMMXReg(gregOfRM(rm)) );
5538       delta++;
5539    } else {
5540       addr = disAMode ( &alen, sorb, delta, dis_buf );
5541       assign( amt, loadLE(Ity_I32, mkexpr(addr)) );
5542       DIP("%s %s,%s\n", opname,
5543                         dis_buf,
5544                         nameMMXReg(gregOfRM(rm)) );
5545       delta += alen;
5546    }
5547    assign( g0,   getMMXReg(gregOfRM(rm)) );
5548    assign( amt8, unop(Iop_32to8, mkexpr(amt)) );
5549
5550    shl = shr = sar = False;
5551    size = 0;
5552    switch (op) {
5553       case Iop_ShlN16x4: shl = True; size = 32; break;
5554       case Iop_ShlN32x2: shl = True; size = 32; break;
5555       case Iop_Shl64:    shl = True; size = 64; break;
5556       case Iop_ShrN16x4: shr = True; size = 16; break;
5557       case Iop_ShrN32x2: shr = True; size = 32; break;
5558       case Iop_Shr64:    shr = True; size = 64; break;
5559       case Iop_SarN16x4: sar = True; size = 16; break;
5560       case Iop_SarN32x2: sar = True; size = 32; break;
5561       default: vassert(0);
5562    }
5563
5564    if (shl || shr) {
5565      assign( 
5566         g1,
5567         IRExpr_Mux0X(
5568            unop(Iop_1Uto8,binop(Iop_CmpLT32U,mkexpr(amt),mkU32(size))),
5569            mkU64(0),
5570            binop(op, mkexpr(g0), mkexpr(amt8))
5571         )
5572      );
5573    } else 
5574    if (sar) {
5575      assign( 
5576         g1,
5577         IRExpr_Mux0X(
5578            unop(Iop_1Uto8,binop(Iop_CmpLT32U,mkexpr(amt),mkU32(size))),
5579            binop(op, mkexpr(g0), mkU8(size-1)),
5580            binop(op, mkexpr(g0), mkexpr(amt8))
5581         )
5582      );
5583    } else {
5584       /*NOTREACHED*/
5585       vassert(0);
5586    }
5587
5588    putMMXReg( gregOfRM(rm), mkexpr(g1) );
5589    return delta;
5590 }
5591
5592
5593 /* Vector by scalar shift of E by an immediate byte.  This is a
5594    straight copy of dis_SSE_shiftE_imm. */
5595
5596 static 
5597 UInt dis_MMX_shiftE_imm ( Int delta, HChar* opname, IROp op )
5598 {
5599    Bool    shl, shr, sar;
5600    UChar   rm   = getIByte(delta);
5601    IRTemp  e0   = newTemp(Ity_I64);
5602    IRTemp  e1   = newTemp(Ity_I64);
5603    UChar   amt, size;
5604    vassert(epartIsReg(rm));
5605    vassert(gregOfRM(rm) == 2 
5606            || gregOfRM(rm) == 4 || gregOfRM(rm) == 6);
5607    amt = getIByte(delta+1);
5608    delta += 2;
5609    DIP("%s $%d,%s\n", opname,
5610                       (Int)amt,
5611                       nameMMXReg(eregOfRM(rm)) );
5612
5613    assign( e0, getMMXReg(eregOfRM(rm)) );
5614
5615    shl = shr = sar = False;
5616    size = 0;
5617    switch (op) {
5618       case Iop_ShlN16x4: shl = True; size = 16; break;
5619       case Iop_ShlN32x2: shl = True; size = 32; break;
5620       case Iop_Shl64:    shl = True; size = 64; break;
5621       case Iop_SarN16x4: sar = True; size = 16; break;
5622       case Iop_SarN32x2: sar = True; size = 32; break;
5623       case Iop_ShrN16x4: shr = True; size = 16; break;
5624       case Iop_ShrN32x2: shr = True; size = 32; break;
5625       case Iop_Shr64:    shr = True; size = 64; break;
5626       default: vassert(0);
5627    }
5628
5629    if (shl || shr) {
5630       assign( e1, amt >= size 
5631                      ? mkU64(0)
5632                      : binop(op, mkexpr(e0), mkU8(amt))
5633       );
5634    } else 
5635    if (sar) {
5636       assign( e1, amt >= size 
5637                      ? binop(op, mkexpr(e0), mkU8(size-1))
5638                      : binop(op, mkexpr(e0), mkU8(amt))
5639       );
5640    } else {
5641       /*NOTREACHED*/
5642       vassert(0);
5643    }
5644
5645    putMMXReg( eregOfRM(rm), mkexpr(e1) );
5646    return delta;
5647 }
5648
5649
5650 /* Completely handle all MMX instructions except emms. */
5651
5652 static
5653 UInt dis_MMX ( Bool* decode_ok, UChar sorb, Int sz, Int delta )
5654 {
5655    Int   len;
5656    UChar modrm;
5657    HChar dis_buf[50];
5658    UChar opc = getIByte(delta);
5659    delta++;
5660
5661    /* dis_MMX handles all insns except emms. */
5662    do_MMX_preamble();
5663
5664    switch (opc) {
5665
5666       case 0x6E: 
5667          /* MOVD (src)ireg-or-mem (E), (dst)mmxreg (G)*/
5668          if (sz != 4) 
5669             goto mmx_decode_failure;
5670          modrm = getIByte(delta);
5671          if (epartIsReg(modrm)) {
5672             delta++;
5673             putMMXReg(
5674                gregOfRM(modrm),
5675                binop( Iop_32HLto64,
5676                       mkU32(0),
5677                       getIReg(4, eregOfRM(modrm)) ) );
5678             DIP("movd %s, %s\n", 
5679                 nameIReg(4,eregOfRM(modrm)), nameMMXReg(gregOfRM(modrm)));
5680          } else {
5681             IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
5682             delta += len;
5683             putMMXReg(
5684                gregOfRM(modrm),
5685                binop( Iop_32HLto64,
5686                       mkU32(0),
5687                       loadLE(Ity_I32, mkexpr(addr)) ) );
5688             DIP("movd %s, %s\n", dis_buf, nameMMXReg(gregOfRM(modrm)));
5689          }
5690          break;
5691
5692       case 0x7E: /* MOVD (src)mmxreg (G), (dst)ireg-or-mem (E) */
5693          if (sz != 4) 
5694             goto mmx_decode_failure;
5695          modrm = getIByte(delta);
5696          if (epartIsReg(modrm)) {
5697             delta++;
5698             putIReg( 4, eregOfRM(modrm),
5699                      unop(Iop_64to32, getMMXReg(gregOfRM(modrm)) ) );
5700             DIP("movd %s, %s\n", 
5701                 nameMMXReg(gregOfRM(modrm)), nameIReg(4,eregOfRM(modrm)));
5702          } else {
5703             IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
5704             delta += len;
5705             storeLE( mkexpr(addr),
5706                      unop(Iop_64to32, getMMXReg(gregOfRM(modrm)) ) );
5707             DIP("movd %s, %s\n", nameMMXReg(gregOfRM(modrm)), dis_buf);
5708          }
5709          break;
5710
5711       case 0x6F:
5712          /* MOVQ (src)mmxreg-or-mem, (dst)mmxreg */
5713          if (sz != 4) 
5714             goto mmx_decode_failure;
5715          modrm = getIByte(delta);
5716          if (epartIsReg(modrm)) {
5717             delta++;
5718             putMMXReg( gregOfRM(modrm), getMMXReg(eregOfRM(modrm)) );
5719             DIP("movq %s, %s\n", 
5720                 nameMMXReg(eregOfRM(modrm)), nameMMXReg(gregOfRM(modrm)));
5721          } else {
5722             IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
5723             delta += len;
5724             putMMXReg( gregOfRM(modrm), loadLE(Ity_I64, mkexpr(addr)) );
5725             DIP("movq %s, %s\n", 
5726                 dis_buf, nameMMXReg(gregOfRM(modrm)));
5727          }
5728          break;
5729
5730       case 0x7F:
5731          /* MOVQ (src)mmxreg, (dst)mmxreg-or-mem */
5732          if (sz != 4) 
5733             goto mmx_decode_failure;
5734          modrm = getIByte(delta);
5735          if (epartIsReg(modrm)) {
5736             delta++;
5737             putMMXReg( eregOfRM(modrm), getMMXReg(gregOfRM(modrm)) );
5738             DIP("movq %s, %s\n", 
5739                 nameMMXReg(gregOfRM(modrm)), nameMMXReg(eregOfRM(modrm)));
5740          } else {
5741             IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
5742             delta += len;
5743             storeLE( mkexpr(addr), getMMXReg(gregOfRM(modrm)) );
5744             DIP("mov(nt)q %s, %s\n", 
5745                 nameMMXReg(gregOfRM(modrm)), dis_buf);
5746          }
5747          break;
5748
5749       case 0xFC: 
5750       case 0xFD: 
5751       case 0xFE: /* PADDgg (src)mmxreg-or-mem, (dst)mmxreg */
5752          if (sz != 4) 
5753             goto mmx_decode_failure;
5754          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "padd", True );
5755          break;
5756
5757       case 0xEC: 
5758       case 0xED: /* PADDSgg (src)mmxreg-or-mem, (dst)mmxreg */
5759          if (sz != 4) 
5760             goto mmx_decode_failure;
5761          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "padds", True );
5762          break;
5763
5764       case 0xDC: 
5765       case 0xDD: /* PADDUSgg (src)mmxreg-or-mem, (dst)mmxreg */
5766          if (sz != 4) 
5767             goto mmx_decode_failure;
5768          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "paddus", True );
5769          break;
5770
5771       case 0xF8: 
5772       case 0xF9: 
5773       case 0xFA: /* PSUBgg (src)mmxreg-or-mem, (dst)mmxreg */
5774          if (sz != 4) 
5775             goto mmx_decode_failure;
5776          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "psub", True );
5777          break;
5778
5779       case 0xE8: 
5780       case 0xE9: /* PSUBSgg (src)mmxreg-or-mem, (dst)mmxreg */
5781          if (sz != 4) 
5782             goto mmx_decode_failure;
5783          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "psubs", True );
5784          break;
5785
5786       case 0xD8: 
5787       case 0xD9: /* PSUBUSgg (src)mmxreg-or-mem, (dst)mmxreg */
5788          if (sz != 4) 
5789             goto mmx_decode_failure;
5790          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "psubus", True );
5791          break;
5792
5793       case 0xE5: /* PMULHW (src)mmxreg-or-mem, (dst)mmxreg */
5794          if (sz != 4) 
5795             goto mmx_decode_failure;
5796          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "pmulhw", False );
5797          break;
5798
5799       case 0xD5: /* PMULLW (src)mmxreg-or-mem, (dst)mmxreg */
5800          if (sz != 4) 
5801             goto mmx_decode_failure;
5802          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "pmullw", False );
5803          break;
5804
5805       case 0xF5: /* PMADDWD (src)mmxreg-or-mem, (dst)mmxreg */
5806          vassert(sz == 4);
5807          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "pmaddwd", False );
5808          break;
5809
5810       case 0x74: 
5811       case 0x75: 
5812       case 0x76: /* PCMPEQgg (src)mmxreg-or-mem, (dst)mmxreg */
5813          if (sz != 4) 
5814             goto mmx_decode_failure;
5815          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "pcmpeq", True );
5816          break;
5817
5818       case 0x64: 
5819       case 0x65: 
5820       case 0x66: /* PCMPGTgg (src)mmxreg-or-mem, (dst)mmxreg */
5821          if (sz != 4) 
5822             goto mmx_decode_failure;
5823          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "pcmpgt", True );
5824          break;
5825
5826       case 0x6B: /* PACKSSDW (src)mmxreg-or-mem, (dst)mmxreg */
5827          if (sz != 4) 
5828             goto mmx_decode_failure;
5829          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "packssdw", False );
5830          break;
5831
5832       case 0x63: /* PACKSSWB (src)mmxreg-or-mem, (dst)mmxreg */
5833          if (sz != 4) 
5834             goto mmx_decode_failure;
5835          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "packsswb", False );
5836          break;
5837
5838       case 0x67: /* PACKUSWB (src)mmxreg-or-mem, (dst)mmxreg */
5839          if (sz != 4) 
5840             goto mmx_decode_failure;
5841          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "packuswb", False );
5842          break;
5843
5844       case 0x68: 
5845       case 0x69: 
5846       case 0x6A: /* PUNPCKHgg (src)mmxreg-or-mem, (dst)mmxreg */
5847          if (sz != 4) 
5848             goto mmx_decode_failure;
5849          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "punpckh", True );
5850          break;
5851
5852       case 0x60: 
5853       case 0x61: 
5854       case 0x62: /* PUNPCKLgg (src)mmxreg-or-mem, (dst)mmxreg */
5855          if (sz != 4) 
5856             goto mmx_decode_failure;
5857          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "punpckl", True );
5858          break;
5859
5860       case 0xDB: /* PAND (src)mmxreg-or-mem, (dst)mmxreg */
5861          if (sz != 4) 
5862             goto mmx_decode_failure;
5863          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "pand", False );
5864          break;
5865
5866       case 0xDF: /* PANDN (src)mmxreg-or-mem, (dst)mmxreg */
5867          if (sz != 4) 
5868             goto mmx_decode_failure;
5869          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "pandn", False );
5870          break;
5871
5872       case 0xEB: /* POR (src)mmxreg-or-mem, (dst)mmxreg */
5873          if (sz != 4) 
5874             goto mmx_decode_failure;
5875          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "por", False );
5876          break;
5877
5878       case 0xEF: /* PXOR (src)mmxreg-or-mem, (dst)mmxreg */
5879          if (sz != 4) 
5880             goto mmx_decode_failure;
5881          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "pxor", False );
5882          break; 
5883
5884 #     define SHIFT_BY_REG(_name,_op)                                 \
5885                 delta = dis_MMX_shiftG_byE(sorb, delta, _name, _op); \
5886                 break;
5887
5888       /* PSLLgg (src)mmxreg-or-mem, (dst)mmxreg */
5889       case 0xF1: SHIFT_BY_REG("psllw", Iop_ShlN16x4);
5890       case 0xF2: SHIFT_BY_REG("pslld", Iop_ShlN32x2);
5891       case 0xF3: SHIFT_BY_REG("psllq", Iop_Shl64);
5892
5893       /* PSRLgg (src)mmxreg-or-mem, (dst)mmxreg */
5894       case 0xD1: SHIFT_BY_REG("psrlw", Iop_ShrN16x4);
5895       case 0xD2: SHIFT_BY_REG("psrld", Iop_ShrN32x2);
5896       case 0xD3: SHIFT_BY_REG("psrlq", Iop_Shr64);
5897
5898       /* PSRAgg (src)mmxreg-or-mem, (dst)mmxreg */
5899       case 0xE1: SHIFT_BY_REG("psraw", Iop_SarN16x4);
5900       case 0xE2: SHIFT_BY_REG("psrad", Iop_SarN32x2);
5901
5902 #     undef SHIFT_BY_REG
5903
5904       case 0x71: 
5905       case 0x72: 
5906       case 0x73: {
5907          /* (sz==4): PSLLgg/PSRAgg/PSRLgg mmxreg by imm8 */
5908          UChar byte2, subopc;
5909          if (sz != 4) 
5910             goto mmx_decode_failure;
5911          byte2  = getIByte(delta);           /* amode / sub-opcode */
5912          subopc = toUChar( (byte2 >> 3) & 7 );
5913
5914 #        define SHIFT_BY_IMM(_name,_op)                         \
5915              do { delta = dis_MMX_shiftE_imm(delta,_name,_op);  \
5916              } while (0)
5917
5918               if (subopc == 2 /*SRL*/ && opc == 0x71) 
5919                  SHIFT_BY_IMM("psrlw", Iop_ShrN16x4);
5920          else if (subopc == 2 /*SRL*/ && opc == 0x72) 
5921                  SHIFT_BY_IMM("psrld", Iop_ShrN32x2);
5922          else if (subopc == 2 /*SRL*/ && opc == 0x73) 
5923                  SHIFT_BY_IMM("psrlq", Iop_Shr64);
5924
5925          else if (subopc == 4 /*SAR*/ && opc == 0x71) 
5926                  SHIFT_BY_IMM("psraw", Iop_SarN16x4);
5927          else if (subopc == 4 /*SAR*/ && opc == 0x72) 
5928                  SHIFT_BY_IMM("psrad", Iop_SarN32x2);
5929
5930          else if (subopc == 6 /*SHL*/ && opc == 0x71) 
5931                  SHIFT_BY_IMM("psllw", Iop_ShlN16x4);
5932          else if (subopc == 6 /*SHL*/ && opc == 0x72) 
5933                  SHIFT_BY_IMM("pslld", Iop_ShlN32x2);
5934          else if (subopc == 6 /*SHL*/ && opc == 0x73) 
5935                  SHIFT_BY_IMM("psllq", Iop_Shl64);
5936
5937          else goto mmx_decode_failure;
5938
5939 #        undef SHIFT_BY_IMM
5940          break;
5941       }
5942
5943       case 0xF7: {
5944          IRTemp addr    = newTemp(Ity_I32);
5945          IRTemp regD    = newTemp(Ity_I64);
5946          IRTemp regM    = newTemp(Ity_I64);
5947          IRTemp mask    = newTemp(Ity_I64);
5948          IRTemp olddata = newTemp(Ity_I64);
5949          IRTemp newdata = newTemp(Ity_I64);
5950
5951          modrm = getIByte(delta);
5952          if (sz != 4 || (!epartIsReg(modrm)))
5953             goto mmx_decode_failure;
5954          delta++;
5955
5956          assign( addr, handleSegOverride( sorb, getIReg(4, R_EDI) ));
5957          assign( regM, getMMXReg( eregOfRM(modrm) ));
5958          assign( regD, getMMXReg( gregOfRM(modrm) ));
5959          assign( mask, binop(Iop_SarN8x8, mkexpr(regM), mkU8(7)) );
5960          assign( olddata, loadLE( Ity_I64, mkexpr(addr) ));
5961          assign( newdata, 
5962                  binop(Iop_Or64, 
5963                        binop(Iop_And64, 
5964                              mkexpr(regD), 
5965                              mkexpr(mask) ),
5966                        binop(Iop_And64, 
5967                              mkexpr(olddata),
5968                              unop(Iop_Not64, mkexpr(mask)))) );
5969          storeLE( mkexpr(addr), mkexpr(newdata) );
5970          DIP("maskmovq %s,%s\n", nameMMXReg( eregOfRM(modrm) ),
5971                                  nameMMXReg( gregOfRM(modrm) ) );
5972          break;
5973       }
5974
5975       /* --- MMX decode failure --- */
5976       default:
5977       mmx_decode_failure:
5978          *decode_ok = False;
5979          return delta; /* ignored */
5980
5981    }
5982
5983    *decode_ok = True;
5984    return delta;
5985 }
5986
5987
5988 /*------------------------------------------------------------*/
5989 /*--- More misc arithmetic and other obscure insns.        ---*/
5990 /*------------------------------------------------------------*/
5991
5992 /* Double length left and right shifts.  Apparently only required in
5993    v-size (no b- variant). */
5994 static
5995 UInt dis_SHLRD_Gv_Ev ( UChar sorb,
5996                        Int delta, UChar modrm,
5997                        Int sz,
5998                        IRExpr* shift_amt,
5999                        Bool amt_is_literal,
6000                        HChar* shift_amt_txt,
6001                        Bool left_shift )
6002 {
6003    /* shift_amt :: Ity_I8 is the amount to shift.  shift_amt_txt is used
6004       for printing it.   And eip on entry points at the modrm byte. */
6005    Int len;
6006    HChar dis_buf[50];
6007
6008    IRType ty       = szToITy(sz);
6009    IRTemp gsrc     = newTemp(ty);
6010    IRTemp esrc     = newTemp(ty);
6011    IRTemp addr     = IRTemp_INVALID;
6012    IRTemp tmpSH    = newTemp(Ity_I8);
6013    IRTemp tmpL     = IRTemp_INVALID;
6014    IRTemp tmpRes   = IRTemp_INVALID;
6015    IRTemp tmpSubSh = IRTemp_INVALID;
6016    IROp   mkpair;
6017    IROp   getres;
6018    IROp   shift;
6019    IRExpr* mask = NULL;
6020
6021    vassert(sz == 2 || sz == 4);
6022
6023    /* The E-part is the destination; this is shifted.  The G-part
6024       supplies bits to be shifted into the E-part, but is not
6025       changed.  
6026
6027       If shifting left, form a double-length word with E at the top
6028       and G at the bottom, and shift this left.  The result is then in
6029       the high part.
6030
6031       If shifting right, form a double-length word with G at the top
6032       and E at the bottom, and shift this right.  The result is then
6033       at the bottom.  */
6034
6035    /* Fetch the operands. */
6036
6037    assign( gsrc, getIReg(sz, gregOfRM(modrm)) );
6038
6039    if (epartIsReg(modrm)) {
6040       delta++;
6041       assign( esrc, getIReg(sz, eregOfRM(modrm)) );
6042       DIP("sh%cd%c %s, %s, %s\n",
6043           ( left_shift ? 'l' : 'r' ), nameISize(sz), 
6044           shift_amt_txt,
6045           nameIReg(sz, gregOfRM(modrm)), nameIReg(sz, eregOfRM(modrm)));
6046    } else {
6047       addr = disAMode ( &len, sorb, delta, dis_buf );
6048       delta += len;
6049       assign( esrc, loadLE(ty, mkexpr(addr)) );
6050       DIP("sh%cd%c %s, %s, %s\n", 
6051           ( left_shift ? 'l' : 'r' ), nameISize(sz), 
6052           shift_amt_txt,
6053           nameIReg(sz, gregOfRM(modrm)), dis_buf);
6054    }
6055
6056    /* Round up the relevant primops. */
6057
6058    if (sz == 4) {
6059       tmpL     = newTemp(Ity_I64);
6060       tmpRes   = newTemp(Ity_I32);
6061       tmpSubSh = newTemp(Ity_I32);
6062       mkpair   = Iop_32HLto64;
6063       getres   = left_shift ? Iop_64HIto32 : Iop_64to32;
6064       shift    = left_shift ? Iop_Shl64 : Iop_Shr64;
6065       mask     = mkU8(31);
6066    } else {
6067       /* sz == 2 */
6068       tmpL     = newTemp(Ity_I32);
6069       tmpRes   = newTemp(Ity_I16);
6070       tmpSubSh = newTemp(Ity_I16);
6071       mkpair   = Iop_16HLto32;
6072       getres   = left_shift ? Iop_32HIto16 : Iop_32to16;
6073       shift    = left_shift ? Iop_Shl32 : Iop_Shr32;
6074       mask     = mkU8(15);
6075    }
6076
6077    /* Do the shift, calculate the subshift value, and set 
6078       the flag thunk. */
6079
6080    assign( tmpSH, binop(Iop_And8, shift_amt, mask) );
6081
6082    if (left_shift)
6083       assign( tmpL, binop(mkpair, mkexpr(esrc), mkexpr(gsrc)) );
6084    else
6085       assign( tmpL, binop(mkpair, mkexpr(gsrc), mkexpr(esrc)) );
6086
6087    assign( tmpRes, unop(getres, binop(shift, mkexpr(tmpL), mkexpr(tmpSH)) ) );
6088    assign( tmpSubSh, 
6089            unop(getres, 
6090                 binop(shift, 
6091                       mkexpr(tmpL), 
6092                       binop(Iop_And8, 
6093                             binop(Iop_Sub8, mkexpr(tmpSH), mkU8(1) ),
6094                             mask))) );
6095
6096    setFlags_DEP1_DEP2_shift ( left_shift ? Iop_Shl32 : Iop_Sar32,
6097                               tmpRes, tmpSubSh, ty, tmpSH );
6098
6099    /* Put result back. */
6100
6101    if (epartIsReg(modrm)) {
6102       putIReg(sz, eregOfRM(modrm), mkexpr(tmpRes));
6103    } else {
6104       storeLE( mkexpr(addr), mkexpr(tmpRes) );
6105    }
6106
6107    if (amt_is_literal) delta++;
6108    return delta;
6109 }
6110
6111
6112 /* Handle BT/BTS/BTR/BTC Gv, Ev.  Apparently b-size is not
6113    required. */
6114
6115 typedef enum { BtOpNone, BtOpSet, BtOpReset, BtOpComp } BtOp;
6116
6117 static HChar* nameBtOp ( BtOp op )
6118 {
6119    switch (op) {
6120       case BtOpNone:  return "";
6121       case BtOpSet:   return "s";
6122       case BtOpReset: return "r";
6123       case BtOpComp:  return "c";
6124       default: vpanic("nameBtOp(x86)");
6125    }
6126 }
6127
6128
6129 static
6130 UInt dis_bt_G_E ( UChar sorb, Bool locked, Int sz, Int delta, BtOp op )
6131 {
6132    HChar  dis_buf[50];
6133    UChar  modrm;
6134    Int    len;
6135    IRTemp t_fetched, t_bitno0, t_bitno1, t_bitno2, t_addr0, 
6136           t_addr1, t_esp, t_mask, t_new;
6137
6138    vassert(sz == 2 || sz == 4);
6139
6140    t_fetched = t_bitno0 = t_bitno1 = t_bitno2 
6141              = t_addr0 = t_addr1 = t_esp 
6142              = t_mask = t_new = IRTemp_INVALID;
6143
6144    t_fetched = newTemp(Ity_I8);
6145    t_new     = newTemp(Ity_I8);
6146    t_bitno0  = newTemp(Ity_I32);
6147    t_bitno1  = newTemp(Ity_I32);
6148    t_bitno2  = newTemp(Ity_I8);
6149    t_addr1   = newTemp(Ity_I32);
6150    modrm     = getIByte(delta);
6151
6152    assign( t_bitno0, widenSto32(getIReg(sz, gregOfRM(modrm))) );
6153    
6154    if (epartIsReg(modrm)) {
6155       delta++;
6156       /* Get it onto the client's stack. */
6157       t_esp = newTemp(Ity_I32);
6158       t_addr0 = newTemp(Ity_I32);
6159
6160       assign( t_esp, binop(Iop_Sub32, getIReg(4, R_ESP), mkU32(sz)) );
6161       putIReg(4, R_ESP, mkexpr(t_esp));
6162
6163       storeLE( mkexpr(t_esp), getIReg(sz, eregOfRM(modrm)) );
6164
6165       /* Make t_addr0 point at it. */
6166       assign( t_addr0, mkexpr(t_esp) );
6167
6168       /* Mask out upper bits of the shift amount, since we're doing a
6169          reg. */
6170       assign( t_bitno1, binop(Iop_And32, 
6171                               mkexpr(t_bitno0), 
6172                               mkU32(sz == 4 ? 31 : 15)) );
6173
6174    } else {
6175       t_addr0 = disAMode ( &len, sorb, delta, dis_buf );
6176       delta += len;
6177       assign( t_bitno1, mkexpr(t_bitno0) );
6178    }
6179   
6180    /* At this point: t_addr0 is the address being operated on.  If it
6181       was a reg, we will have pushed it onto the client's stack.
6182       t_bitno1 is the bit number, suitably masked in the case of a
6183       reg.  */
6184   
6185    /* Now the main sequence. */
6186    assign( t_addr1, 
6187            binop(Iop_Add32, 
6188                  mkexpr(t_addr0), 
6189                  binop(Iop_Sar32, mkexpr(t_bitno1), mkU8(3))) );
6190
6191    /* t_addr1 now holds effective address */
6192
6193    assign( t_bitno2, 
6194            unop(Iop_32to8, 
6195                 binop(Iop_And32, mkexpr(t_bitno1), mkU32(7))) );
6196
6197    /* t_bitno2 contains offset of bit within byte */
6198
6199    if (op != BtOpNone) {
6200       t_mask = newTemp(Ity_I8);
6201       assign( t_mask, binop(Iop_Shl8, mkU8(1), mkexpr(t_bitno2)) );
6202    }
6203
6204    /* t_mask is now a suitable byte mask */
6205
6206    assign( t_fetched, loadLE(Ity_I8, mkexpr(t_addr1)) );
6207
6208    if (op != BtOpNone) {
6209       switch (op) {
6210          case BtOpSet:
6211             assign( t_new,
6212                     binop(Iop_Or8, mkexpr(t_fetched), mkexpr(t_mask)) );
6213             break;
6214          case BtOpComp:
6215             assign( t_new,
6216                     binop(Iop_Xor8, mkexpr(t_fetched), mkexpr(t_mask)) );
6217             break;
6218          case BtOpReset:
6219             assign( t_new,
6220                     binop(Iop_And8, mkexpr(t_fetched), 
6221                                     unop(Iop_Not8, mkexpr(t_mask))) );
6222             break;
6223          default: 
6224             vpanic("dis_bt_G_E(x86)");
6225       }
6226       if (locked && !epartIsReg(modrm)) {
6227          casLE( mkexpr(t_addr1), mkexpr(t_fetched)/*expd*/,
6228                                  mkexpr(t_new)/*new*/,
6229                                  guest_EIP_curr_instr );
6230       } else {
6231          storeLE( mkexpr(t_addr1), mkexpr(t_new) );
6232       }
6233    }
6234  
6235    /* Side effect done; now get selected bit into Carry flag */
6236    /* Flags: C=selected bit, O,S,Z,A,P undefined, so are set to zero. */
6237    stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(X86G_CC_OP_COPY) ));
6238    stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0) ));
6239    stmt( IRStmt_Put( 
6240             OFFB_CC_DEP1,
6241             binop(Iop_And32,
6242                   binop(Iop_Shr32, 
6243                         unop(Iop_8Uto32, mkexpr(t_fetched)),
6244                         mkexpr(t_bitno2)),
6245                   mkU32(1)))
6246        );
6247    /* Set NDEP even though it isn't used.  This makes redundant-PUT
6248       elimination of previous stores to this field work better. */
6249    stmt( IRStmt_Put( OFFB_CC_NDEP, mkU32(0) ));
6250
6251    /* Move reg operand from stack back to reg */
6252    if (epartIsReg(modrm)) {
6253       /* t_esp still points at it. */
6254       putIReg(sz, eregOfRM(modrm), loadLE(szToITy(sz), mkexpr(t_esp)) );
6255       putIReg(4, R_ESP, binop(Iop_Add32, mkexpr(t_esp), mkU32(sz)) );
6256    }
6257
6258    DIP("bt%s%c %s, %s\n",
6259        nameBtOp(op), nameISize(sz), nameIReg(sz, gregOfRM(modrm)), 
6260        ( epartIsReg(modrm) ? nameIReg(sz, eregOfRM(modrm)) : dis_buf ) );
6261  
6262    return delta;
6263 }
6264
6265
6266
6267 /* Handle BSF/BSR.  Only v-size seems necessary. */
6268 static
6269 UInt dis_bs_E_G ( UChar sorb, Int sz, Int delta, Bool fwds )
6270 {
6271    Bool   isReg;
6272    UChar  modrm;
6273    HChar  dis_buf[50];
6274    
6275    IRType ty  = szToITy(sz);
6276    IRTemp src = newTemp(ty);
6277    IRTemp dst = newTemp(ty);
6278
6279    IRTemp src32 = newTemp(Ity_I32);
6280    IRTemp dst32 = newTemp(Ity_I32);
6281    IRTemp src8  = newTemp(Ity_I8);
6282
6283    vassert(sz == 4 || sz == 2);
6284
6285    modrm = getIByte(delta);
6286
6287    isReg = epartIsReg(modrm);
6288    if (isReg) {
6289       delta++;
6290       assign( src, getIReg(sz, eregOfRM(modrm)) );
6291    } else {
6292       Int    len;
6293       IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
6294       delta += len;
6295       assign( src, loadLE(ty, mkexpr(addr)) );
6296    }
6297
6298    DIP("bs%c%c %s, %s\n",
6299        fwds ? 'f' : 'r', nameISize(sz), 
6300        ( isReg ? nameIReg(sz, eregOfRM(modrm)) : dis_buf ), 
6301        nameIReg(sz, gregOfRM(modrm)));
6302
6303    /* Generate an 8-bit expression which is zero iff the 
6304       original is zero, and nonzero otherwise */
6305    assign( src8,
6306            unop(Iop_1Uto8, binop(mkSizedOp(ty,Iop_CmpNE8),
6307                            mkexpr(src), mkU(ty,0))) );
6308
6309    /* Flags: Z is 1 iff source value is zero.  All others 
6310       are undefined -- we force them to zero. */
6311    stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(X86G_CC_OP_COPY) ));
6312    stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0) ));
6313    stmt( IRStmt_Put( 
6314             OFFB_CC_DEP1,
6315             IRExpr_Mux0X( mkexpr(src8),
6316                           /* src==0 */
6317                           mkU32(X86G_CC_MASK_Z),
6318                           /* src!=0 */
6319                           mkU32(0)
6320                         )
6321        ));
6322    /* Set NDEP even though it isn't used.  This makes redundant-PUT
6323       elimination of previous stores to this field work better. */
6324    stmt( IRStmt_Put( OFFB_CC_NDEP, mkU32(0) ));
6325
6326    /* Result: iff source value is zero, we can't use
6327       Iop_Clz32/Iop_Ctz32 as they have no defined result in that case.
6328       But anyway, Intel x86 semantics say the result is undefined in
6329       such situations.  Hence handle the zero case specially. */
6330
6331    /* Bleh.  What we compute:
6332
6333           bsf32:  if src == 0 then 0 else  Ctz32(src)
6334           bsr32:  if src == 0 then 0 else  31 - Clz32(src)
6335
6336           bsf16:  if src == 0 then 0 else  Ctz32(16Uto32(src))
6337           bsr16:  if src == 0 then 0 else  31 - Clz32(16Uto32(src))
6338
6339       First, widen src to 32 bits if it is not already.
6340
6341       Postscript 15 Oct 04: it seems that at least VIA Nehemiah leaves the
6342       dst register unchanged when src == 0.  Hence change accordingly.
6343    */
6344    if (sz == 2)
6345       assign( src32, unop(Iop_16Uto32, mkexpr(src)) );
6346    else
6347       assign( src32, mkexpr(src) );
6348
6349    /* The main computation, guarding against zero. */
6350    assign( dst32,   
6351            IRExpr_Mux0X( 
6352               mkexpr(src8),
6353               /* src == 0 -- leave dst unchanged */
6354               widenUto32( getIReg( sz, gregOfRM(modrm) ) ),
6355               /* src != 0 */
6356               fwds ? unop(Iop_Ctz32, mkexpr(src32))
6357                    : binop(Iop_Sub32, 
6358                            mkU32(31), 
6359                            unop(Iop_Clz32, mkexpr(src32)))
6360            )
6361          );
6362
6363    if (sz == 2)
6364       assign( dst, unop(Iop_32to16, mkexpr(dst32)) );
6365    else
6366       assign( dst, mkexpr(dst32) );
6367
6368    /* dump result back */
6369    putIReg( sz, gregOfRM(modrm), mkexpr(dst) );
6370
6371    return delta;
6372 }
6373
6374
6375 static 
6376 void codegen_xchg_eAX_Reg ( Int sz, Int reg )
6377 {
6378    IRType ty = szToITy(sz);
6379    IRTemp t1 = newTemp(ty);
6380    IRTemp t2 = newTemp(ty);
6381    vassert(sz == 2 || sz == 4);
6382    assign( t1, getIReg(sz, R_EAX) );
6383    assign( t2, getIReg(sz, reg) );
6384    putIReg( sz, R_EAX, mkexpr(t2) );
6385    putIReg( sz, reg, mkexpr(t1) );
6386    DIP("xchg%c %s, %s\n", 
6387        nameISize(sz), nameIReg(sz, R_EAX), nameIReg(sz, reg));
6388 }
6389
6390
6391 static 
6392 void codegen_SAHF ( void )
6393 {
6394    /* Set the flags to:
6395       (x86g_calculate_flags_all() & X86G_CC_MASK_O)  -- retain the old O flag
6396       | (%AH & (X86G_CC_MASK_S|X86G_CC_MASK_Z|X86G_CC_MASK_A
6397                 |X86G_CC_MASK_P|X86G_CC_MASK_C)
6398    */
6399    UInt   mask_SZACP = X86G_CC_MASK_S|X86G_CC_MASK_Z|X86G_CC_MASK_A
6400                        |X86G_CC_MASK_C|X86G_CC_MASK_P;
6401    IRTemp oldflags   = newTemp(Ity_I32);
6402    assign( oldflags, mk_x86g_calculate_eflags_all() );
6403    stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(X86G_CC_OP_COPY) ));
6404    stmt( IRStmt_Put( OFFB_CC_NDEP, mkU32(0) ));
6405    stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0) ));
6406    stmt( IRStmt_Put( OFFB_CC_DEP1,
6407          binop(Iop_Or32,
6408                binop(Iop_And32, mkexpr(oldflags), mkU32(X86G_CC_MASK_O)),
6409                binop(Iop_And32, 
6410                      binop(Iop_Shr32, getIReg(4, R_EAX), mkU8(8)),
6411                      mkU32(mask_SZACP))
6412               )
6413    ));
6414    /* Set NDEP even though it isn't used.  This makes redundant-PUT
6415       elimination of previous stores to this field work better. */
6416    stmt( IRStmt_Put( OFFB_CC_NDEP, mkU32(0) ));
6417 }
6418
6419
6420 static 
6421 void codegen_LAHF ( void  )
6422 {
6423    /* AH <- EFLAGS(SF:ZF:0:AF:0:PF:1:CF) */
6424    IRExpr* eax_with_hole;
6425    IRExpr* new_byte;
6426    IRExpr* new_eax;
6427    UInt    mask_SZACP = X86G_CC_MASK_S|X86G_CC_MASK_Z|X86G_CC_MASK_A
6428                         |X86G_CC_MASK_C|X86G_CC_MASK_P;
6429
6430    IRTemp  flags = newTemp(Ity_I32);
6431    assign( flags, mk_x86g_calculate_eflags_all() );
6432
6433    eax_with_hole 
6434       = binop(Iop_And32, getIReg(4, R_EAX), mkU32(0xFFFF00FF));
6435    new_byte 
6436       = binop(Iop_Or32, binop(Iop_And32, mkexpr(flags), mkU32(mask_SZACP)),
6437                         mkU32(1<<1));
6438    new_eax 
6439       = binop(Iop_Or32, eax_with_hole,
6440                         binop(Iop_Shl32, new_byte, mkU8(8)));
6441    putIReg(4, R_EAX, new_eax);
6442 }
6443
6444
6445 static
6446 UInt dis_cmpxchg_G_E ( UChar       sorb,
6447                        Bool        locked,
6448                        Int         size, 
6449                        Int         delta0 )
6450 {
6451    HChar dis_buf[50];
6452    Int   len;
6453
6454    IRType ty    = szToITy(size);
6455    IRTemp acc   = newTemp(ty);
6456    IRTemp src   = newTemp(ty);
6457    IRTemp dest  = newTemp(ty);
6458    IRTemp dest2 = newTemp(ty);
6459    IRTemp acc2  = newTemp(ty);
6460    IRTemp cond8 = newTemp(Ity_I8);
6461    IRTemp addr  = IRTemp_INVALID;
6462    UChar  rm    = getUChar(delta0);
6463
6464    /* There are 3 cases to consider:
6465
6466       reg-reg: ignore any lock prefix, generate sequence based
6467                on Mux0X
6468
6469       reg-mem, not locked: ignore any lock prefix, generate sequence
6470                            based on Mux0X
6471
6472       reg-mem, locked: use IRCAS
6473    */
6474    if (epartIsReg(rm)) {
6475       /* case 1 */
6476       assign( dest, getIReg(size, eregOfRM(rm)) );
6477       delta0++;
6478       assign( src, getIReg(size, gregOfRM(rm)) );
6479       assign( acc, getIReg(size, R_EAX) );
6480       setFlags_DEP1_DEP2(Iop_Sub8, acc, dest, ty);
6481       assign( cond8, unop(Iop_1Uto8, mk_x86g_calculate_condition(X86CondZ)) );
6482       assign( dest2, IRExpr_Mux0X(mkexpr(cond8), mkexpr(dest), mkexpr(src)) );
6483       assign( acc2,  IRExpr_Mux0X(mkexpr(cond8), mkexpr(dest), mkexpr(acc)) );
6484       putIReg(size, R_EAX, mkexpr(acc2));
6485       putIReg(size, eregOfRM(rm), mkexpr(dest2));
6486       DIP("cmpxchg%c %s,%s\n", nameISize(size),
6487                                nameIReg(size,gregOfRM(rm)),
6488                                nameIReg(size,eregOfRM(rm)) );
6489    } 
6490    else if (!epartIsReg(rm) && !locked) {
6491       /* case 2 */
6492       addr = disAMode ( &len, sorb, delta0, dis_buf );
6493       assign( dest, loadLE(ty, mkexpr(addr)) );
6494       delta0 += len;
6495       assign( src, getIReg(size, gregOfRM(rm)) );
6496       assign( acc, getIReg(size, R_EAX) );
6497       setFlags_DEP1_DEP2(Iop_Sub8, acc, dest, ty);
6498       assign( cond8, unop(Iop_1Uto8, mk_x86g_calculate_condition(X86CondZ)) );
6499       assign( dest2, IRExpr_Mux0X(mkexpr(cond8), mkexpr(dest), mkexpr(src)) );
6500       assign( acc2,  IRExpr_Mux0X(mkexpr(cond8), mkexpr(dest), mkexpr(acc)) );
6501       putIReg(size, R_EAX, mkexpr(acc2));
6502       storeLE( mkexpr(addr), mkexpr(dest2) );
6503       DIP("cmpxchg%c %s,%s\n", nameISize(size), 
6504                                nameIReg(size,gregOfRM(rm)), dis_buf);
6505    }
6506    else if (!epartIsReg(rm) && locked) {
6507       /* case 3 */
6508       /* src is new value.  acc is expected value.  dest is old value.
6509          Compute success from the output of the IRCAS, and steer the
6510          new value for EAX accordingly: in case of success, EAX is
6511          unchanged. */
6512       addr = disAMode ( &len, sorb, delta0, dis_buf );
6513       delta0 += len;
6514       assign( src, getIReg(size, gregOfRM(rm)) );
6515       assign( acc, getIReg(size, R_EAX) );
6516       stmt( IRStmt_CAS( 
6517          mkIRCAS( IRTemp_INVALID, dest, Iend_LE, mkexpr(addr), 
6518                   NULL, mkexpr(acc), NULL, mkexpr(src) )
6519       ));
6520       setFlags_DEP1_DEP2(Iop_Sub8, acc, dest, ty);
6521       assign( cond8, unop(Iop_1Uto8, mk_x86g_calculate_condition(X86CondZ)) );
6522       assign( acc2,  IRExpr_Mux0X(mkexpr(cond8), mkexpr(dest), mkexpr(acc)) );
6523       putIReg(size, R_EAX, mkexpr(acc2));
6524       DIP("cmpxchg%c %s,%s\n", nameISize(size), 
6525                                nameIReg(size,gregOfRM(rm)), dis_buf);
6526    }
6527    else vassert(0);
6528
6529    return delta0;
6530 }
6531
6532
6533 /* Handle conditional move instructions of the form
6534       cmovcc E(reg-or-mem), G(reg)
6535
6536    E(src) is reg-or-mem
6537    G(dst) is reg.
6538
6539    If E is reg, -->    GET %E, tmps
6540                        GET %G, tmpd
6541                        CMOVcc tmps, tmpd
6542                        PUT tmpd, %G
6543  
6544    If E is mem  -->    (getAddr E) -> tmpa
6545                        LD (tmpa), tmps
6546                        GET %G, tmpd
6547                        CMOVcc tmps, tmpd
6548                        PUT tmpd, %G
6549 */
6550 static
6551 UInt dis_cmov_E_G ( UChar       sorb,
6552                     Int         sz, 
6553                     X86Condcode cond,
6554                     Int         delta0 )
6555 {
6556    UChar rm  = getIByte(delta0);
6557    HChar dis_buf[50];
6558    Int   len;
6559
6560    IRType ty   = szToITy(sz);
6561    IRTemp tmps = newTemp(ty);
6562    IRTemp tmpd = newTemp(ty);
6563
6564    if (epartIsReg(rm)) {
6565       assign( tmps, getIReg(sz, eregOfRM(rm)) );
6566       assign( tmpd, getIReg(sz, gregOfRM(rm)) );
6567
6568       putIReg(sz, gregOfRM(rm),
6569                   IRExpr_Mux0X( unop(Iop_1Uto8,
6570                                      mk_x86g_calculate_condition(cond)),
6571                                 mkexpr(tmpd),
6572                                 mkexpr(tmps) )
6573              );
6574       DIP("cmov%c%s %s,%s\n", nameISize(sz), 
6575                               name_X86Condcode(cond),
6576                               nameIReg(sz,eregOfRM(rm)),
6577                               nameIReg(sz,gregOfRM(rm)));
6578       return 1+delta0;
6579    }
6580
6581    /* E refers to memory */    
6582    {
6583       IRTemp addr = disAMode ( &len, sorb, delta0, dis_buf );
6584       assign( tmps, loadLE(ty, mkexpr(addr)) );
6585       assign( tmpd, getIReg(sz, gregOfRM(rm)) );
6586
6587       putIReg(sz, gregOfRM(rm),
6588                   IRExpr_Mux0X( unop(Iop_1Uto8,
6589                                      mk_x86g_calculate_condition(cond)),
6590                                 mkexpr(tmpd),
6591                                 mkexpr(tmps) )
6592              );
6593
6594       DIP("cmov%c%s %s,%s\n", nameISize(sz), 
6595                               name_X86Condcode(cond),
6596                               dis_buf,
6597                               nameIReg(sz,gregOfRM(rm)));
6598       return len+delta0;
6599    }
6600 }
6601
6602
6603 static
6604 UInt dis_xadd_G_E ( UChar sorb, Bool locked, Int sz, Int delta0,
6605                     Bool* decodeOK )
6606 {
6607    Int   len;
6608    UChar rm = getIByte(delta0);
6609    HChar dis_buf[50];
6610
6611    IRType ty    = szToITy(sz);
6612    IRTemp tmpd  = newTemp(ty);
6613    IRTemp tmpt0 = newTemp(ty);
6614    IRTemp tmpt1 = newTemp(ty);
6615
6616    /* There are 3 cases to consider:
6617
6618       reg-reg: currently unhandled
6619
6620       reg-mem, not locked: ignore any lock prefix, generate 'naive'
6621                            (non-atomic) sequence
6622
6623       reg-mem, locked: use IRCAS
6624    */
6625
6626    if (epartIsReg(rm)) {
6627       /* case 1 */
6628       *decodeOK = False;
6629       return delta0;
6630       /* Currently we don't handle xadd_G_E with register operand. */
6631    }
6632    else if (!epartIsReg(rm) && !locked) {
6633       /* case 2 */
6634       IRTemp addr = disAMode ( &len, sorb, delta0, dis_buf );
6635       assign( tmpd,  loadLE(ty, mkexpr(addr)) );
6636       assign( tmpt0, getIReg(sz, gregOfRM(rm)) );
6637       assign( tmpt1, binop(mkSizedOp(ty,Iop_Add8),
6638                            mkexpr(tmpd), mkexpr(tmpt0)) );
6639       storeLE( mkexpr(addr), mkexpr(tmpt1) );
6640       setFlags_DEP1_DEP2( Iop_Add8, tmpd, tmpt0, ty );
6641       putIReg(sz, gregOfRM(rm), mkexpr(tmpd));
6642       DIP("xadd%c %s, %s\n",
6643           nameISize(sz), nameIReg(sz,gregOfRM(rm)), dis_buf);
6644       *decodeOK = True;
6645       return len+delta0;
6646    }
6647    else if (!epartIsReg(rm) && locked) {
6648       /* case 3 */
6649       IRTemp addr = disAMode ( &len, sorb, delta0, dis_buf );
6650       assign( tmpd,  loadLE(ty, mkexpr(addr)) );
6651       assign( tmpt0, getIReg(sz, gregOfRM(rm)) );
6652       assign( tmpt1, binop(mkSizedOp(ty,Iop_Add8), 
6653                            mkexpr(tmpd), mkexpr(tmpt0)) );
6654       casLE( mkexpr(addr), mkexpr(tmpd)/*expVal*/,
6655                            mkexpr(tmpt1)/*newVal*/, guest_EIP_curr_instr );
6656       setFlags_DEP1_DEP2( Iop_Add8, tmpd, tmpt0, ty );
6657       putIReg(sz, gregOfRM(rm), mkexpr(tmpd));
6658       DIP("xadd%c %s, %s\n",
6659           nameISize(sz), nameIReg(sz,gregOfRM(rm)), dis_buf);
6660       *decodeOK = True;
6661       return len+delta0;
6662    }
6663    /*UNREACHED*/
6664    vassert(0);
6665 }
6666
6667 /* Move 16 bits from Ew (ireg or mem) to G (a segment register). */
6668
6669 static
6670 UInt dis_mov_Ew_Sw ( UChar sorb, Int delta0 )
6671 {
6672    Int    len;
6673    IRTemp addr;
6674    UChar  rm  = getIByte(delta0);
6675    HChar  dis_buf[50];
6676
6677    if (epartIsReg(rm)) {
6678       putSReg( gregOfRM(rm), getIReg(2, eregOfRM(rm)) );
6679       DIP("movw %s,%s\n", nameIReg(2,eregOfRM(rm)), nameSReg(gregOfRM(rm)));
6680       return 1+delta0;
6681    } else {
6682       addr = disAMode ( &len, sorb, delta0, dis_buf );
6683       putSReg( gregOfRM(rm), loadLE(Ity_I16, mkexpr(addr)) );
6684       DIP("movw %s,%s\n", dis_buf, nameSReg(gregOfRM(rm)));
6685       return len+delta0;
6686    }
6687 }
6688
6689 /* Move 16 bits from G (a segment register) to Ew (ireg or mem).  If
6690    dst is ireg and sz==4, zero out top half of it.  */
6691
6692 static
6693 UInt dis_mov_Sw_Ew ( UChar sorb,
6694                      Int   sz,
6695                      Int   delta0 )
6696 {
6697    Int    len;
6698    IRTemp addr;
6699    UChar  rm  = getIByte(delta0);
6700    HChar  dis_buf[50];
6701
6702    vassert(sz == 2 || sz == 4);
6703
6704    if (epartIsReg(rm)) {
6705       if (sz == 4)
6706          putIReg(4, eregOfRM(rm), unop(Iop_16Uto32, getSReg(gregOfRM(rm))));
6707       else
6708          putIReg(2, eregOfRM(rm), getSReg(gregOfRM(rm)));
6709
6710       DIP("mov %s,%s\n", nameSReg(gregOfRM(rm)), nameIReg(sz,eregOfRM(rm)));
6711       return 1+delta0;
6712    } else {
6713       addr = disAMode ( &len, sorb, delta0, dis_buf );
6714       storeLE( mkexpr(addr), getSReg(gregOfRM(rm)) );
6715       DIP("mov %s,%s\n", nameSReg(gregOfRM(rm)), dis_buf);
6716       return len+delta0;
6717    }
6718 }
6719
6720
6721 static 
6722 void dis_push_segreg ( UInt sreg, Int sz )
6723 {
6724     IRTemp t1 = newTemp(Ity_I16);
6725     IRTemp ta = newTemp(Ity_I32);
6726     vassert(sz == 2 || sz == 4);
6727
6728     assign( t1, getSReg(sreg) );
6729     assign( ta, binop(Iop_Sub32, getIReg(4, R_ESP), mkU32(sz)) );
6730     putIReg(4, R_ESP, mkexpr(ta));
6731     storeLE( mkexpr(ta), mkexpr(t1) );
6732
6733     DIP("push%c %s\n", sz==2 ? 'w' : 'l', nameSReg(sreg));
6734 }
6735
6736 static
6737 void dis_pop_segreg ( UInt sreg, Int sz )
6738 {
6739     IRTemp t1 = newTemp(Ity_I16);
6740     IRTemp ta = newTemp(Ity_I32);
6741     vassert(sz == 2 || sz == 4);
6742
6743     assign( ta, getIReg(4, R_ESP) );
6744     assign( t1, loadLE(Ity_I16, mkexpr(ta)) );
6745
6746     putIReg(4, R_ESP, binop(Iop_Add32, mkexpr(ta), mkU32(sz)) );
6747     putSReg( sreg, mkexpr(t1) );
6748     DIP("pop%c %s\n", sz==2 ? 'w' : 'l', nameSReg(sreg));
6749 }
6750
6751 static
6752 void dis_ret ( UInt d32 )
6753 {
6754    IRTemp t1 = newTemp(Ity_I32), t2 = newTemp(Ity_I32);
6755    assign(t1, getIReg(4,R_ESP));
6756    assign(t2, loadLE(Ity_I32,mkexpr(t1)));
6757    putIReg(4, R_ESP,binop(Iop_Add32, mkexpr(t1), mkU32(4+d32)));
6758    jmp_treg(Ijk_Ret,t2);
6759 }
6760
6761 /*------------------------------------------------------------*/
6762 /*--- SSE/SSE2/SSE3 helpers                                ---*/
6763 /*------------------------------------------------------------*/
6764
6765 /* Worker function; do not call directly. 
6766    Handles full width G = G `op` E   and   G = (not G) `op` E.
6767 */
6768
6769 static UInt dis_SSE_E_to_G_all_wrk ( 
6770                UChar sorb, Int delta, 
6771                HChar* opname, IROp op,
6772                Bool   invertG
6773             )
6774 {
6775    HChar   dis_buf[50];
6776    Int     alen;
6777    IRTemp  addr;
6778    UChar   rm = getIByte(delta);
6779    IRExpr* gpart
6780       = invertG ? unop(Iop_NotV128, getXMMReg(gregOfRM(rm)))
6781                 : getXMMReg(gregOfRM(rm));
6782    if (epartIsReg(rm)) {
6783       putXMMReg( gregOfRM(rm), 
6784                  binop(op, gpart,
6785                            getXMMReg(eregOfRM(rm))) );
6786       DIP("%s %s,%s\n", opname,
6787                         nameXMMReg(eregOfRM(rm)),
6788                         nameXMMReg(gregOfRM(rm)) );
6789       return delta+1;
6790    } else {
6791       addr = disAMode ( &alen, sorb, delta, dis_buf );
6792       putXMMReg( gregOfRM(rm), 
6793                  binop(op, gpart,
6794                            loadLE(Ity_V128, mkexpr(addr))) );
6795       DIP("%s %s,%s\n", opname,
6796                         dis_buf,
6797                         nameXMMReg(gregOfRM(rm)) );
6798       return delta+alen;
6799    }
6800 }
6801
6802
6803 /* All lanes SSE binary operation, G = G `op` E. */
6804
6805 static
6806 UInt dis_SSE_E_to_G_all ( UChar sorb, Int delta, HChar* opname, IROp op )
6807 {
6808    return dis_SSE_E_to_G_all_wrk( sorb, delta, opname, op, False );
6809 }
6810
6811 /* All lanes SSE binary operation, G = (not G) `op` E. */
6812
6813 static
6814 UInt dis_SSE_E_to_G_all_invG ( UChar sorb, Int delta, 
6815                                HChar* opname, IROp op )
6816 {
6817    return dis_SSE_E_to_G_all_wrk( sorb, delta, opname, op, True );
6818 }
6819
6820
6821 /* Lowest 32-bit lane only SSE binary operation, G = G `op` E. */
6822
6823 static UInt dis_SSE_E_to_G_lo32 ( UChar sorb, Int delta, 
6824                                   HChar* opname, IROp op )
6825 {
6826    HChar   dis_buf[50];
6827    Int     alen;
6828    IRTemp  addr;
6829    UChar   rm = getIByte(delta);
6830    IRExpr* gpart = getXMMReg(gregOfRM(rm));
6831    if (epartIsReg(rm)) {
6832       putXMMReg( gregOfRM(rm), 
6833                  binop(op, gpart,
6834                            getXMMReg(eregOfRM(rm))) );
6835       DIP("%s %s,%s\n", opname,
6836                         nameXMMReg(eregOfRM(rm)),
6837                         nameXMMReg(gregOfRM(rm)) );
6838       return delta+1;
6839    } else {
6840       /* We can only do a 32-bit memory read, so the upper 3/4 of the
6841          E operand needs to be made simply of zeroes. */
6842       IRTemp epart = newTemp(Ity_V128);
6843       addr = disAMode ( &alen, sorb, delta, dis_buf );
6844       assign( epart, unop( Iop_32UtoV128,
6845                            loadLE(Ity_I32, mkexpr(addr))) );
6846       putXMMReg( gregOfRM(rm), 
6847                  binop(op, gpart, mkexpr(epart)) );
6848       DIP("%s %s,%s\n", opname,
6849                         dis_buf,
6850                         nameXMMReg(gregOfRM(rm)) );
6851       return delta+alen;
6852    }
6853 }
6854
6855
6856 /* Lower 64-bit lane only SSE binary operation, G = G `op` E. */
6857
6858 static UInt dis_SSE_E_to_G_lo64 ( UChar sorb, Int delta, 
6859                                   HChar* opname, IROp op )
6860 {
6861    HChar   dis_buf[50];
6862    Int     alen;
6863    IRTemp  addr;
6864    UChar   rm = getIByte(delta);
6865    IRExpr* gpart = getXMMReg(gregOfRM(rm));
6866    if (epartIsReg(rm)) {
6867       putXMMReg( gregOfRM(rm), 
6868                  binop(op, gpart,
6869                            getXMMReg(eregOfRM(rm))) );
6870       DIP("%s %s,%s\n", opname,
6871                         nameXMMReg(eregOfRM(rm)),
6872                         nameXMMReg(gregOfRM(rm)) );
6873       return delta+1;
6874    } else {
6875       /* We can only do a 64-bit memory read, so the upper half of the
6876          E operand needs to be made simply of zeroes. */
6877       IRTemp epart = newTemp(Ity_V128);
6878       addr = disAMode ( &alen, sorb, delta, dis_buf );
6879       assign( epart, unop( Iop_64UtoV128,
6880                            loadLE(Ity_I64, mkexpr(addr))) );
6881       putXMMReg( gregOfRM(rm), 
6882                  binop(op, gpart, mkexpr(epart)) );
6883       DIP("%s %s,%s\n", opname,
6884                         dis_buf,
6885                         nameXMMReg(gregOfRM(rm)) );
6886       return delta+alen;
6887    }
6888 }
6889
6890
6891 /* All lanes unary SSE operation, G = op(E). */
6892
6893 static UInt dis_SSE_E_to_G_unary_all ( 
6894                UChar sorb, Int delta, 
6895                HChar* opname, IROp op
6896             )
6897 {
6898    HChar   dis_buf[50];
6899    Int     alen;
6900    IRTemp  addr;
6901    UChar   rm = getIByte(delta);
6902    if (epartIsReg(rm)) {
6903       putXMMReg( gregOfRM(rm), 
6904                  unop(op, getXMMReg(eregOfRM(rm))) );
6905       DIP("%s %s,%s\n", opname,
6906                         nameXMMReg(eregOfRM(rm)),
6907                         nameXMMReg(gregOfRM(rm)) );
6908       return delta+1;
6909    } else {
6910       addr = disAMode ( &alen, sorb, delta, dis_buf );
6911       putXMMReg( gregOfRM(rm), 
6912                  unop(op, loadLE(Ity_V128, mkexpr(addr))) );
6913       DIP("%s %s,%s\n", opname,
6914                         dis_buf,
6915                         nameXMMReg(gregOfRM(rm)) );
6916       return delta+alen;
6917    }
6918 }
6919
6920
6921 /* Lowest 32-bit lane only unary SSE operation, G = op(E). */
6922
6923 static UInt dis_SSE_E_to_G_unary_lo32 ( 
6924                UChar sorb, Int delta, 
6925                HChar* opname, IROp op
6926             )
6927 {
6928    /* First we need to get the old G value and patch the low 32 bits
6929       of the E operand into it.  Then apply op and write back to G. */
6930    HChar   dis_buf[50];
6931    Int     alen;
6932    IRTemp  addr;
6933    UChar   rm = getIByte(delta);
6934    IRTemp  oldG0 = newTemp(Ity_V128);
6935    IRTemp  oldG1 = newTemp(Ity_V128);
6936
6937    assign( oldG0, getXMMReg(gregOfRM(rm)) );
6938
6939    if (epartIsReg(rm)) {
6940       assign( oldG1, 
6941               binop( Iop_SetV128lo32,
6942                      mkexpr(oldG0),
6943                      getXMMRegLane32(eregOfRM(rm), 0)) );
6944       putXMMReg( gregOfRM(rm), unop(op, mkexpr(oldG1)) );
6945       DIP("%s %s,%s\n", opname,
6946                         nameXMMReg(eregOfRM(rm)),
6947                         nameXMMReg(gregOfRM(rm)) );
6948       return delta+1;
6949    } else {
6950       addr = disAMode ( &alen, sorb, delta, dis_buf );
6951       assign( oldG1, 
6952               binop( Iop_SetV128lo32,
6953                      mkexpr(oldG0),
6954                      loadLE(Ity_I32, mkexpr(addr)) ));
6955       putXMMReg( gregOfRM(rm), unop(op, mkexpr(oldG1)) );
6956       DIP("%s %s,%s\n", opname,
6957                         dis_buf,
6958                         nameXMMReg(gregOfRM(rm)) );
6959       return delta+alen;
6960    }
6961 }
6962
6963
6964 /* Lowest 64-bit lane only unary SSE operation, G = op(E). */
6965
6966 static UInt dis_SSE_E_to_G_unary_lo64 ( 
6967                UChar sorb, Int delta, 
6968                HChar* opname, IROp op
6969             )
6970 {
6971    /* First we need to get the old G value and patch the low 64 bits
6972       of the E operand into it.  Then apply op and write back to G. */
6973    HChar   dis_buf[50];
6974    Int     alen;
6975    IRTemp  addr;
6976    UChar   rm = getIByte(delta);
6977    IRTemp  oldG0 = newTemp(Ity_V128);
6978    IRTemp  oldG1 = newTemp(Ity_V128);
6979
6980    assign( oldG0, getXMMReg(gregOfRM(rm)) );
6981
6982    if (epartIsReg(rm)) {
6983       assign( oldG1, 
6984               binop( Iop_SetV128lo64,
6985                      mkexpr(oldG0),
6986                      getXMMRegLane64(eregOfRM(rm), 0)) );
6987       putXMMReg( gregOfRM(rm), unop(op, mkexpr(oldG1)) );
6988       DIP("%s %s,%s\n", opname,
6989                         nameXMMReg(eregOfRM(rm)),
6990                         nameXMMReg(gregOfRM(rm)) );
6991       return delta+1;
6992    } else {
6993       addr = disAMode ( &alen, sorb, delta, dis_buf );
6994       assign( oldG1, 
6995               binop( Iop_SetV128lo64,
6996                      mkexpr(oldG0),
6997                      loadLE(Ity_I64, mkexpr(addr)) ));
6998       putXMMReg( gregOfRM(rm), unop(op, mkexpr(oldG1)) );
6999       DIP("%s %s,%s\n", opname,
7000                         dis_buf,
7001                         nameXMMReg(gregOfRM(rm)) );
7002       return delta+alen;
7003    }
7004 }
7005
7006
7007 /* SSE integer binary operation:
7008       G = G `op` E   (eLeft == False)
7009       G = E `op` G   (eLeft == True)
7010 */
7011 static UInt dis_SSEint_E_to_G( 
7012                UChar sorb, Int delta, 
7013                HChar* opname, IROp op,
7014                Bool   eLeft
7015             )
7016 {
7017    HChar   dis_buf[50];
7018    Int     alen;
7019    IRTemp  addr;
7020    UChar   rm = getIByte(delta);
7021    IRExpr* gpart = getXMMReg(gregOfRM(rm));
7022    IRExpr* epart = NULL;
7023    if (epartIsReg(rm)) {
7024       epart = getXMMReg(eregOfRM(rm));
7025       DIP("%s %s,%s\n", opname,
7026                         nameXMMReg(eregOfRM(rm)),
7027                         nameXMMReg(gregOfRM(rm)) );
7028       delta += 1;
7029    } else {
7030       addr  = disAMode ( &alen, sorb, delta, dis_buf );
7031       epart = loadLE(Ity_V128, mkexpr(addr));
7032       DIP("%s %s,%s\n", opname,
7033                         dis_buf,
7034                         nameXMMReg(gregOfRM(rm)) );
7035       delta += alen;
7036    }
7037    putXMMReg( gregOfRM(rm), 
7038               eLeft ? binop(op, epart, gpart)
7039                     : binop(op, gpart, epart) );
7040    return delta;
7041 }
7042
7043
7044 /* Helper for doing SSE FP comparisons. */
7045
7046 static void findSSECmpOp ( Bool* needNot, IROp* op, 
7047                            Int imm8, Bool all_lanes, Int sz )
7048 {
7049    imm8 &= 7;
7050    *needNot = False;
7051    *op      = Iop_INVALID;
7052    if (imm8 >= 4) {
7053       *needNot = True;
7054       imm8 -= 4;
7055    }
7056
7057    if (sz == 4 && all_lanes) {
7058       switch (imm8) {
7059          case 0: *op = Iop_CmpEQ32Fx4; return;
7060          case 1: *op = Iop_CmpLT32Fx4; return;
7061          case 2: *op = Iop_CmpLE32Fx4; return;
7062          case 3: *op = Iop_CmpUN32Fx4; return;
7063          default: break;
7064       }
7065    }
7066    if (sz == 4 && !all_lanes) {
7067       switch (imm8) {
7068          case 0: *op = Iop_CmpEQ32F0x4; return;
7069          case 1: *op = Iop_CmpLT32F0x4; return;
7070          case 2: *op = Iop_CmpLE32F0x4; return;
7071          case 3: *op = Iop_CmpUN32F0x4; return;
7072          default: break;
7073       }
7074    }
7075    if (sz == 8 && all_lanes) {
7076       switch (imm8) {
7077          case 0: *op = Iop_CmpEQ64Fx2; return;
7078          case 1: *op = Iop_CmpLT64Fx2; return;
7079          case 2: *op = Iop_CmpLE64Fx2; return;
7080          case 3: *op = Iop_CmpUN64Fx2; return;
7081          default: break;
7082       }
7083    }
7084    if (sz == 8 && !all_lanes) {
7085       switch (imm8) {
7086          case 0: *op = Iop_CmpEQ64F0x2; return;
7087          case 1: *op = Iop_CmpLT64F0x2; return;
7088          case 2: *op = Iop_CmpLE64F0x2; return;
7089          case 3: *op = Iop_CmpUN64F0x2; return;
7090          default: break;
7091       }
7092    }
7093    vpanic("findSSECmpOp(x86,guest)");
7094 }
7095
7096 /* Handles SSE 32F/64F comparisons. */
7097
7098 static UInt dis_SSEcmp_E_to_G ( UChar sorb, Int delta, 
7099                                 HChar* opname, Bool all_lanes, Int sz )
7100 {
7101    HChar   dis_buf[50];
7102    Int     alen, imm8;
7103    IRTemp  addr;
7104    Bool    needNot = False;
7105    IROp    op      = Iop_INVALID;
7106    IRTemp  plain   = newTemp(Ity_V128);
7107    UChar   rm      = getIByte(delta);
7108    UShort  mask    = 0;
7109    vassert(sz == 4 || sz == 8);
7110    if (epartIsReg(rm)) {
7111       imm8 = getIByte(delta+1);
7112       findSSECmpOp(&needNot, &op, imm8, all_lanes, sz);
7113       assign( plain, binop(op, getXMMReg(gregOfRM(rm)), 
7114                                getXMMReg(eregOfRM(rm))) );
7115       delta += 2;
7116       DIP("%s $%d,%s,%s\n", opname,
7117                             (Int)imm8,
7118                             nameXMMReg(eregOfRM(rm)),
7119                             nameXMMReg(gregOfRM(rm)) );
7120    } else {
7121       addr = disAMode ( &alen, sorb, delta, dis_buf );
7122       imm8 = getIByte(delta+alen);
7123       findSSECmpOp(&needNot, &op, imm8, all_lanes, sz);
7124       assign( plain, 
7125               binop(
7126                  op,
7127                  getXMMReg(gregOfRM(rm)), 
7128                    all_lanes  ? loadLE(Ity_V128, mkexpr(addr))
7129                  : sz == 8    ? unop( Iop_64UtoV128, loadLE(Ity_I64, mkexpr(addr)))
7130                  : /*sz==4*/    unop( Iop_32UtoV128, loadLE(Ity_I32, mkexpr(addr)))
7131              ) 
7132       );
7133       delta += alen+1;
7134       DIP("%s $%d,%s,%s\n", opname,
7135                             (Int)imm8,
7136                             dis_buf,
7137                             nameXMMReg(gregOfRM(rm)) );
7138    }
7139
7140    if (needNot && all_lanes) {
7141       putXMMReg( gregOfRM(rm), 
7142                  unop(Iop_NotV128, mkexpr(plain)) );
7143    }
7144    else
7145    if (needNot && !all_lanes) {
7146       mask = toUShort( sz==4 ? 0x000F : 0x00FF );
7147       putXMMReg( gregOfRM(rm), 
7148                  binop(Iop_XorV128, mkexpr(plain), mkV128(mask)) );
7149    }
7150    else {
7151       putXMMReg( gregOfRM(rm), mkexpr(plain) );
7152    }
7153
7154    return delta;
7155 }
7156
7157
7158 /* Vector by scalar shift of G by the amount specified at the bottom
7159    of E. */
7160
7161 static UInt dis_SSE_shiftG_byE ( UChar sorb, Int delta, 
7162                                  HChar* opname, IROp op )
7163 {
7164    HChar   dis_buf[50];
7165    Int     alen, size;
7166    IRTemp  addr;
7167    Bool    shl, shr, sar;
7168    UChar   rm   = getIByte(delta);
7169    IRTemp  g0   = newTemp(Ity_V128);
7170    IRTemp  g1   = newTemp(Ity_V128);
7171    IRTemp  amt  = newTemp(Ity_I32);
7172    IRTemp  amt8 = newTemp(Ity_I8);
7173    if (epartIsReg(rm)) {
7174       assign( amt, getXMMRegLane32(eregOfRM(rm), 0) );
7175       DIP("%s %s,%s\n", opname,
7176                         nameXMMReg(eregOfRM(rm)),
7177                         nameXMMReg(gregOfRM(rm)) );
7178       delta++;
7179    } else {
7180       addr = disAMode ( &alen, sorb, delta, dis_buf );
7181       assign( amt, loadLE(Ity_I32, mkexpr(addr)) );
7182       DIP("%s %s,%s\n", opname,
7183                         dis_buf,
7184                         nameXMMReg(gregOfRM(rm)) );
7185       delta += alen;
7186    }
7187    assign( g0,   getXMMReg(gregOfRM(rm)) );
7188    assign( amt8, unop(Iop_32to8, mkexpr(amt)) );
7189
7190    shl = shr = sar = False;
7191    size = 0;
7192    switch (op) {
7193       case Iop_ShlN16x8: shl = True; size = 32; break;
7194       case Iop_ShlN32x4: shl = True; size = 32; break;
7195       case Iop_ShlN64x2: shl = True; size = 64; break;
7196       case Iop_SarN16x8: sar = True; size = 16; break;
7197       case Iop_SarN32x4: sar = True; size = 32; break;
7198       case Iop_ShrN16x8: shr = True; size = 16; break;
7199       case Iop_ShrN32x4: shr = True; size = 32; break;
7200       case Iop_ShrN64x2: shr = True; size = 64; break;
7201       default: vassert(0);
7202    }
7203
7204    if (shl || shr) {
7205      assign( 
7206         g1,
7207         IRExpr_Mux0X(
7208            unop(Iop_1Uto8,binop(Iop_CmpLT32U,mkexpr(amt),mkU32(size))),
7209            mkV128(0x0000),
7210            binop(op, mkexpr(g0), mkexpr(amt8))
7211         )
7212      );
7213    } else 
7214    if (sar) {
7215      assign( 
7216         g1,
7217         IRExpr_Mux0X(
7218            unop(Iop_1Uto8,binop(Iop_CmpLT32U,mkexpr(amt),mkU32(size))),
7219            binop(op, mkexpr(g0), mkU8(size-1)),
7220            binop(op, mkexpr(g0), mkexpr(amt8))
7221         )
7222      );
7223    } else {
7224       /*NOTREACHED*/
7225       vassert(0);
7226    }
7227
7228    putXMMReg( gregOfRM(rm), mkexpr(g1) );
7229    return delta;
7230 }
7231
7232
7233 /* Vector by scalar shift of E by an immediate byte. */
7234
7235 static 
7236 UInt dis_SSE_shiftE_imm ( Int delta, HChar* opname, IROp op )
7237 {
7238    Bool    shl, shr, sar;
7239    UChar   rm   = getIByte(delta);
7240    IRTemp  e0   = newTemp(Ity_V128);
7241    IRTemp  e1   = newTemp(Ity_V128);
7242    UChar   amt, size;
7243    vassert(epartIsReg(rm));
7244    vassert(gregOfRM(rm) == 2 
7245            || gregOfRM(rm) == 4 || gregOfRM(rm) == 6);
7246    amt = getIByte(delta+1);
7247    delta += 2;
7248    DIP("%s $%d,%s\n", opname,
7249                       (Int)amt,
7250                       nameXMMReg(eregOfRM(rm)) );
7251    assign( e0, getXMMReg(eregOfRM(rm)) );
7252
7253    shl = shr = sar = False;
7254    size = 0;
7255    switch (op) {
7256       case Iop_ShlN16x8: shl = True; size = 16; break;
7257       case Iop_ShlN32x4: shl = True; size = 32; break;
7258       case Iop_ShlN64x2: shl = True; size = 64; break;
7259       case Iop_SarN16x8: sar = True; size = 16; break;
7260       case Iop_SarN32x4: sar = True; size = 32; break;
7261       case Iop_ShrN16x8: shr = True; size = 16; break;
7262       case Iop_ShrN32x4: shr = True; size = 32; break;
7263       case Iop_ShrN64x2: shr = True; size = 64; break;
7264       default: vassert(0);
7265    }
7266
7267    if (shl || shr) {
7268       assign( e1, amt >= size 
7269                      ? mkV128(0x0000)
7270                      : binop(op, mkexpr(e0), mkU8(amt))
7271       );
7272    } else 
7273    if (sar) {
7274       assign( e1, amt >= size 
7275                      ? binop(op, mkexpr(e0), mkU8(size-1))
7276                      : binop(op, mkexpr(e0), mkU8(amt))
7277       );
7278    } else {
7279       /*NOTREACHED*/
7280       vassert(0);
7281    }
7282
7283    putXMMReg( eregOfRM(rm), mkexpr(e1) );
7284    return delta;
7285 }
7286
7287
7288 /* Get the current SSE rounding mode. */
7289
7290 static IRExpr* /* :: Ity_I32 */ get_sse_roundingmode ( void )
7291 {
7292    return binop( Iop_And32, 
7293                  IRExpr_Get( OFFB_SSEROUND, Ity_I32 ), 
7294                  mkU32(3) );
7295 }
7296
7297 static void put_sse_roundingmode ( IRExpr* sseround )
7298 {
7299    vassert(typeOfIRExpr(irsb->tyenv, sseround) == Ity_I32);
7300    stmt( IRStmt_Put( OFFB_SSEROUND, sseround ) );
7301 }
7302
7303 /* Break a 128-bit value up into four 32-bit ints. */
7304
7305 static void breakup128to32s ( IRTemp t128,
7306                               /*OUTs*/
7307                               IRTemp* t3, IRTemp* t2,
7308                               IRTemp* t1, IRTemp* t0 )
7309 {
7310    IRTemp hi64 = newTemp(Ity_I64);
7311    IRTemp lo64 = newTemp(Ity_I64);
7312    assign( hi64, unop(Iop_V128HIto64, mkexpr(t128)) );
7313    assign( lo64, unop(Iop_V128to64,   mkexpr(t128)) );
7314
7315    vassert(t0 && *t0 == IRTemp_INVALID);
7316    vassert(t1 && *t1 == IRTemp_INVALID);
7317    vassert(t2 && *t2 == IRTemp_INVALID);
7318    vassert(t3 && *t3 == IRTemp_INVALID);
7319
7320    *t0 = newTemp(Ity_I32);
7321    *t1 = newTemp(Ity_I32);
7322    *t2 = newTemp(Ity_I32);
7323    *t3 = newTemp(Ity_I32);
7324    assign( *t0, unop(Iop_64to32,   mkexpr(lo64)) );
7325    assign( *t1, unop(Iop_64HIto32, mkexpr(lo64)) );
7326    assign( *t2, unop(Iop_64to32,   mkexpr(hi64)) );
7327    assign( *t3, unop(Iop_64HIto32, mkexpr(hi64)) );
7328 }
7329
7330 /* Construct a 128-bit value from four 32-bit ints. */
7331
7332 static IRExpr* mk128from32s ( IRTemp t3, IRTemp t2,
7333                               IRTemp t1, IRTemp t0 )
7334 {
7335    return
7336       binop( Iop_64HLtoV128,
7337              binop(Iop_32HLto64, mkexpr(t3), mkexpr(t2)),
7338              binop(Iop_32HLto64, mkexpr(t1), mkexpr(t0))
7339    );
7340 }
7341
7342 /* Break a 64-bit value up into four 16-bit ints. */
7343
7344 static void breakup64to16s ( IRTemp t64,
7345                              /*OUTs*/
7346                              IRTemp* t3, IRTemp* t2,
7347                              IRTemp* t1, IRTemp* t0 )
7348 {
7349    IRTemp hi32 = newTemp(Ity_I32);
7350    IRTemp lo32 = newTemp(Ity_I32);
7351    assign( hi32, unop(Iop_64HIto32, mkexpr(t64)) );
7352    assign( lo32, unop(Iop_64to32,   mkexpr(t64)) );
7353
7354    vassert(t0 && *t0 == IRTemp_INVALID);
7355    vassert(t1 && *t1 == IRTemp_INVALID);
7356    vassert(t2 && *t2 == IRTemp_INVALID);
7357    vassert(t3 && *t3 == IRTemp_INVALID);
7358
7359    *t0 = newTemp(Ity_I16);
7360    *t1 = newTemp(Ity_I16);
7361    *t2 = newTemp(Ity_I16);
7362    *t3 = newTemp(Ity_I16);
7363    assign( *t0, unop(Iop_32to16,   mkexpr(lo32)) );
7364    assign( *t1, unop(Iop_32HIto16, mkexpr(lo32)) );
7365    assign( *t2, unop(Iop_32to16,   mkexpr(hi32)) );
7366    assign( *t3, unop(Iop_32HIto16, mkexpr(hi32)) );
7367 }
7368
7369 /* Construct a 64-bit value from four 16-bit ints. */
7370
7371 static IRExpr* mk64from16s ( IRTemp t3, IRTemp t2,
7372                              IRTemp t1, IRTemp t0 )
7373 {
7374    return
7375       binop( Iop_32HLto64,
7376              binop(Iop_16HLto32, mkexpr(t3), mkexpr(t2)),
7377              binop(Iop_16HLto32, mkexpr(t1), mkexpr(t0))
7378    );
7379 }
7380
7381 /* Generate IR to set the guest %EFLAGS from the pushfl-format image
7382    in the given 32-bit temporary.  The flags that are set are: O S Z A
7383    C P D ID AC.
7384
7385    In all cases, code to set AC is generated.  However, VEX actually
7386    ignores the AC value and so can optionally emit an emulation
7387    warning when it is enabled.  In this routine, an emulation warning
7388    is only emitted if emit_AC_emwarn is True, in which case
7389    next_insn_EIP must be correct (this allows for correct code
7390    generation for popfl/popfw).  If emit_AC_emwarn is False,
7391    next_insn_EIP is unimportant (this allows for easy if kludgey code
7392    generation for IRET.) */
7393
7394 static 
7395 void set_EFLAGS_from_value ( IRTemp t1, 
7396                              Bool   emit_AC_emwarn,
7397                              Addr32 next_insn_EIP )
7398 {
7399    vassert(typeOfIRTemp(irsb->tyenv,t1) == Ity_I32);
7400
7401    /* t1 is the flag word.  Mask out everything except OSZACP and set
7402       the flags thunk to X86G_CC_OP_COPY. */
7403    stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(X86G_CC_OP_COPY) ));
7404    stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0) ));
7405    stmt( IRStmt_Put( OFFB_CC_DEP1, 
7406                      binop(Iop_And32,
7407                            mkexpr(t1), 
7408                            mkU32( X86G_CC_MASK_C | X86G_CC_MASK_P 
7409                                   | X86G_CC_MASK_A | X86G_CC_MASK_Z 
7410                                   | X86G_CC_MASK_S| X86G_CC_MASK_O )
7411                           )
7412                     )
7413        );
7414    /* Set NDEP even though it isn't used.  This makes redundant-PUT
7415       elimination of previous stores to this field work better. */
7416    stmt( IRStmt_Put( OFFB_CC_NDEP, mkU32(0) ));
7417
7418    /* Also need to set the D flag, which is held in bit 10 of t1.
7419       If zero, put 1 in OFFB_DFLAG, else -1 in OFFB_DFLAG. */
7420    stmt( IRStmt_Put( 
7421             OFFB_DFLAG,
7422             IRExpr_Mux0X( 
7423                unop(Iop_32to8,
7424                     binop(Iop_And32, 
7425                           binop(Iop_Shr32, mkexpr(t1), mkU8(10)), 
7426                           mkU32(1))),
7427                mkU32(1), 
7428                mkU32(0xFFFFFFFF))) 
7429        );
7430
7431    /* Set the ID flag */
7432    stmt( IRStmt_Put( 
7433             OFFB_IDFLAG,
7434             IRExpr_Mux0X( 
7435                unop(Iop_32to8,
7436                     binop(Iop_And32, 
7437                           binop(Iop_Shr32, mkexpr(t1), mkU8(21)), 
7438                           mkU32(1))),
7439                mkU32(0), 
7440                mkU32(1))) 
7441        );
7442
7443    /* And set the AC flag.  If setting it 1 to, possibly emit an
7444       emulation warning. */
7445    stmt( IRStmt_Put( 
7446             OFFB_ACFLAG,
7447             IRExpr_Mux0X( 
7448                unop(Iop_32to8,
7449                     binop(Iop_And32, 
7450                           binop(Iop_Shr32, mkexpr(t1), mkU8(18)), 
7451                           mkU32(1))),
7452                mkU32(0), 
7453                mkU32(1))) 
7454        );
7455
7456    if (emit_AC_emwarn) {
7457       put_emwarn( mkU32(EmWarn_X86_acFlag) );
7458       stmt( 
7459          IRStmt_Exit(
7460             binop( Iop_CmpNE32, 
7461                    binop(Iop_And32, mkexpr(t1), mkU32(1<<18)), 
7462                    mkU32(0) ),
7463             Ijk_EmWarn,
7464             IRConst_U32( next_insn_EIP )
7465          )
7466       );
7467    }
7468 }
7469
7470
7471 /* Helper for the SSSE3 (not SSE3) PMULHRSW insns.  Given two 64-bit
7472    values (aa,bb), computes, for each of the 4 16-bit lanes:
7473
7474    (((aa_lane *s32 bb_lane) >>u 14) + 1) >>u 1
7475 */
7476 static IRExpr* dis_PMULHRSW_helper ( IRExpr* aax, IRExpr* bbx )
7477 {
7478    IRTemp aa      = newTemp(Ity_I64);
7479    IRTemp bb      = newTemp(Ity_I64);
7480    IRTemp aahi32s = newTemp(Ity_I64);
7481    IRTemp aalo32s = newTemp(Ity_I64);
7482    IRTemp bbhi32s = newTemp(Ity_I64);
7483    IRTemp bblo32s = newTemp(Ity_I64);
7484    IRTemp rHi     = newTemp(Ity_I64);
7485    IRTemp rLo     = newTemp(Ity_I64);
7486    IRTemp one32x2 = newTemp(Ity_I64);
7487    assign(aa, aax);
7488    assign(bb, bbx);
7489    assign( aahi32s,
7490            binop(Iop_SarN32x2,
7491                  binop(Iop_InterleaveHI16x4, mkexpr(aa), mkexpr(aa)),
7492                  mkU8(16) ));
7493    assign( aalo32s,
7494            binop(Iop_SarN32x2,
7495                  binop(Iop_InterleaveLO16x4, mkexpr(aa), mkexpr(aa)),
7496                  mkU8(16) ));
7497    assign( bbhi32s,
7498            binop(Iop_SarN32x2,
7499                  binop(Iop_InterleaveHI16x4, mkexpr(bb), mkexpr(bb)),
7500                  mkU8(16) ));
7501    assign( bblo32s,
7502            binop(Iop_SarN32x2,
7503                  binop(Iop_InterleaveLO16x4, mkexpr(bb), mkexpr(bb)),
7504                  mkU8(16) ));
7505    assign(one32x2, mkU64( (1ULL << 32) + 1 ));
7506    assign(
7507       rHi,
7508       binop(
7509          Iop_ShrN32x2,
7510          binop(
7511             Iop_Add32x2, 
7512             binop(
7513                Iop_ShrN32x2,
7514                binop(Iop_Mul32x2, mkexpr(aahi32s), mkexpr(bbhi32s)),
7515                mkU8(14)
7516             ),
7517             mkexpr(one32x2)
7518          ),
7519          mkU8(1)
7520       )
7521    );
7522    assign(
7523       rLo,
7524       binop(
7525          Iop_ShrN32x2,
7526          binop(
7527             Iop_Add32x2, 
7528             binop(
7529                Iop_ShrN32x2,
7530                binop(Iop_Mul32x2, mkexpr(aalo32s), mkexpr(bblo32s)),
7531                mkU8(14)
7532             ),
7533             mkexpr(one32x2)
7534          ),
7535          mkU8(1)
7536       )
7537    );
7538    return
7539       binop(Iop_CatEvenLanes16x4, mkexpr(rHi), mkexpr(rLo));
7540 }
7541
7542 /* Helper for the SSSE3 (not SSE3) PSIGN{B,W,D} insns.  Given two 64-bit
7543    values (aa,bb), computes, for each lane:
7544
7545           if aa_lane < 0 then - bb_lane
7546      else if aa_lane > 0 then bb_lane
7547      else 0
7548 */
7549 static IRExpr* dis_PSIGN_helper ( IRExpr* aax, IRExpr* bbx, Int laneszB )
7550 {
7551    IRTemp aa       = newTemp(Ity_I64);
7552    IRTemp bb       = newTemp(Ity_I64);
7553    IRTemp zero     = newTemp(Ity_I64);
7554    IRTemp bbNeg    = newTemp(Ity_I64);
7555    IRTemp negMask  = newTemp(Ity_I64);
7556    IRTemp posMask  = newTemp(Ity_I64);
7557    IROp   opSub    = Iop_INVALID;
7558    IROp   opCmpGTS = Iop_INVALID;
7559
7560    switch (laneszB) {
7561       case 1: opSub = Iop_Sub8x8;  opCmpGTS = Iop_CmpGT8Sx8;  break;
7562       case 2: opSub = Iop_Sub16x4; opCmpGTS = Iop_CmpGT16Sx4; break;
7563       case 4: opSub = Iop_Sub32x2; opCmpGTS = Iop_CmpGT32Sx2; break;
7564       default: vassert(0);
7565    }
7566
7567    assign( aa,      aax );
7568    assign( bb,      bbx );
7569    assign( zero,    mkU64(0) );
7570    assign( bbNeg,   binop(opSub,    mkexpr(zero), mkexpr(bb)) );
7571    assign( negMask, binop(opCmpGTS, mkexpr(zero), mkexpr(aa)) );
7572    assign( posMask, binop(opCmpGTS, mkexpr(aa),   mkexpr(zero)) );
7573
7574    return
7575       binop(Iop_Or64,
7576             binop(Iop_And64, mkexpr(bb),    mkexpr(posMask)),
7577             binop(Iop_And64, mkexpr(bbNeg), mkexpr(negMask)) );
7578
7579 }
7580
7581 /* Helper for the SSSE3 (not SSE3) PABS{B,W,D} insns.  Given a 64-bit
7582    value aa, computes, for each lane
7583
7584    if aa < 0 then -aa else aa
7585
7586    Note that the result is interpreted as unsigned, so that the
7587    absolute value of the most negative signed input can be
7588    represented.
7589 */
7590 static IRExpr* dis_PABS_helper ( IRExpr* aax, Int laneszB )
7591 {
7592    IRTemp aa      = newTemp(Ity_I64);
7593    IRTemp zero    = newTemp(Ity_I64);
7594    IRTemp aaNeg   = newTemp(Ity_I64);
7595    IRTemp negMask = newTemp(Ity_I64);
7596    IRTemp posMask = newTemp(Ity_I64);
7597    IROp   opSub   = Iop_INVALID;
7598    IROp   opSarN  = Iop_INVALID;
7599
7600    switch (laneszB) {
7601       case 1: opSub = Iop_Sub8x8;  opSarN = Iop_SarN8x8;  break;
7602       case 2: opSub = Iop_Sub16x4; opSarN = Iop_SarN16x4; break;
7603       case 4: opSub = Iop_Sub32x2; opSarN = Iop_SarN32x2; break;
7604       default: vassert(0);
7605    }
7606
7607    assign( aa,      aax );
7608    assign( negMask, binop(opSarN, mkexpr(aa), mkU8(8*laneszB-1)) );
7609    assign( posMask, unop(Iop_Not64, mkexpr(negMask)) );
7610    assign( zero,    mkU64(0) );
7611    assign( aaNeg,   binop(opSub, mkexpr(zero), mkexpr(aa)) );
7612    return
7613       binop(Iop_Or64,
7614             binop(Iop_And64, mkexpr(aa),    mkexpr(posMask)),
7615             binop(Iop_And64, mkexpr(aaNeg), mkexpr(negMask)) );
7616 }
7617
7618 static IRExpr* dis_PALIGNR_XMM_helper ( IRTemp hi64,
7619                                         IRTemp lo64, Int byteShift )
7620 {
7621    vassert(byteShift >= 1 && byteShift <= 7);
7622    return
7623       binop(Iop_Or64,
7624             binop(Iop_Shl64, mkexpr(hi64), mkU8(8*(8-byteShift))),
7625             binop(Iop_Shr64, mkexpr(lo64), mkU8(8*byteShift))
7626       );
7627 }
7628
7629 /* Generate a SIGSEGV followed by a restart of the current instruction
7630    if effective_addr is not 16-aligned.  This is required behaviour
7631    for some SSE3 instructions and all 128-bit SSSE3 instructions.
7632    This assumes that guest_RIP_curr_instr is set correctly! */
7633 static void gen_SEGV_if_not_16_aligned ( IRTemp effective_addr )
7634 {
7635    stmt(
7636       IRStmt_Exit(
7637          binop(Iop_CmpNE32,
7638                binop(Iop_And32,mkexpr(effective_addr),mkU32(0xF)),
7639                mkU32(0)),
7640          Ijk_SigSEGV,
7641          IRConst_U32(guest_EIP_curr_instr)
7642       )
7643    );
7644 }
7645
7646
7647 /* Helper for deciding whether a given insn (starting at the opcode
7648    byte) may validly be used with a LOCK prefix.  The following insns
7649    may be used with LOCK when their destination operand is in memory.
7650    AFAICS this is exactly the same for both 32-bit and 64-bit mode.
7651
7652    ADD        80 /0,  81 /0,  82 /0,  83 /0,  00,  01
7653    OR         80 /1,  81 /1,  82 /x,  83 /1,  08,  09
7654    ADC        80 /2,  81 /2,  82 /2,  83 /2,  10,  11
7655    SBB        81 /3,  81 /3,  82 /x,  83 /3,  18,  19
7656    AND        80 /4,  81 /4,  82 /x,  83 /4,  20,  21
7657    SUB        80 /5,  81 /5,  82 /x,  83 /5,  28,  29
7658    XOR        80 /6,  81 /6,  82 /x,  83 /6,  30,  31
7659
7660    DEC        FE /1,  FF /1
7661    INC        FE /0,  FF /0
7662
7663    NEG        F6 /3,  F7 /3
7664    NOT        F6 /2,  F7 /2
7665
7666    XCHG       86, 87
7667
7668    BTC        0F BB,  0F BA /7
7669    BTR        0F B3,  0F BA /6
7670    BTS        0F AB,  0F BA /5
7671
7672    CMPXCHG    0F B0,  0F B1
7673    CMPXCHG8B  0F C7 /1
7674
7675    XADD       0F C0,  0F C1
7676
7677    ------------------------------
7678
7679    80 /0  =  addb $imm8,  rm8
7680    81 /0  =  addl $imm32, rm32  and  addw $imm16, rm16
7681    82 /0  =  addb $imm8,  rm8
7682    83 /0  =  addl $simm8, rm32  and  addw $simm8, rm16
7683
7684    00     =  addb r8,  rm8
7685    01     =  addl r32, rm32  and  addw r16, rm16
7686
7687    Same for ADD OR ADC SBB AND SUB XOR
7688
7689    FE /1  = dec rm8
7690    FF /1  = dec rm32  and  dec rm16
7691
7692    FE /0  = inc rm8
7693    FF /0  = inc rm32  and  inc rm16
7694
7695    F6 /3  = neg rm8
7696    F7 /3  = neg rm32  and  neg rm16
7697
7698    F6 /2  = not rm8
7699    F7 /2  = not rm32  and  not rm16
7700
7701    0F BB     = btcw r16, rm16    and  btcl r32, rm32
7702    OF BA /7  = btcw $imm8, rm16  and  btcw $imm8, rm32
7703
7704    Same for BTS, BTR
7705 */
7706 static Bool can_be_used_with_LOCK_prefix ( UChar* opc )
7707 {
7708    switch (opc[0]) {
7709       case 0x00: case 0x01: case 0x08: case 0x09:
7710       case 0x10: case 0x11: case 0x18: case 0x19:
7711       case 0x20: case 0x21: case 0x28: case 0x29:
7712       case 0x30: case 0x31:
7713          if (!epartIsReg(opc[1]))
7714             return True;
7715          break;
7716
7717       case 0x80: case 0x81: case 0x82: case 0x83:
7718          if (gregOfRM(opc[1]) >= 0 && gregOfRM(opc[1]) <= 6
7719              && !epartIsReg(opc[1]))
7720             return True;
7721          break;
7722
7723       case 0xFE: case 0xFF:
7724          if (gregOfRM(opc[1]) >= 0 && gregOfRM(opc[1]) <= 1
7725              && !epartIsReg(opc[1]))
7726             return True;
7727          break;
7728
7729       case 0xF6: case 0xF7:
7730          if (gregOfRM(opc[1]) >= 2 && gregOfRM(opc[1]) <= 3
7731              && !epartIsReg(opc[1]))
7732             return True;
7733          break;
7734
7735       case 0x86: case 0x87:
7736          if (!epartIsReg(opc[1]))
7737             return True;
7738          break;
7739
7740       case 0x0F: {
7741          switch (opc[1]) {
7742             case 0xBB: case 0xB3: case 0xAB:
7743                if (!epartIsReg(opc[2]))
7744                   return True;
7745                break;
7746             case 0xBA: 
7747                if (gregOfRM(opc[2]) >= 5 && gregOfRM(opc[2]) <= 7
7748                    && !epartIsReg(opc[2]))
7749                   return True;
7750                break;
7751             case 0xB0: case 0xB1:
7752                if (!epartIsReg(opc[2]))
7753                   return True;
7754                break;
7755             case 0xC7: 
7756                if (gregOfRM(opc[2]) == 1 && !epartIsReg(opc[2]) )
7757                   return True;
7758                break;
7759             case 0xC0: case 0xC1:
7760                if (!epartIsReg(opc[2]))
7761                   return True;
7762                break;
7763             default:
7764                break;
7765          } /* switch (opc[1]) */
7766          break;
7767       }
7768
7769       default:
7770          break;
7771    } /* switch (opc[0]) */
7772
7773    return False;
7774 }
7775
7776
7777 /*------------------------------------------------------------*/
7778 /*--- Disassemble a single instruction                     ---*/
7779 /*------------------------------------------------------------*/
7780
7781 /* Disassemble a single instruction into IR.  The instruction is
7782    located in host memory at &guest_code[delta].  *expect_CAS is set
7783    to True if the resulting IR is expected to contain an IRCAS
7784    statement, and False if it's not expected to.  This makes it
7785    possible for the caller of disInstr_X86_WRK to check that
7786    LOCK-prefixed instructions are at least plausibly translated, in
7787    that it becomes possible to check that a (validly) LOCK-prefixed
7788    instruction generates a translation containing an IRCAS, and
7789    instructions without LOCK prefixes don't generate translations
7790    containing an IRCAS.
7791 */
7792 static
7793 DisResult disInstr_X86_WRK (
7794              /*OUT*/Bool* expect_CAS,
7795              Bool         put_IP,
7796              Bool         (*resteerOkFn) ( /*opaque*/void*, Addr64 ),
7797              Bool         resteerCisOk,
7798              void*        callback_opaque,
7799              Long         delta64,
7800              VexArchInfo* archinfo 
7801           )
7802 {
7803    IRType    ty;
7804    IRTemp    addr, t0, t1, t2, t3, t4, t5, t6;
7805    Int       alen;
7806    UChar     opc, modrm, abyte, pre;
7807    UInt      d32;
7808    HChar     dis_buf[50];
7809    Int       am_sz, d_sz, n_prefixes;
7810    DisResult dres;
7811    UChar*    insn; /* used in SSE decoders */
7812
7813    /* The running delta */
7814    Int delta = (Int)delta64;
7815
7816    /* Holds eip at the start of the insn, so that we can print
7817       consistent error messages for unimplemented insns. */
7818    Int delta_start = delta;
7819
7820    /* sz denotes the nominal data-op size of the insn; we change it to
7821       2 if an 0x66 prefix is seen */
7822    Int sz = 4;
7823
7824    /* sorb holds the segment-override-prefix byte, if any.  Zero if no
7825       prefix has been seen, else one of {0x26, 0x3E, 0x64, 0x65}
7826       indicating the prefix.  */
7827    UChar sorb = 0;
7828
7829    /* Gets set to True if a LOCK prefix is seen. */
7830    Bool pfx_lock = False;
7831
7832    /* Set result defaults. */
7833    dres.whatNext   = Dis_Continue;
7834    dres.len        = 0;
7835    dres.continueAt = 0;
7836
7837    *expect_CAS = False;
7838
7839    addr = t0 = t1 = t2 = t3 = t4 = t5 = t6 = IRTemp_INVALID; 
7840
7841    vassert(guest_EIP_bbstart + delta == guest_EIP_curr_instr);
7842    DIP("\t0x%x:  ", guest_EIP_bbstart+delta);
7843
7844    /* We may be asked to update the guest EIP before going further. */
7845    if (put_IP)
7846       stmt( IRStmt_Put( OFFB_EIP, mkU32(guest_EIP_curr_instr)) );
7847
7848    /* Spot "Special" instructions (see comment at top of file). */
7849    {
7850       UChar* code = (UChar*)(guest_code + delta);
7851       /* Spot the 12-byte preamble:
7852          C1C703   roll $3,  %edi
7853          C1C70D   roll $13, %edi
7854          C1C71D   roll $29, %edi
7855          C1C713   roll $19, %edi
7856       */
7857       if (code[ 0] == 0xC1 && code[ 1] == 0xC7 && code[ 2] == 0x03 &&
7858           code[ 3] == 0xC1 && code[ 4] == 0xC7 && code[ 5] == 0x0D &&
7859           code[ 6] == 0xC1 && code[ 7] == 0xC7 && code[ 8] == 0x1D &&
7860           code[ 9] == 0xC1 && code[10] == 0xC7 && code[11] == 0x13) {
7861          /* Got a "Special" instruction preamble.  Which one is it? */
7862          if (code[12] == 0x87 && code[13] == 0xDB /* xchgl %ebx,%ebx */) {
7863             /* %EDX = client_request ( %EAX ) */
7864             DIP("%%edx = client_request ( %%eax )\n");
7865             delta += 14;
7866             jmp_lit(Ijk_ClientReq, guest_EIP_bbstart+delta);
7867             dres.whatNext = Dis_StopHere;
7868             goto decode_success;
7869          }
7870          else
7871          if (code[12] == 0x87 && code[13] == 0xC9 /* xchgl %ecx,%ecx */) {
7872             /* %EAX = guest_NRADDR */
7873             DIP("%%eax = guest_NRADDR\n");
7874             delta += 14;
7875             putIReg(4, R_EAX, IRExpr_Get( OFFB_NRADDR, Ity_I32 ));
7876             goto decode_success;
7877          }
7878          else
7879          if (code[12] == 0x87 && code[13] == 0xD2 /* xchgl %edx,%edx */) {
7880             /* call-noredir *%EAX */
7881             DIP("call-noredir *%%eax\n");
7882             delta += 14;
7883             t1 = newTemp(Ity_I32);
7884             assign(t1, getIReg(4,R_EAX));
7885             t2 = newTemp(Ity_I32);
7886             assign(t2, binop(Iop_Sub32, getIReg(4,R_ESP), mkU32(4)));
7887             putIReg(4, R_ESP, mkexpr(t2));
7888             storeLE( mkexpr(t2), mkU32(guest_EIP_bbstart+delta));
7889             jmp_treg(Ijk_NoRedir,t1);
7890             dres.whatNext = Dis_StopHere;
7891             goto decode_success;
7892          }
7893          /* We don't know what it is. */
7894          goto decode_failure;
7895          /*NOTREACHED*/
7896       }
7897 #if 1
7898       /* To make a syscall in L4Re the guest must access its UTCB.
7899        * The address of the UTCB is stored in %gs, so we look for
7900        * the following instructions:
7901        * 65 a1 00 00 00 00       mov    %gs:0x0,%eax
7902        * 65 8b 0d 00 00 00 00    mov    %gs:0x0,%ecx
7903        * 65 8b 15 00 00 00 00    mov    %gs:0x0,%edx
7904        * 65 8b 3d 00 00 00 00    mov    %gs:0x0,%edi
7905        * 65 8b 35 00 00 00 00    mov    %gs:0x0,%esi
7906        */
7907       if (code[ 0] == 0x65 && code[ 1] == 0xa1 && code[ 2] == 0x0 &&
7908           code[ 3] == 0x0  && code[ 4] == 0x0  && code[ 5] == 0x0) {
7909 //          printf("%x\n", code);
7910 //          printf("0x%x\n", guest_EIP_bbstart+delta);
7911 //          DIP("%%edx = client_request ( %%eax )\n");
7912 //          putIReg(4, R_EAX, mkexpr(0xdeadbeef));
7913 //          vg_enter_kdebug();
7914           delta += 6;
7915           jmp_lit(Ijk_l4_utcb_eax, guest_EIP_bbstart+delta);
7916           dres.whatNext = Dis_StopHere;
7917           goto decode_success;
7918       }
7919       /* utcb -> ebx */
7920       // TODO implement me
7921       /* utcb -> ecx */
7922       if (code[ 0] == 0x65 && code[ 1] == 0x8b && code[ 2] == 0x0d &&
7923           code[ 3] == 0x0  && code[ 4] == 0x0  && code[ 5] == 0x0  && code[ 6] == 0x0) {
7924           delta += 7;
7925           jmp_lit(Ijk_l4_utcb_ecx, guest_EIP_bbstart+delta);
7926           dres.whatNext = Dis_StopHere;
7927           goto decode_success;
7928       }
7929       /* utcb -> edx */
7930       if (code[ 0] == 0x65 && code[ 1] == 0x8b && code[ 2] == 0x15 &&
7931           code[ 3] == 0x0  && code[ 4] == 0x0  && code[ 5] == 0x0  && code[ 6] == 0x0) {
7932           delta += 7;
7933           jmp_lit(Ijk_l4_utcb_edx, guest_EIP_bbstart+delta);
7934           dres.whatNext = Dis_StopHere;
7935           goto decode_success;
7936       }
7937       /* utcb -> edi */
7938       if (code[ 0] == 0x65 && code[ 1] == 0x8b && code[ 2] == 0x3d &&
7939           code[ 3] == 0x0  && code[ 4] == 0x0  && code[ 5] == 0x0  && code[ 6] == 0x0) {
7940           delta += 7;
7941           jmp_lit(Ijk_l4_utcb_edi, guest_EIP_bbstart+delta);
7942           dres.whatNext = Dis_StopHere;
7943           goto decode_success;
7944       }
7945
7946       /* utcb -> esi */
7947       if (code[ 0] == 0x65 && code[ 1] == 0x8b && code[ 2] == 0x35 &&
7948           code[ 3] == 0x0  && code[ 4] == 0x0  && code[ 5] == 0x0  && code[ 6] == 0x0) {
7949           delta += 7;
7950           jmp_lit(Ijk_l4_utcb_esi, guest_EIP_bbstart+delta);
7951           dres.whatNext = Dis_StopHere;
7952           goto decode_success;
7953       }
7954
7955           /* ud2 */
7956           if (code[ 0] == 0x0F && code[ 1] == 0x0B) {
7957                   delta += 2;
7958                   jmp_lit(Ijk_l4_ud2, guest_EIP_bbstart+delta);
7959                   dres.whatNext = Dis_StopHere;
7960                   goto decode_success;
7961           }
7962
7963           /*
7964            * The L4Re artificial trap instruction:
7965            *
7966            * 0x50             push eax
7967            * 0xc1 0xc0 0x42   rol eax, 0x42
7968            * 0xc1 0xc8 0x42   ror eax, 0x42
7969            * 0x58             pop eax
7970            */
7971           if (code[ 0] == 0x50 && code[ 1] == 0xc1 &&
7972                   code[ 2] == 0xc0 && code[ 3] == 0x42 &&
7973                   code[ 4] == 0xc1 && code[ 5] == 0xc8 &&
7974                   code[ 6] == 0x42 && code[ 7] == 0x58) {
7975                   delta += 8;
7976                   jmp_lit(Ijk_l4_artificial, guest_EIP_bbstart + delta);
7977                   dres.whatNext = Dis_StopHere;
7978                   goto decode_success;
7979           }
7980 #endif // L4Re
7981    }
7982
7983    /* Handle a couple of weird-ass NOPs that have been observed in the
7984       wild. */
7985    {
7986       UChar* code = (UChar*)(guest_code + delta);
7987       /* Sun's JVM 1.5.0 uses the following as a NOP:
7988          26 2E 64 65 90  %es:%cs:%fs:%gs:nop */
7989       if (code[0] == 0x26 && code[1] == 0x2E && code[2] == 0x64 
7990           && code[3] == 0x65 && code[4] == 0x90) {
7991          DIP("%%es:%%cs:%%fs:%%gs:nop\n");
7992          delta += 5;
7993          goto decode_success;
7994       }
7995       /* Don't barf on recent binutils padding,
7996          all variants of which are: nopw %cs:0x0(%eax,%eax,1)
7997          66 2e 0f 1f 84 00 00 00 00 00
7998          66 66 2e 0f 1f 84 00 00 00 00 00
7999          66 66 66 2e 0f 1f 84 00 00 00 00 00
8000          66 66 66 66 2e 0f 1f 84 00 00 00 00 00
8001          66 66 66 66 66 2e 0f 1f 84 00 00 00 00 00
8002          66 66 66 66 66 66 2e 0f 1f 84 00 00 00 00 00
8003       */
8004       if (code[0] == 0x66) {
8005          Int data16_cnt;
8006          for (data16_cnt = 1; data16_cnt < 6; data16_cnt++)
8007             if (code[data16_cnt] != 0x66)
8008                break;
8009          if (code[data16_cnt] == 0x2E && code[data16_cnt + 1] == 0x0F
8010              && code[data16_cnt + 2] == 0x1F && code[data16_cnt + 3] == 0x84
8011              && code[data16_cnt + 4] == 0x00 && code[data16_cnt + 5] == 0x00
8012              && code[data16_cnt + 6] == 0x00 && code[data16_cnt + 7] == 0x00
8013              && code[data16_cnt + 8] == 0x00 ) {
8014             DIP("nopw %%cs:0x0(%%eax,%%eax,1)\n");
8015             delta += 9 + data16_cnt;
8016             goto decode_success;
8017          }
8018       }
8019    }       
8020
8021    /* Normal instruction handling starts here. */
8022
8023    /* Deal with some but not all prefixes: 
8024          66(oso)
8025          F0(lock)
8026          2E(cs:) 3E(ds:) 26(es:) 64(fs:) 65(gs:) 36(ss:)
8027       Not dealt with (left in place):
8028          F2 F3
8029    */
8030    n_prefixes = 0;
8031    while (True) {
8032       if (n_prefixes > 7) goto decode_failure;
8033       pre = getUChar(delta);
8034       switch (pre) {
8035          case 0x66: 
8036             sz = 2;
8037             break;
8038          case 0xF0: 
8039             pfx_lock = True; 
8040             *expect_CAS = True;
8041             break;
8042          case 0x3E: /* %DS: */
8043          case 0x26: /* %ES: */
8044          case 0x64: /* %FS: */
8045          case 0x65: /* %GS: */
8046             if (sorb != 0) 
8047                goto decode_failure; /* only one seg override allowed */
8048             sorb = pre;
8049             break;
8050          case 0x2E: { /* %CS: */
8051             /* 2E prefix on a conditional branch instruction is a
8052                branch-prediction hint, which can safely be ignored.  */
8053             UChar op1 = getIByte(delta+1);
8054             UChar op2 = getIByte(delta+2);
8055             if ((op1 >= 0x70 && op1 <= 0x7F)
8056                 || (op1 == 0xE3)
8057                 || (op1 == 0x0F && op2 >= 0x80 && op2 <= 0x8F)) {
8058                if (0) vex_printf("vex x86->IR: ignoring branch hint\n");
8059             } else {
8060                /* All other CS override cases are not handled */
8061                goto decode_failure;
8062             }
8063             break;
8064          }
8065          case 0x36: /* %SS: */
8066             /* SS override cases are not handled */
8067             goto decode_failure;
8068          default: 
8069             goto not_a_prefix;
8070       }
8071       n_prefixes++;
8072       delta++;
8073    }
8074
8075    not_a_prefix:
8076
8077    /* Now we should be looking at the primary opcode byte or the
8078       leading F2 or F3.  Check that any LOCK prefix is actually
8079       allowed. */
8080
8081    if (pfx_lock) {
8082       if (can_be_used_with_LOCK_prefix( (UChar*)&guest_code[delta] )) {
8083          DIP("lock ");
8084       } else {
8085          *expect_CAS = False;
8086          goto decode_failure;
8087       }
8088    }
8089
8090
8091    /* ---------------------------------------------------- */
8092    /* --- The SSE decoder.                             --- */
8093    /* ---------------------------------------------------- */
8094
8095    /* What did I do to deserve SSE ?  Perhaps I was really bad in a
8096       previous life? */
8097
8098    /* Note, this doesn't handle SSE2 or SSE3.  That is handled in a
8099       later section, further on. */
8100
8101    insn = (UChar*)&guest_code[delta];
8102
8103    /* Treat fxsave specially.  It should be doable even on an SSE0
8104       (Pentium-II class) CPU.  Hence be prepared to handle it on
8105       any subarchitecture variant.
8106    */
8107
8108    /* 0F AE /0 = FXSAVE m512 -- write x87 and SSE state to memory */
8109    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xAE
8110        && !epartIsReg(insn[2]) && gregOfRM(insn[2]) == 0) {
8111       IRDirty* d;
8112       modrm = getIByte(delta+2);
8113       vassert(sz == 4);
8114       vassert(!epartIsReg(modrm));
8115
8116       addr = disAMode ( &alen, sorb, delta+2, dis_buf );
8117       delta += 2+alen;
8118
8119       DIP("fxsave %s\n", dis_buf);
8120
8121       /* Uses dirty helper: 
8122             void x86g_do_FXSAVE ( VexGuestX86State*, UInt ) */
8123       d = unsafeIRDirty_0_N ( 
8124              0/*regparms*/, 
8125              "x86g_dirtyhelper_FXSAVE", 
8126              &x86g_dirtyhelper_FXSAVE,
8127              mkIRExprVec_1( mkexpr(addr) )
8128           );
8129       d->needsBBP = True;
8130
8131       /* declare we're writing memory */
8132       d->mFx   = Ifx_Write;
8133       d->mAddr = mkexpr(addr);
8134       d->mSize = 512;
8135
8136       /* declare we're reading guest state */
8137       d->nFxState = 7;
8138
8139       d->fxState[0].fx     = Ifx_Read;
8140       d->fxState[0].offset = OFFB_FTOP;
8141       d->fxState[0].size   = sizeof(UInt);
8142
8143       d->fxState[1].fx     = Ifx_Read;
8144       d->fxState[1].offset = OFFB_FPREGS;
8145       d->fxState[1].size   = 8 * sizeof(ULong);
8146
8147       d->fxState[2].fx     = Ifx_Read;
8148       d->fxState[2].offset = OFFB_FPTAGS;
8149       d->fxState[2].size   = 8 * sizeof(UChar);
8150
8151       d->fxState[3].fx     = Ifx_Read;
8152       d->fxState[3].offset = OFFB_FPROUND;
8153       d->fxState[3].size   = sizeof(UInt);
8154
8155       d->fxState[4].fx     = Ifx_Read;
8156       d->fxState[4].offset = OFFB_FC3210;
8157       d->fxState[4].size   = sizeof(UInt);
8158
8159       d->fxState[5].fx     = Ifx_Read;
8160       d->fxState[5].offset = OFFB_XMM0;
8161       d->fxState[5].size   = 8 * sizeof(U128);
8162
8163       d->fxState[6].fx     = Ifx_Read;
8164       d->fxState[6].offset = OFFB_SSEROUND;
8165       d->fxState[6].size   = sizeof(UInt);
8166
8167       /* Be paranoid ... this assertion tries to ensure the 8 %xmm
8168          images are packed back-to-back.  If not, the value of
8169          d->fxState[5].size is wrong. */
8170       vassert(16 == sizeof(U128));
8171       vassert(OFFB_XMM7 == (OFFB_XMM0 + 7 * 16));
8172
8173       stmt( IRStmt_Dirty(d) );
8174
8175       goto decode_success;
8176    }
8177
8178    /* 0F AE /1 = FXRSTOR m512 -- read x87 and SSE state from memory */
8179    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xAE
8180        && !epartIsReg(insn[2]) && gregOfRM(insn[2]) == 1) {
8181       IRDirty* d;
8182       modrm = getIByte(delta+2);
8183       vassert(sz == 4);
8184       vassert(!epartIsReg(modrm));
8185
8186       addr = disAMode ( &alen, sorb, delta+2, dis_buf );
8187       delta += 2+alen;
8188
8189       DIP("fxrstor %s\n", dis_buf);
8190
8191       /* Uses dirty helper: 
8192             void x86g_do_FXRSTOR ( VexGuestX86State*, UInt ) */
8193       d = unsafeIRDirty_0_N ( 
8194              0/*regparms*/, 
8195              "x86g_dirtyhelper_FXRSTOR", 
8196              &x86g_dirtyhelper_FXRSTOR,
8197              mkIRExprVec_1( mkexpr(addr) )
8198           );
8199       d->needsBBP = True;
8200
8201       /* declare we're reading memory */
8202       d->mFx   = Ifx_Read;
8203       d->mAddr = mkexpr(addr);
8204       d->mSize = 512;
8205
8206       /* declare we're writing guest state */
8207       d->nFxState = 7;
8208
8209       d->fxState[0].fx     = Ifx_Write;
8210       d->fxState[0].offset = OFFB_FTOP;
8211       d->fxState[0].size   = sizeof(UInt);
8212
8213       d->fxState[1].fx     = Ifx_Write;
8214       d->fxState[1].offset = OFFB_FPREGS;
8215       d->fxState[1].size   = 8 * sizeof(ULong);
8216
8217       d->fxState[2].fx     = Ifx_Write;
8218       d->fxState[2].offset = OFFB_FPTAGS;
8219       d->fxState[2].size   = 8 * sizeof(UChar);
8220
8221       d->fxState[3].fx     = Ifx_Write;
8222       d->fxState[3].offset = OFFB_FPROUND;
8223       d->fxState[3].size   = sizeof(UInt);
8224
8225       d->fxState[4].fx     = Ifx_Write;
8226       d->fxState[4].offset = OFFB_FC3210;
8227       d->fxState[4].size   = sizeof(UInt);
8228
8229       d->fxState[5].fx     = Ifx_Write;
8230       d->fxState[5].offset = OFFB_XMM0;
8231       d->fxState[5].size   = 8 * sizeof(U128);
8232
8233       d->fxState[6].fx     = Ifx_Write;
8234       d->fxState[6].offset = OFFB_SSEROUND;
8235       d->fxState[6].size   = sizeof(UInt);
8236
8237       /* Be paranoid ... this assertion tries to ensure the 8 %xmm
8238          images are packed back-to-back.  If not, the value of
8239          d->fxState[5].size is wrong. */
8240       vassert(16 == sizeof(U128));
8241       vassert(OFFB_XMM7 == (OFFB_XMM0 + 7 * 16));
8242
8243       stmt( IRStmt_Dirty(d) );
8244
8245       goto decode_success;
8246    }
8247
8248    /* ------ SSE decoder main ------ */
8249
8250    /* Skip parts of the decoder which don't apply given the stated
8251       guest subarchitecture. */
8252    if (archinfo->hwcaps == 0/*baseline, no sse at all*/)
8253       goto after_sse_decoders;
8254    
8255    /* Otherwise we must be doing sse1 or sse2, so we can at least try
8256       for SSE1 here. */
8257
8258    /* 0F 58 = ADDPS -- add 32Fx4 from R/M to R */
8259    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x58) {
8260       delta = dis_SSE_E_to_G_all( sorb, delta+2, "addps", Iop_Add32Fx4 );
8261       goto decode_success;
8262    }
8263
8264    /* F3 0F 58 = ADDSS -- add 32F0x4 from R/M to R */
8265    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x58) {
8266       vassert(sz == 4);
8267       delta = dis_SSE_E_to_G_lo32( sorb, delta+3, "addss", Iop_Add32F0x4 );
8268       goto decode_success;
8269    }
8270
8271    /* 0F 55 = ANDNPS -- G = (not G) and E */
8272    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x55) {
8273       delta = dis_SSE_E_to_G_all_invG( sorb, delta+2, "andnps", Iop_AndV128 );
8274       goto decode_success;
8275    }
8276
8277    /* 0F 54 = ANDPS -- G = G and E */
8278    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x54) {
8279       delta = dis_SSE_E_to_G_all( sorb, delta+2, "andps", Iop_AndV128 );
8280       goto decode_success;
8281    }
8282
8283    /* 0F C2 = CMPPS -- 32Fx4 comparison from R/M to R */
8284    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xC2) {
8285       delta = dis_SSEcmp_E_to_G( sorb, delta+2, "cmpps", True, 4 );
8286       goto decode_success;
8287    }
8288
8289    /* F3 0F C2 = CMPSS -- 32F0x4 comparison from R/M to R */
8290    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0xC2) {
8291       vassert(sz == 4);
8292       delta = dis_SSEcmp_E_to_G( sorb, delta+3, "cmpss", False, 4 );
8293       goto decode_success;
8294    }
8295
8296    /* 0F 2F = COMISS  -- 32F0x4 comparison G,E, and set ZCP */
8297    /* 0F 2E = UCOMISS -- 32F0x4 comparison G,E, and set ZCP */
8298    if (sz == 4 && insn[0] == 0x0F && (insn[1] == 0x2F || insn[1] == 0x2E)) {
8299       IRTemp argL = newTemp(Ity_F32);
8300       IRTemp argR = newTemp(Ity_F32);
8301       modrm = getIByte(delta+2);
8302       if (epartIsReg(modrm)) {
8303          assign( argR, getXMMRegLane32F( eregOfRM(modrm), 0/*lowest lane*/ ) );
8304          delta += 2+1;
8305          DIP("[u]comiss %s,%s\n", nameXMMReg(eregOfRM(modrm)),
8306                                   nameXMMReg(gregOfRM(modrm)) );
8307       } else {
8308          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
8309          assign( argR, loadLE(Ity_F32, mkexpr(addr)) );
8310          delta += 2+alen;
8311          DIP("[u]comiss %s,%s\n", dis_buf,
8312                                   nameXMMReg(gregOfRM(modrm)) );
8313       }
8314       assign( argL, getXMMRegLane32F( gregOfRM(modrm), 0/*lowest lane*/ ) );
8315
8316       stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(X86G_CC_OP_COPY) ));
8317       stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0) ));
8318       stmt( IRStmt_Put( 
8319                OFFB_CC_DEP1,
8320                binop( Iop_And32,
8321                       binop(Iop_CmpF64, 
8322                             unop(Iop_F32toF64,mkexpr(argL)),
8323                             unop(Iop_F32toF64,mkexpr(argR))),
8324                       mkU32(0x45)
8325           )));
8326       /* Set NDEP even though it isn't used.  This makes redundant-PUT
8327          elimination of previous stores to this field work better. */
8328       stmt( IRStmt_Put( OFFB_CC_NDEP, mkU32(0) ));
8329       goto decode_success;
8330    }
8331
8332    /* 0F 2A = CVTPI2PS -- convert 2 x I32 in mem/mmx to 2 x F32 in low
8333       half xmm */
8334    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x2A) {
8335       IRTemp arg64 = newTemp(Ity_I64);
8336       IRTemp rmode = newTemp(Ity_I32);
8337       vassert(sz == 4);
8338
8339       modrm = getIByte(delta+2);
8340       do_MMX_preamble();
8341       if (epartIsReg(modrm)) {
8342          assign( arg64, getMMXReg(eregOfRM(modrm)) );
8343          delta += 2+1;
8344          DIP("cvtpi2ps %s,%s\n", nameMMXReg(eregOfRM(modrm)),
8345                                  nameXMMReg(gregOfRM(modrm)));
8346       } else {
8347          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
8348          assign( arg64, loadLE(Ity_I64, mkexpr(addr)) );
8349          delta += 2+alen;
8350          DIP("cvtpi2ps %s,%s\n", dis_buf,
8351                                  nameXMMReg(gregOfRM(modrm)) );
8352       }
8353
8354       assign( rmode, get_sse_roundingmode() );
8355
8356       putXMMRegLane32F( 
8357          gregOfRM(modrm), 0,
8358          binop(Iop_F64toF32, 
8359                mkexpr(rmode),
8360                unop(Iop_I32StoF64, 
8361                     unop(Iop_64to32, mkexpr(arg64)) )) );
8362
8363       putXMMRegLane32F(
8364          gregOfRM(modrm), 1, 
8365          binop(Iop_F64toF32, 
8366                mkexpr(rmode),
8367                unop(Iop_I32StoF64,
8368                     unop(Iop_64HIto32, mkexpr(arg64)) )) );
8369
8370       goto decode_success;
8371    }
8372
8373    /* F3 0F 2A = CVTSI2SS -- convert I32 in mem/ireg to F32 in low
8374       quarter xmm */
8375    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x2A) {
8376       IRTemp arg32 = newTemp(Ity_I32);
8377       IRTemp rmode = newTemp(Ity_I32);
8378       vassert(sz == 4);
8379
8380       modrm = getIByte(delta+3);
8381       if (epartIsReg(modrm)) {
8382          assign( arg32, getIReg(4, eregOfRM(modrm)) );
8383          delta += 3+1;
8384          DIP("cvtsi2ss %s,%s\n", nameIReg(4, eregOfRM(modrm)),
8385                                  nameXMMReg(gregOfRM(modrm)));
8386       } else {
8387          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
8388          assign( arg32, loadLE(Ity_I32, mkexpr(addr)) );
8389          delta += 3+alen;
8390          DIP("cvtsi2ss %s,%s\n", dis_buf,
8391                                  nameXMMReg(gregOfRM(modrm)) );
8392       }
8393
8394       assign( rmode, get_sse_roundingmode() );
8395
8396       putXMMRegLane32F( 
8397          gregOfRM(modrm), 0,
8398          binop(Iop_F64toF32,
8399                mkexpr(rmode),
8400                unop(Iop_I32StoF64, mkexpr(arg32)) ) );
8401
8402       goto decode_success;
8403    }
8404
8405    /* 0F 2D = CVTPS2PI -- convert 2 x F32 in mem/low half xmm to 2 x
8406       I32 in mmx, according to prevailing SSE rounding mode */
8407    /* 0F 2C = CVTTPS2PI -- convert 2 x F32 in mem/low half xmm to 2 x
8408       I32 in mmx, rounding towards zero */
8409    if (sz == 4 && insn[0] == 0x0F && (insn[1] == 0x2D || insn[1] == 0x2C)) {
8410       IRTemp dst64  = newTemp(Ity_I64);
8411       IRTemp rmode  = newTemp(Ity_I32);
8412       IRTemp f32lo  = newTemp(Ity_F32);
8413       IRTemp f32hi  = newTemp(Ity_F32);
8414       Bool   r2zero = toBool(insn[1] == 0x2C);
8415
8416       do_MMX_preamble();
8417       modrm = getIByte(delta+2);
8418
8419       if (epartIsReg(modrm)) {
8420          delta += 2+1;
8421          assign(f32lo, getXMMRegLane32F(eregOfRM(modrm), 0));
8422          assign(f32hi, getXMMRegLane32F(eregOfRM(modrm), 1));
8423          DIP("cvt%sps2pi %s,%s\n", r2zero ? "t" : "",
8424                                    nameXMMReg(eregOfRM(modrm)),
8425                                    nameMMXReg(gregOfRM(modrm)));
8426       } else {
8427          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
8428          assign(f32lo, loadLE(Ity_F32, mkexpr(addr)));
8429          assign(f32hi, loadLE(Ity_F32, binop( Iop_Add32, 
8430                                               mkexpr(addr), 
8431                                               mkU32(4) )));
8432          delta += 2+alen;
8433          DIP("cvt%sps2pi %s,%s\n", r2zero ? "t" : "",
8434                                    dis_buf,
8435                                    nameMMXReg(gregOfRM(modrm)));
8436       }
8437
8438       if (r2zero) {
8439          assign(rmode, mkU32((UInt)Irrm_ZERO) );
8440       } else {
8441          assign( rmode, get_sse_roundingmode() );
8442       }
8443
8444       assign( 
8445          dst64,
8446          binop( Iop_32HLto64,
8447                 binop( Iop_F64toI32S, 
8448                        mkexpr(rmode), 
8449                        unop( Iop_F32toF64, mkexpr(f32hi) ) ),
8450                 binop( Iop_F64toI32S, 
8451                        mkexpr(rmode), 
8452                        unop( Iop_F32toF64, mkexpr(f32lo) ) )
8453               )
8454       );
8455
8456       putMMXReg(gregOfRM(modrm), mkexpr(dst64));
8457       goto decode_success;
8458    }
8459
8460    /* F3 0F 2D = CVTSS2SI -- convert F32 in mem/low quarter xmm to
8461       I32 in ireg, according to prevailing SSE rounding mode */
8462    /* F3 0F 2C = CVTTSS2SI -- convert F32 in mem/low quarter xmm to
8463       I32 in ireg, rounding towards zero */
8464    if (insn[0] == 0xF3 && insn[1] == 0x0F 
8465        && (insn[2] == 0x2D || insn[2] == 0x2C)) {
8466       IRTemp rmode = newTemp(Ity_I32);
8467       IRTemp f32lo = newTemp(Ity_F32);
8468       Bool   r2zero = toBool(insn[2] == 0x2C);
8469       vassert(sz == 4);
8470
8471       modrm = getIByte(delta+3);
8472       if (epartIsReg(modrm)) {
8473          delta += 3+1;
8474          assign(f32lo, getXMMRegLane32F(eregOfRM(modrm), 0));
8475          DIP("cvt%sss2si %s,%s\n", r2zero ? "t" : "",
8476                                    nameXMMReg(eregOfRM(modrm)),
8477                                    nameIReg(4, gregOfRM(modrm)));
8478       } else {
8479          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
8480          assign(f32lo, loadLE(Ity_F32, mkexpr(addr)));
8481          delta += 3+alen;
8482          DIP("cvt%sss2si %s,%s\n", r2zero ? "t" : "",
8483                                    dis_buf,
8484                                    nameIReg(4, gregOfRM(modrm)));
8485       }
8486
8487       if (r2zero) {
8488          assign( rmode, mkU32((UInt)Irrm_ZERO) );
8489       } else {
8490          assign( rmode, get_sse_roundingmode() );
8491       }
8492
8493       putIReg(4, gregOfRM(modrm),
8494                  binop( Iop_F64toI32S, 
8495                         mkexpr(rmode), 
8496                         unop( Iop_F32toF64, mkexpr(f32lo) ) )
8497       );
8498
8499       goto decode_success;
8500    }
8501
8502    /* 0F 5E = DIVPS -- div 32Fx4 from R/M to R */
8503    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x5E) {
8504       delta = dis_SSE_E_to_G_all( sorb, delta+2, "divps", Iop_Div32Fx4 );
8505       goto decode_success;
8506    }
8507
8508    /* F3 0F 5E = DIVSS -- div 32F0x4 from R/M to R */
8509    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x5E) {
8510       vassert(sz == 4);
8511       delta = dis_SSE_E_to_G_lo32( sorb, delta+3, "divss", Iop_Div32F0x4 );
8512       goto decode_success;
8513    }
8514
8515    /* 0F AE /2 = LDMXCSR m32 -- load %mxcsr */
8516    if (insn[0] == 0x0F && insn[1] == 0xAE
8517        && !epartIsReg(insn[2]) && gregOfRM(insn[2]) == 2) {
8518
8519       IRTemp t64 = newTemp(Ity_I64);
8520       IRTemp ew = newTemp(Ity_I32);
8521
8522       modrm = getIByte(delta+2);
8523       vassert(!epartIsReg(modrm));
8524       vassert(sz == 4);
8525
8526       addr = disAMode ( &alen, sorb, delta+2, dis_buf );
8527       delta += 2+alen;
8528       DIP("ldmxcsr %s\n", dis_buf);
8529
8530       /* The only thing we observe in %mxcsr is the rounding mode.
8531          Therefore, pass the 32-bit value (SSE native-format control
8532          word) to a clean helper, getting back a 64-bit value, the
8533          lower half of which is the SSEROUND value to store, and the
8534          upper half of which is the emulation-warning token which may
8535          be generated.  
8536       */
8537       /* ULong x86h_check_ldmxcsr ( UInt ); */
8538       assign( t64, mkIRExprCCall(
8539                       Ity_I64, 0/*regparms*/, 
8540                       "x86g_check_ldmxcsr",
8541                       &x86g_check_ldmxcsr, 
8542                       mkIRExprVec_1( loadLE(Ity_I32, mkexpr(addr)) )
8543                    )
8544             );
8545
8546       put_sse_roundingmode( unop(Iop_64to32, mkexpr(t64)) );
8547       assign( ew, unop(Iop_64HIto32, mkexpr(t64) ) );
8548       put_emwarn( mkexpr(ew) );
8549       /* Finally, if an emulation warning was reported, side-exit to
8550          the next insn, reporting the warning, so that Valgrind's
8551          dispatcher sees the warning. */
8552       stmt( 
8553          IRStmt_Exit(
8554             binop(Iop_CmpNE32, mkexpr(ew), mkU32(0)),
8555             Ijk_EmWarn,
8556             IRConst_U32( ((Addr32)guest_EIP_bbstart)+delta)
8557          )
8558       );
8559       goto decode_success;
8560    }
8561
8562    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
8563    /* 0F F7 = MASKMOVQ -- 8x8 masked store */
8564    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xF7) {
8565       Bool ok = False;
8566       delta = dis_MMX( &ok, sorb, sz, delta+1 );
8567       if (!ok)
8568          goto decode_failure;
8569       goto decode_success;
8570    }
8571
8572    /* 0F 5F = MAXPS -- max 32Fx4 from R/M to R */
8573    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x5F) {
8574       delta = dis_SSE_E_to_G_all( sorb, delta+2, "maxps", Iop_Max32Fx4 );
8575       goto decode_success;
8576    }
8577
8578    /* F3 0F 5F = MAXSS -- max 32F0x4 from R/M to R */
8579    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x5F) {
8580       vassert(sz == 4);
8581       delta = dis_SSE_E_to_G_lo32( sorb, delta+3, "maxss", Iop_Max32F0x4 );
8582       goto decode_success;
8583    }
8584
8585    /* 0F 5D = MINPS -- min 32Fx4 from R/M to R */
8586    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x5D) {
8587       delta = dis_SSE_E_to_G_all( sorb, delta+2, "minps", Iop_Min32Fx4 );
8588       goto decode_success;
8589    }
8590
8591    /* F3 0F 5D = MINSS -- min 32F0x4 from R/M to R */
8592    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x5D) {
8593       vassert(sz == 4);
8594       delta = dis_SSE_E_to_G_lo32( sorb, delta+3, "minss", Iop_Min32F0x4 );
8595       goto decode_success;
8596    }
8597
8598    /* 0F 28 = MOVAPS -- move from E (mem or xmm) to G (xmm). */
8599    /* 0F 10 = MOVUPS -- move from E (mem or xmm) to G (xmm). */
8600    if (sz == 4 && insn[0] == 0x0F && (insn[1] == 0x28 || insn[1] == 0x10)) {
8601       modrm = getIByte(delta+2);
8602       if (epartIsReg(modrm)) {
8603          putXMMReg( gregOfRM(modrm), 
8604                     getXMMReg( eregOfRM(modrm) ));
8605          DIP("mov[ua]ps %s,%s\n", nameXMMReg(eregOfRM(modrm)),
8606                                   nameXMMReg(gregOfRM(modrm)));
8607          delta += 2+1;
8608       } else {
8609          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
8610          putXMMReg( gregOfRM(modrm), 
8611                     loadLE(Ity_V128, mkexpr(addr)) );
8612          DIP("mov[ua]ps %s,%s\n", dis_buf,
8613                                   nameXMMReg(gregOfRM(modrm)));
8614          delta += 2+alen;
8615       }
8616       goto decode_success;
8617    }
8618
8619    /* 0F 29 = MOVAPS -- move from G (xmm) to E (mem or xmm). */
8620    /* 0F 11 = MOVUPS -- move from G (xmm) to E (mem or xmm). */
8621    if (sz == 4 && insn[0] == 0x0F 
8622        && (insn[1] == 0x29 || insn[1] == 0x11)) {
8623       modrm = getIByte(delta+2);
8624       if (epartIsReg(modrm)) {
8625          /* fall through; awaiting test case */
8626       } else {
8627          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
8628          storeLE( mkexpr(addr), getXMMReg(gregOfRM(modrm)) );
8629          DIP("mov[ua]ps %s,%s\n", nameXMMReg(gregOfRM(modrm)),
8630                                   dis_buf );
8631          delta += 2+alen;
8632          goto decode_success;
8633       }
8634    }
8635
8636    /* 0F 16 = MOVHPS -- move from mem to high half of XMM. */
8637    /* 0F 16 = MOVLHPS -- move from lo half to hi half of XMM. */
8638    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x16) {
8639       modrm = getIByte(delta+2);
8640       if (epartIsReg(modrm)) {
8641          delta += 2+1;
8642          putXMMRegLane64( gregOfRM(modrm), 1/*upper lane*/,
8643                           getXMMRegLane64( eregOfRM(modrm), 0 ) );
8644          DIP("movhps %s,%s\n", nameXMMReg(eregOfRM(modrm)), 
8645                                nameXMMReg(gregOfRM(modrm)));
8646       } else {
8647          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
8648          delta += 2+alen;
8649          putXMMRegLane64( gregOfRM(modrm), 1/*upper lane*/,
8650                           loadLE(Ity_I64, mkexpr(addr)) );
8651          DIP("movhps %s,%s\n", dis_buf, 
8652                                nameXMMReg( gregOfRM(modrm) ));
8653       }
8654       goto decode_success;
8655    }
8656
8657    /* 0F 17 = MOVHPS -- move from high half of XMM to mem. */
8658    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x17) {
8659       if (!epartIsReg(insn[2])) {
8660          delta += 2;
8661          addr = disAMode ( &alen, sorb, delta, dis_buf );
8662          delta += alen;
8663          storeLE( mkexpr(addr), 
8664                   getXMMRegLane64( gregOfRM(insn[2]),
8665                                    1/*upper lane*/ ) );
8666          DIP("movhps %s,%s\n", nameXMMReg( gregOfRM(insn[2]) ),
8667                                dis_buf);
8668          goto decode_success;
8669       }
8670       /* else fall through */
8671    }
8672
8673    /* 0F 12 = MOVLPS -- move from mem to low half of XMM. */
8674    /* OF 12 = MOVHLPS -- from from hi half to lo half of XMM. */
8675    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x12) {
8676       modrm = getIByte(delta+2);
8677       if (epartIsReg(modrm)) {
8678          delta += 2+1;
8679          putXMMRegLane64( gregOfRM(modrm),  
8680                           0/*lower lane*/,
8681                           getXMMRegLane64( eregOfRM(modrm), 1 ));
8682          DIP("movhlps %s, %s\n", nameXMMReg(eregOfRM(modrm)), 
8683                                  nameXMMReg(gregOfRM(modrm)));
8684       } else {
8685          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
8686          delta += 2+alen;
8687          putXMMRegLane64( gregOfRM(modrm),  0/*lower lane*/,
8688                           loadLE(Ity_I64, mkexpr(addr)) );
8689          DIP("movlps %s, %s\n", 
8690              dis_buf, nameXMMReg( gregOfRM(modrm) ));
8691       }
8692       goto decode_success;
8693    }
8694
8695    /* 0F 13 = MOVLPS -- move from low half of XMM to mem. */
8696    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x13) {
8697       if (!epartIsReg(insn[2])) {
8698          delta += 2;
8699          addr = disAMode ( &alen, sorb, delta, dis_buf );
8700          delta += alen;
8701          storeLE( mkexpr(addr), 
8702                   getXMMRegLane64( gregOfRM(insn[2]), 
8703                                    0/*lower lane*/ ) );
8704          DIP("movlps %s, %s\n", nameXMMReg( gregOfRM(insn[2]) ),
8705                                 dis_buf);
8706          goto decode_success;
8707       }
8708       /* else fall through */
8709    }
8710
8711    /* 0F 50 = MOVMSKPS - move 4 sign bits from 4 x F32 in xmm(E)
8712       to 4 lowest bits of ireg(G) */
8713    if (insn[0] == 0x0F && insn[1] == 0x50) {
8714       modrm = getIByte(delta+2);
8715       if (sz == 4 && epartIsReg(modrm)) {
8716          Int src;
8717          t0 = newTemp(Ity_I32);
8718          t1 = newTemp(Ity_I32);
8719          t2 = newTemp(Ity_I32);
8720          t3 = newTemp(Ity_I32);
8721          delta += 2+1;
8722          src = eregOfRM(modrm);
8723          assign( t0, binop( Iop_And32,
8724                             binop(Iop_Shr32, getXMMRegLane32(src,0), mkU8(31)),
8725                             mkU32(1) ));
8726          assign( t1, binop( Iop_And32,
8727                             binop(Iop_Shr32, getXMMRegLane32(src,1), mkU8(30)),
8728                             mkU32(2) ));
8729          assign( t2, binop( Iop_And32,
8730                             binop(Iop_Shr32, getXMMRegLane32(src,2), mkU8(29)),
8731                             mkU32(4) ));
8732          assign( t3, binop( Iop_And32,
8733                             binop(Iop_Shr32, getXMMRegLane32(src,3), mkU8(28)),
8734                             mkU32(8) ));
8735          putIReg(4, gregOfRM(modrm),
8736                     binop(Iop_Or32,
8737                           binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
8738                           binop(Iop_Or32, mkexpr(t2), mkexpr(t3))
8739                          )
8740                  );
8741          DIP("movmskps %s,%s\n", nameXMMReg(src), 
8742                                  nameIReg(4, gregOfRM(modrm)));
8743          goto decode_success;
8744       }
8745       /* else fall through */
8746    }
8747
8748    /* 0F 2B = MOVNTPS -- for us, just a plain SSE store. */
8749    /* 66 0F 2B = MOVNTPD -- for us, just a plain SSE store. */
8750    if (insn[0] == 0x0F && insn[1] == 0x2B) {
8751       modrm = getIByte(delta+2);
8752       if (!epartIsReg(modrm)) {
8753          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
8754          storeLE( mkexpr(addr), getXMMReg(gregOfRM(modrm)) );
8755          DIP("movntp%s %s,%s\n", sz==2 ? "d" : "s",
8756                                  dis_buf,
8757                                  nameXMMReg(gregOfRM(modrm)));
8758          delta += 2+alen;
8759          goto decode_success;
8760       }
8761       /* else fall through */
8762    }
8763
8764    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
8765    /* 0F E7 = MOVNTQ -- for us, just a plain MMX store.  Note, the
8766       Intel manual does not say anything about the usual business of
8767       the FP reg tags getting trashed whenever an MMX insn happens.
8768       So we just leave them alone. 
8769    */
8770    if (insn[0] == 0x0F && insn[1] == 0xE7) {
8771       modrm = getIByte(delta+2);
8772       if (sz == 4 && !epartIsReg(modrm)) {
8773          /* do_MMX_preamble(); Intel docs don't specify this */
8774          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
8775          storeLE( mkexpr(addr), getMMXReg(gregOfRM(modrm)) );
8776          DIP("movntq %s,%s\n", dis_buf,
8777                                nameMMXReg(gregOfRM(modrm)));
8778          delta += 2+alen;
8779          goto decode_success;
8780       }
8781       /* else fall through */
8782    }
8783
8784    /* F3 0F 10 = MOVSS -- move 32 bits from E (mem or lo 1/4 xmm) to G
8785       (lo 1/4 xmm).  If E is mem, upper 3/4 of G is zeroed out. */
8786    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x10) {
8787       vassert(sz == 4);
8788       modrm = getIByte(delta+3);
8789       if (epartIsReg(modrm)) {
8790          putXMMRegLane32( gregOfRM(modrm), 0,
8791                           getXMMRegLane32( eregOfRM(modrm), 0 ));
8792          DIP("movss %s,%s\n", nameXMMReg(eregOfRM(modrm)),
8793                               nameXMMReg(gregOfRM(modrm)));
8794          delta += 3+1;
8795       } else {
8796          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
8797          /* zero bits 127:64 */
8798          putXMMRegLane64( gregOfRM(modrm), 1, mkU64(0) ); 
8799          /* zero bits 63:32 */
8800          putXMMRegLane32( gregOfRM(modrm), 1, mkU32(0) ); 
8801          /* write bits 31:0 */
8802          putXMMRegLane32( gregOfRM(modrm), 0,
8803                           loadLE(Ity_I32, mkexpr(addr)) );
8804          DIP("movss %s,%s\n", dis_buf,
8805                               nameXMMReg(gregOfRM(modrm)));
8806          delta += 3+alen;
8807       }
8808       goto decode_success;
8809    }
8810
8811    /* F3 0F 11 = MOVSS -- move 32 bits from G (lo 1/4 xmm) to E (mem
8812       or lo 1/4 xmm). */
8813    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x11) {
8814       vassert(sz == 4);
8815       modrm = getIByte(delta+3);
8816       if (epartIsReg(modrm)) {
8817          /* fall through, we don't yet have a test case */
8818       } else {
8819          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
8820          storeLE( mkexpr(addr),
8821                   getXMMRegLane32(gregOfRM(modrm), 0) );
8822          DIP("movss %s,%s\n", nameXMMReg(gregOfRM(modrm)),
8823                               dis_buf);
8824          delta += 3+alen;
8825          goto decode_success;
8826       }
8827    }
8828
8829    /* 0F 59 = MULPS -- mul 32Fx4 from R/M to R */
8830    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x59) {
8831       delta = dis_SSE_E_to_G_all( sorb, delta+2, "mulps", Iop_Mul32Fx4 );
8832       goto decode_success;
8833    }
8834
8835    /* F3 0F 59 = MULSS -- mul 32F0x4 from R/M to R */
8836    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x59) {
8837       vassert(sz == 4);
8838       delta = dis_SSE_E_to_G_lo32( sorb, delta+3, "mulss", Iop_Mul32F0x4 );
8839       goto decode_success;
8840    }
8841
8842    /* 0F 56 = ORPS -- G = G and E */
8843    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x56) {
8844       delta = dis_SSE_E_to_G_all( sorb, delta+2, "orps", Iop_OrV128 );
8845       goto decode_success;
8846    }
8847
8848    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
8849    /* 0F E0 = PAVGB -- 8x8 unsigned Packed Average, with rounding */
8850    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xE0) {
8851       do_MMX_preamble();
8852       delta = dis_MMXop_regmem_to_reg ( 
8853                 sorb, delta+2, insn[1], "pavgb", False );
8854       goto decode_success;
8855    }
8856
8857    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
8858    /* 0F E3 = PAVGW -- 16x4 unsigned Packed Average, with rounding */
8859    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xE3) {
8860       do_MMX_preamble();
8861       delta = dis_MMXop_regmem_to_reg ( 
8862                 sorb, delta+2, insn[1], "pavgw", False );
8863       goto decode_success;
8864    }
8865
8866    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
8867    /* 0F C5 = PEXTRW -- extract 16-bit field from mmx(E) and put 
8868       zero-extend of it in ireg(G). */
8869    if (insn[0] == 0x0F && insn[1] == 0xC5) {
8870       modrm = insn[2];
8871       if (sz == 4 && epartIsReg(modrm)) {
8872          IRTemp sV = newTemp(Ity_I64);
8873          t5 = newTemp(Ity_I16);
8874          do_MMX_preamble();
8875          assign(sV, getMMXReg(eregOfRM(modrm)));
8876          breakup64to16s( sV, &t3, &t2, &t1, &t0 );
8877          switch (insn[3] & 3) {
8878             case 0:  assign(t5, mkexpr(t0)); break;
8879             case 1:  assign(t5, mkexpr(t1)); break;
8880             case 2:  assign(t5, mkexpr(t2)); break;
8881             case 3:  assign(t5, mkexpr(t3)); break;
8882             default: vassert(0); /*NOTREACHED*/
8883          }
8884          putIReg(4, gregOfRM(modrm), unop(Iop_16Uto32, mkexpr(t5)));
8885          DIP("pextrw $%d,%s,%s\n",
8886              (Int)insn[3], nameMMXReg(eregOfRM(modrm)),
8887                            nameIReg(4,gregOfRM(modrm)));
8888          delta += 4;
8889          goto decode_success;
8890       } 
8891       /* else fall through */
8892    }
8893
8894    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
8895    /* 0F C4 = PINSRW -- get 16 bits from E(mem or low half ireg) and
8896       put it into the specified lane of mmx(G). */
8897    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xC4) {
8898       /* Use t0 .. t3 to hold the 4 original 16-bit lanes of the
8899          mmx reg.  t4 is the new lane value.  t5 is the original
8900          mmx value. t6 is the new mmx value. */
8901       Int lane;
8902       t4 = newTemp(Ity_I16);
8903       t5 = newTemp(Ity_I64);
8904       t6 = newTemp(Ity_I64);
8905       modrm = insn[2];
8906       do_MMX_preamble();
8907
8908       assign(t5, getMMXReg(gregOfRM(modrm)));
8909       breakup64to16s( t5, &t3, &t2, &t1, &t0 );
8910
8911       if (epartIsReg(modrm)) {
8912          assign(t4, getIReg(2, eregOfRM(modrm)));
8913          delta += 3+1;
8914          lane = insn[3+1-1];
8915          DIP("pinsrw $%d,%s,%s\n", (Int)lane, 
8916                                    nameIReg(2,eregOfRM(modrm)),
8917                                    nameMMXReg(gregOfRM(modrm)));
8918       } else {
8919          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
8920          delta += 3+alen;
8921          lane = insn[3+alen-1];
8922          assign(t4, loadLE(Ity_I16, mkexpr(addr)));
8923          DIP("pinsrw $%d,%s,%s\n", (Int)lane, 
8924                                    dis_buf,
8925                                    nameMMXReg(gregOfRM(modrm)));
8926       }
8927
8928       switch (lane & 3) {
8929          case 0:  assign(t6, mk64from16s(t3,t2,t1,t4)); break;
8930          case 1:  assign(t6, mk64from16s(t3,t2,t4,t0)); break;
8931          case 2:  assign(t6, mk64from16s(t3,t4,t1,t0)); break;
8932          case 3:  assign(t6, mk64from16s(t4,t2,t1,t0)); break;
8933          default: vassert(0); /*NOTREACHED*/
8934       }
8935       putMMXReg(gregOfRM(modrm), mkexpr(t6));
8936       goto decode_success;
8937    }
8938
8939    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
8940    /* 0F EE = PMAXSW -- 16x4 signed max */
8941    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xEE) {
8942       do_MMX_preamble();
8943       delta = dis_MMXop_regmem_to_reg ( 
8944                 sorb, delta+2, insn[1], "pmaxsw", False );
8945       goto decode_success;
8946    }
8947
8948    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
8949    /* 0F DE = PMAXUB -- 8x8 unsigned max */
8950    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xDE) {
8951       do_MMX_preamble();
8952       delta = dis_MMXop_regmem_to_reg ( 
8953                 sorb, delta+2, insn[1], "pmaxub", False );
8954       goto decode_success;
8955    }
8956
8957    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
8958    /* 0F EA = PMINSW -- 16x4 signed min */
8959    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xEA) {
8960       do_MMX_preamble();
8961       delta = dis_MMXop_regmem_to_reg ( 
8962                 sorb, delta+2, insn[1], "pminsw", False );
8963       goto decode_success;
8964    }
8965
8966    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
8967    /* 0F DA = PMINUB -- 8x8 unsigned min */
8968    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xDA) {
8969       do_MMX_preamble();
8970       delta = dis_MMXop_regmem_to_reg ( 
8971                 sorb, delta+2, insn[1], "pminub", False );
8972       goto decode_success;
8973    }
8974
8975    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
8976    /* 0F D7 = PMOVMSKB -- extract sign bits from each of 8 lanes in
8977       mmx(G), turn them into a byte, and put zero-extend of it in
8978       ireg(G). */
8979    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xD7) {
8980       modrm = insn[2];
8981       if (epartIsReg(modrm)) {
8982          do_MMX_preamble();
8983          t0 = newTemp(Ity_I64);
8984          t1 = newTemp(Ity_I32);
8985          assign(t0, getMMXReg(eregOfRM(modrm)));
8986          assign(t1, mkIRExprCCall(
8987                        Ity_I32, 0/*regparms*/, 
8988                        "x86g_calculate_mmx_pmovmskb",
8989                        &x86g_calculate_mmx_pmovmskb,
8990                        mkIRExprVec_1(mkexpr(t0))));
8991          putIReg(4, gregOfRM(modrm), mkexpr(t1));
8992          DIP("pmovmskb %s,%s\n", nameMMXReg(eregOfRM(modrm)),
8993                                  nameIReg(4,gregOfRM(modrm)));
8994          delta += 3;
8995          goto decode_success;
8996       } 
8997       /* else fall through */
8998    }
8999
9000    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
9001    /* 0F E4 = PMULUH -- 16x4 hi-half of unsigned widening multiply */
9002    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xE4) {
9003       do_MMX_preamble();
9004       delta = dis_MMXop_regmem_to_reg ( 
9005                 sorb, delta+2, insn[1], "pmuluh", False );
9006       goto decode_success;
9007    }
9008
9009    /* 0F 18 /0 = PREFETCHNTA -- prefetch into caches, */
9010    /* 0F 18 /1 = PREFETCH0   -- with various different hints */
9011    /* 0F 18 /2 = PREFETCH1 */
9012    /* 0F 18 /3 = PREFETCH2 */
9013    if (insn[0] == 0x0F && insn[1] == 0x18
9014        && !epartIsReg(insn[2]) 
9015        && gregOfRM(insn[2]) >= 0 && gregOfRM(insn[2]) <= 3) {
9016       HChar* hintstr = "??";
9017
9018       modrm = getIByte(delta+2);
9019       vassert(!epartIsReg(modrm));
9020
9021       addr = disAMode ( &alen, sorb, delta+2, dis_buf );
9022       delta += 2+alen;
9023
9024       switch (gregOfRM(modrm)) {
9025          case 0: hintstr = "nta"; break;
9026          case 1: hintstr = "t0"; break;
9027          case 2: hintstr = "t1"; break;
9028          case 3: hintstr = "t2"; break;
9029          default: vassert(0); /*NOTREACHED*/
9030       }
9031
9032       DIP("prefetch%s %s\n", hintstr, dis_buf);
9033       goto decode_success;
9034    }
9035
9036    /* 0F 0D /0 = PREFETCH  m8 -- 3DNow! prefetch */
9037    /* 0F 0D /1 = PREFETCHW m8 -- ditto, with some other hint */
9038    if (insn[0] == 0x0F && insn[1] == 0x0D
9039        && !epartIsReg(insn[2]) 
9040        && gregOfRM(insn[2]) >= 0 && gregOfRM(insn[2]) <= 1) {
9041       HChar* hintstr = "??";
9042
9043       modrm = getIByte(delta+2);
9044       vassert(!epartIsReg(modrm));
9045
9046       addr = disAMode ( &alen, sorb, delta+2, dis_buf );
9047       delta += 2+alen;
9048
9049       switch (gregOfRM(modrm)) {
9050          case 0: hintstr = ""; break;
9051          case 1: hintstr = "w"; break;
9052          default: vassert(0); /*NOTREACHED*/
9053       }
9054
9055       DIP("prefetch%s %s\n", hintstr, dis_buf);
9056       goto decode_success;
9057    }
9058
9059    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
9060    /* 0F F6 = PSADBW -- sum of 8Ux8 absolute differences */
9061    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xF6) {
9062       do_MMX_preamble();
9063       delta = dis_MMXop_regmem_to_reg ( 
9064                  sorb, delta+2, insn[1], "psadbw", False );
9065       goto decode_success;
9066    }
9067
9068    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
9069    /* 0F 70 = PSHUFW -- rearrange 4x16 from E(mmx or mem) to G(mmx) */
9070    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x70) {
9071       Int order;
9072       IRTemp sV, dV, s3, s2, s1, s0;
9073       s3 = s2 = s1 = s0 = IRTemp_INVALID;
9074       sV = newTemp(Ity_I64);
9075       dV = newTemp(Ity_I64);
9076       do_MMX_preamble();
9077       modrm = insn[2];
9078       if (epartIsReg(modrm)) {
9079          assign( sV, getMMXReg(eregOfRM(modrm)) );
9080          order = (Int)insn[3];
9081          delta += 2+2;
9082          DIP("pshufw $%d,%s,%s\n", order, 
9083                                    nameMMXReg(eregOfRM(modrm)),
9084                                    nameMMXReg(gregOfRM(modrm)));
9085       } else {
9086          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
9087          assign( sV, loadLE(Ity_I64, mkexpr(addr)) );
9088          order = (Int)insn[2+alen];
9089          delta += 3+alen;
9090          DIP("pshufw $%d,%s,%s\n", order, 
9091                                    dis_buf,
9092                                    nameMMXReg(gregOfRM(modrm)));
9093       }
9094       breakup64to16s( sV, &s3, &s2, &s1, &s0 );
9095
9096 #     define SEL(n) \
9097                 ((n)==0 ? s0 : ((n)==1 ? s1 : ((n)==2 ? s2 : s3)))
9098       assign(dV,
9099              mk64from16s( SEL((order>>6)&3), SEL((order>>4)&3),
9100                           SEL((order>>2)&3), SEL((order>>0)&3) )
9101       );
9102       putMMXReg(gregOfRM(modrm), mkexpr(dV));
9103 #     undef SEL
9104       goto decode_success;
9105    }
9106
9107    /* 0F 53 = RCPPS -- approx reciprocal 32Fx4 from R/M to R */
9108    if (insn[0] == 0x0F && insn[1] == 0x53) {
9109       vassert(sz == 4);
9110       delta = dis_SSE_E_to_G_unary_all( sorb, delta+2, 
9111                                         "rcpps", Iop_Recip32Fx4 );
9112       goto decode_success;
9113    }
9114
9115    /* F3 0F 53 = RCPSS -- approx reciprocal 32F0x4 from R/M to R */
9116    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x53) {
9117       vassert(sz == 4);
9118       delta = dis_SSE_E_to_G_unary_lo32( sorb, delta+3, 
9119                                          "rcpss", Iop_Recip32F0x4 );
9120       goto decode_success;
9121    }
9122
9123    /* 0F 52 = RSQRTPS -- approx reciprocal sqrt 32Fx4 from R/M to R */
9124    if (insn[0] == 0x0F && insn[1] == 0x52) {
9125       vassert(sz == 4);
9126       delta = dis_SSE_E_to_G_unary_all( sorb, delta+2, 
9127                                         "rsqrtps", Iop_RSqrt32Fx4 );
9128       goto decode_success;
9129    }
9130
9131    /* F3 0F 52 = RSQRTSS -- approx reciprocal sqrt 32F0x4 from R/M to R */
9132    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x52) {
9133       vassert(sz == 4);
9134       delta = dis_SSE_E_to_G_unary_lo32( sorb, delta+3, 
9135                                          "rsqrtss", Iop_RSqrt32F0x4 );
9136       goto decode_success;
9137    }
9138
9139    /* 0F AE /7 = SFENCE -- flush pending operations to memory */
9140    if (insn[0] == 0x0F && insn[1] == 0xAE
9141        && epartIsReg(insn[2]) && gregOfRM(insn[2]) == 7) {
9142       vassert(sz == 4);
9143       delta += 3;
9144       /* Insert a memory fence.  It's sometimes important that these
9145          are carried through to the generated code. */
9146       stmt( IRStmt_MBE(Imbe_Fence) );
9147       DIP("sfence\n");
9148       goto decode_success;
9149    }
9150
9151    /* 0F C6 /r ib = SHUFPS -- shuffle packed F32s */
9152    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xC6) {
9153       Int    select;
9154       IRTemp sV, dV;
9155       IRTemp s3, s2, s1, s0, d3, d2, d1, d0;
9156       sV = newTemp(Ity_V128);
9157       dV = newTemp(Ity_V128);
9158       s3 = s2 = s1 = s0 = d3 = d2 = d1 = d0 = IRTemp_INVALID;
9159       modrm = insn[2];
9160       assign( dV, getXMMReg(gregOfRM(modrm)) );
9161
9162       if (epartIsReg(modrm)) {
9163          assign( sV, getXMMReg(eregOfRM(modrm)) );
9164          select = (Int)insn[3];
9165          delta += 2+2;
9166          DIP("shufps $%d,%s,%s\n", select, 
9167                                    nameXMMReg(eregOfRM(modrm)),
9168                                    nameXMMReg(gregOfRM(modrm)));
9169       } else {
9170          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
9171          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
9172          select = (Int)insn[2+alen];
9173          delta += 3+alen;
9174          DIP("shufps $%d,%s,%s\n", select, 
9175                                    dis_buf,
9176                                    nameXMMReg(gregOfRM(modrm)));
9177       }
9178
9179       breakup128to32s( dV, &d3, &d2, &d1, &d0 );
9180       breakup128to32s( sV, &s3, &s2, &s1, &s0 );
9181
9182 #     define SELD(n) ((n)==0 ? d0 : ((n)==1 ? d1 : ((n)==2 ? d2 : d3)))
9183 #     define SELS(n) ((n)==0 ? s0 : ((n)==1 ? s1 : ((n)==2 ? s2 : s3)))
9184
9185       putXMMReg(
9186          gregOfRM(modrm), 
9187          mk128from32s( SELS((select>>6)&3), SELS((select>>4)&3), 
9188                        SELD((select>>2)&3), SELD((select>>0)&3) )
9189       );
9190
9191 #     undef SELD
9192 #     undef SELS
9193
9194       goto decode_success;
9195    }
9196
9197    /* 0F 51 = SQRTPS -- approx sqrt 32Fx4 from R/M to R */
9198    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x51) {
9199       delta = dis_SSE_E_to_G_unary_all( sorb, delta+2, 
9200                                         "sqrtps", Iop_Sqrt32Fx4 );
9201       goto decode_success;
9202    }
9203
9204    /* F3 0F 51 = SQRTSS -- approx sqrt 32F0x4 from R/M to R */
9205    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x51) {
9206       vassert(sz == 4);
9207       delta = dis_SSE_E_to_G_unary_lo32( sorb, delta+3, 
9208                                          "sqrtss", Iop_Sqrt32F0x4 );
9209       goto decode_success;
9210    }
9211
9212    /* 0F AE /3 = STMXCSR m32 -- store %mxcsr */
9213    if (insn[0] == 0x0F && insn[1] == 0xAE
9214        && !epartIsReg(insn[2]) && gregOfRM(insn[2]) == 3) {
9215       modrm = getIByte(delta+2);
9216       vassert(sz == 4);
9217       vassert(!epartIsReg(modrm));
9218
9219       addr = disAMode ( &alen, sorb, delta+2, dis_buf );
9220       delta += 2+alen;
9221
9222       /* Fake up a native SSE mxcsr word.  The only thing it depends
9223          on is SSEROUND[1:0], so call a clean helper to cook it up. 
9224       */
9225       /* UInt x86h_create_mxcsr ( UInt sseround ) */
9226       DIP("stmxcsr %s\n", dis_buf);
9227       storeLE( mkexpr(addr), 
9228                mkIRExprCCall(
9229                   Ity_I32, 0/*regp*/,
9230                   "x86g_create_mxcsr", &x86g_create_mxcsr, 
9231                   mkIRExprVec_1( get_sse_roundingmode() ) 
9232                ) 
9233              );
9234       goto decode_success;
9235    }
9236
9237    /* 0F 5C = SUBPS -- sub 32Fx4 from R/M to R */
9238    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x5C) {
9239       delta = dis_SSE_E_to_G_all( sorb, delta+2, "subps", Iop_Sub32Fx4 );
9240       goto decode_success;
9241    }
9242
9243    /* F3 0F 5C = SUBSS -- sub 32F0x4 from R/M to R */
9244    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x5C) {
9245       vassert(sz == 4);
9246       delta = dis_SSE_E_to_G_lo32( sorb, delta+3, "subss", Iop_Sub32F0x4 );
9247       goto decode_success;
9248    }
9249
9250    /* 0F 15 = UNPCKHPS -- unpack and interleave high part F32s */
9251    /* 0F 14 = UNPCKLPS -- unpack and interleave low part F32s */
9252    /* These just appear to be special cases of SHUFPS */
9253    if (sz == 4 && insn[0] == 0x0F && (insn[1] == 0x15 || insn[1] == 0x14)) {
9254       IRTemp sV, dV;
9255       IRTemp s3, s2, s1, s0, d3, d2, d1, d0;
9256       Bool hi = toBool(insn[1] == 0x15);
9257       sV = newTemp(Ity_V128);
9258       dV = newTemp(Ity_V128);
9259       s3 = s2 = s1 = s0 = d3 = d2 = d1 = d0 = IRTemp_INVALID;
9260       modrm = insn[2];
9261       assign( dV, getXMMReg(gregOfRM(modrm)) );
9262
9263       if (epartIsReg(modrm)) {
9264          assign( sV, getXMMReg(eregOfRM(modrm)) );
9265          delta += 2+1;
9266          DIP("unpck%sps %s,%s\n", hi ? "h" : "l",
9267                                   nameXMMReg(eregOfRM(modrm)),
9268                                   nameXMMReg(gregOfRM(modrm)));
9269       } else {
9270          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
9271          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
9272          delta += 2+alen;
9273          DIP("unpck%sps %s,%s\n", hi ? "h" : "l",
9274                                   dis_buf,
9275                                   nameXMMReg(gregOfRM(modrm)));
9276       }
9277
9278       breakup128to32s( dV, &d3, &d2, &d1, &d0 );
9279       breakup128to32s( sV, &s3, &s2, &s1, &s0 );
9280
9281       if (hi) {
9282          putXMMReg( gregOfRM(modrm), mk128from32s( s3, d3, s2, d2 ) );
9283       } else {
9284          putXMMReg( gregOfRM(modrm), mk128from32s( s1, d1, s0, d0 ) );
9285       }
9286
9287       goto decode_success;
9288    }
9289
9290    /* 0F 57 = XORPS -- G = G and E */
9291    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x57) {
9292       delta = dis_SSE_E_to_G_all( sorb, delta+2, "xorps", Iop_XorV128 );
9293       goto decode_success;
9294    }
9295
9296    /* ---------------------------------------------------- */
9297    /* --- end of the SSE decoder.                      --- */
9298    /* ---------------------------------------------------- */
9299
9300    /* ---------------------------------------------------- */
9301    /* --- start of the SSE2 decoder.                   --- */
9302    /* ---------------------------------------------------- */
9303
9304    /* Skip parts of the decoder which don't apply given the stated
9305       guest subarchitecture. */
9306    if (0 == (archinfo->hwcaps & VEX_HWCAPS_X86_SSE2))
9307       goto after_sse_decoders; /* no SSE2 capabilities */
9308
9309    insn = (UChar*)&guest_code[delta];
9310
9311    /* 66 0F 58 = ADDPD -- add 32Fx4 from R/M to R */
9312    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x58) {
9313       delta = dis_SSE_E_to_G_all( sorb, delta+2, "addpd", Iop_Add64Fx2 );
9314       goto decode_success;
9315    }
9316  
9317    /* F2 0F 58 = ADDSD -- add 64F0x2 from R/M to R */
9318    if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x58) {
9319       vassert(sz == 4);
9320       delta = dis_SSE_E_to_G_lo64( sorb, delta+3, "addsd", Iop_Add64F0x2 );
9321       goto decode_success;
9322    }
9323
9324    /* 66 0F 55 = ANDNPD -- G = (not G) and E */
9325    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x55) {
9326       delta = dis_SSE_E_to_G_all_invG( sorb, delta+2, "andnpd", Iop_AndV128 );
9327       goto decode_success;
9328    }
9329
9330    /* 66 0F 54 = ANDPD -- G = G and E */
9331    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x54) {
9332       delta = dis_SSE_E_to_G_all( sorb, delta+2, "andpd", Iop_AndV128 );
9333       goto decode_success;
9334    }
9335
9336    /* 66 0F C2 = CMPPD -- 64Fx2 comparison from R/M to R */
9337    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xC2) {
9338       delta = dis_SSEcmp_E_to_G( sorb, delta+2, "cmppd", True, 8 );
9339       goto decode_success;
9340    }
9341
9342    /* F2 0F C2 = CMPSD -- 64F0x2 comparison from R/M to R */
9343    if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0xC2) {
9344       vassert(sz == 4);
9345       delta = dis_SSEcmp_E_to_G( sorb, delta+3, "cmpsd", False, 8 );
9346       goto decode_success;
9347    }
9348
9349    /* 66 0F 2F = COMISD  -- 64F0x2 comparison G,E, and set ZCP */
9350    /* 66 0F 2E = UCOMISD -- 64F0x2 comparison G,E, and set ZCP */
9351    if (sz == 2 && insn[0] == 0x0F && (insn[1] == 0x2F || insn[1] == 0x2E)) {
9352       IRTemp argL = newTemp(Ity_F64);
9353       IRTemp argR = newTemp(Ity_F64);
9354       modrm = getIByte(delta+2);
9355       if (epartIsReg(modrm)) {
9356          assign( argR, getXMMRegLane64F( eregOfRM(modrm), 0/*lowest lane*/ ) );
9357          delta += 2+1;
9358          DIP("[u]comisd %s,%s\n", nameXMMReg(eregOfRM(modrm)),
9359                                   nameXMMReg(gregOfRM(modrm)) );
9360       } else {
9361          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
9362          assign( argR, loadLE(Ity_F64, mkexpr(addr)) );
9363          delta += 2+alen;
9364          DIP("[u]comisd %s,%s\n", dis_buf,
9365                                   nameXMMReg(gregOfRM(modrm)) );
9366       }
9367       assign( argL, getXMMRegLane64F( gregOfRM(modrm), 0/*lowest lane*/ ) );
9368
9369       stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(X86G_CC_OP_COPY) ));
9370       stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0) ));
9371       stmt( IRStmt_Put( 
9372                OFFB_CC_DEP1,
9373                binop( Iop_And32,
9374                       binop(Iop_CmpF64, mkexpr(argL), mkexpr(argR)),
9375                       mkU32(0x45)
9376           )));
9377       /* Set NDEP even though it isn't used.  This makes redundant-PUT
9378          elimination of previous stores to this field work better. */
9379       stmt( IRStmt_Put( OFFB_CC_NDEP, mkU32(0) ));
9380       goto decode_success;
9381    }
9382
9383    /* F3 0F E6 = CVTDQ2PD -- convert 2 x I32 in mem/lo half xmm to 2 x
9384       F64 in xmm(G) */
9385    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0xE6) {
9386       IRTemp arg64 = newTemp(Ity_I64);
9387       vassert(sz == 4);
9388
9389       modrm = getIByte(delta+3);
9390       if (epartIsReg(modrm)) {
9391          assign( arg64, getXMMRegLane64(eregOfRM(modrm), 0) );
9392          delta += 3+1;
9393          DIP("cvtdq2pd %s,%s\n", nameXMMReg(eregOfRM(modrm)),
9394                                  nameXMMReg(gregOfRM(modrm)));
9395       } else {
9396          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
9397          assign( arg64, loadLE(Ity_I64, mkexpr(addr)) );
9398          delta += 3+alen;
9399          DIP("cvtdq2pd %s,%s\n", dis_buf,
9400                                  nameXMMReg(gregOfRM(modrm)) );
9401       }
9402
9403       putXMMRegLane64F( 
9404          gregOfRM(modrm), 0,
9405          unop(Iop_I32StoF64, unop(Iop_64to32, mkexpr(arg64)))
9406       );
9407
9408       putXMMRegLane64F(
9409          gregOfRM(modrm), 1, 
9410          unop(Iop_I32StoF64, unop(Iop_64HIto32, mkexpr(arg64)))
9411       );
9412
9413       goto decode_success;
9414    }
9415
9416    /* 0F 5B = CVTDQ2PS -- convert 4 x I32 in mem/xmm to 4 x F32 in
9417       xmm(G) */
9418    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x5B) {
9419       IRTemp argV  = newTemp(Ity_V128);
9420       IRTemp rmode = newTemp(Ity_I32);
9421
9422       modrm = getIByte(delta+2);
9423       if (epartIsReg(modrm)) {
9424          assign( argV, getXMMReg(eregOfRM(modrm)) );
9425          delta += 2+1;
9426          DIP("cvtdq2ps %s,%s\n", nameXMMReg(eregOfRM(modrm)),
9427                                  nameXMMReg(gregOfRM(modrm)));
9428       } else {
9429          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
9430          assign( argV, loadLE(Ity_V128, mkexpr(addr)) );
9431          delta += 2+alen;
9432          DIP("cvtdq2ps %s,%s\n", dis_buf,
9433                                  nameXMMReg(gregOfRM(modrm)) );
9434       }
9435          
9436       assign( rmode, get_sse_roundingmode() );
9437       breakup128to32s( argV, &t3, &t2, &t1, &t0 );
9438
9439 #     define CVT(_t)  binop( Iop_F64toF32,                    \
9440                              mkexpr(rmode),                   \
9441                              unop(Iop_I32StoF64,mkexpr(_t)))
9442       
9443       putXMMRegLane32F( gregOfRM(modrm), 3, CVT(t3) );
9444       putXMMRegLane32F( gregOfRM(modrm), 2, CVT(t2) );
9445       putXMMRegLane32F( gregOfRM(modrm), 1, CVT(t1) );
9446       putXMMRegLane32F( gregOfRM(modrm), 0, CVT(t0) );
9447
9448 #     undef CVT
9449
9450       goto decode_success;
9451    }
9452
9453    /* F2 0F E6 = CVTPD2DQ -- convert 2 x F64 in mem/xmm to 2 x I32 in
9454       lo half xmm(G), and zero upper half */
9455    if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0xE6) {
9456       IRTemp argV  = newTemp(Ity_V128);
9457       IRTemp rmode = newTemp(Ity_I32);
9458       vassert(sz == 4);
9459
9460       modrm = getIByte(delta+3);
9461       if (epartIsReg(modrm)) {
9462          assign( argV, getXMMReg(eregOfRM(modrm)) );
9463          delta += 3+1;
9464          DIP("cvtpd2dq %s,%s\n", nameXMMReg(eregOfRM(modrm)),
9465                                  nameXMMReg(gregOfRM(modrm)));
9466       } else {
9467          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
9468          assign( argV, loadLE(Ity_V128, mkexpr(addr)) );
9469          delta += 3+alen;
9470          DIP("cvtpd2dq %s,%s\n", dis_buf,
9471                                  nameXMMReg(gregOfRM(modrm)) );
9472       }
9473          
9474       assign( rmode, get_sse_roundingmode() );
9475       t0 = newTemp(Ity_F64);
9476       t1 = newTemp(Ity_F64);
9477       assign( t0, unop(Iop_ReinterpI64asF64, 
9478                        unop(Iop_V128to64, mkexpr(argV))) );
9479       assign( t1, unop(Iop_ReinterpI64asF64, 
9480                        unop(Iop_V128HIto64, mkexpr(argV))) );
9481       
9482 #     define CVT(_t)  binop( Iop_F64toI32S,                   \
9483                              mkexpr(rmode),                   \
9484                              mkexpr(_t) )
9485       
9486       putXMMRegLane32( gregOfRM(modrm), 3, mkU32(0) );
9487       putXMMRegLane32( gregOfRM(modrm), 2, mkU32(0) );
9488       putXMMRegLane32( gregOfRM(modrm), 1, CVT(t1) );
9489       putXMMRegLane32( gregOfRM(modrm), 0, CVT(t0) );
9490
9491 #     undef CVT
9492
9493       goto decode_success;
9494    }
9495
9496    /* 66 0F 2D = CVTPD2PI -- convert 2 x F64 in mem/xmm to 2 x
9497       I32 in mmx, according to prevailing SSE rounding mode */
9498    /* 66 0F 2C = CVTTPD2PI -- convert 2 x F64 in mem/xmm to 2 x
9499       I32 in mmx, rounding towards zero */
9500    if (sz == 2 && insn[0] == 0x0F && (insn[1] == 0x2D || insn[1] == 0x2C)) {
9501       IRTemp dst64  = newTemp(Ity_I64);
9502       IRTemp rmode  = newTemp(Ity_I32);
9503       IRTemp f64lo  = newTemp(Ity_F64);
9504       IRTemp f64hi  = newTemp(Ity_F64);
9505       Bool   r2zero = toBool(insn[1] == 0x2C);
9506
9507       do_MMX_preamble();
9508       modrm = getIByte(delta+2);
9509
9510       if (epartIsReg(modrm)) {
9511          delta += 2+1;
9512          assign(f64lo, getXMMRegLane64F(eregOfRM(modrm), 0));
9513          assign(f64hi, getXMMRegLane64F(eregOfRM(modrm), 1));
9514          DIP("cvt%spd2pi %s,%s\n", r2zero ? "t" : "",
9515                                    nameXMMReg(eregOfRM(modrm)),
9516                                    nameMMXReg(gregOfRM(modrm)));
9517       } else {
9518          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
9519          assign(f64lo, loadLE(Ity_F64, mkexpr(addr)));
9520          assign(f64hi, loadLE(Ity_F64, binop( Iop_Add32, 
9521                                               mkexpr(addr), 
9522                                               mkU32(8) )));
9523          delta += 2+alen;
9524          DIP("cvt%spf2pi %s,%s\n", r2zero ? "t" : "",
9525                                    dis_buf,
9526                                    nameMMXReg(gregOfRM(modrm)));
9527       }
9528
9529       if (r2zero) {
9530          assign(rmode, mkU32((UInt)Irrm_ZERO) );
9531       } else {
9532          assign( rmode, get_sse_roundingmode() );
9533       }
9534
9535       assign( 
9536          dst64,
9537          binop( Iop_32HLto64,
9538                 binop( Iop_F64toI32S, mkexpr(rmode), mkexpr(f64hi) ),
9539                 binop( Iop_F64toI32S, mkexpr(rmode), mkexpr(f64lo) )
9540               )
9541       );
9542
9543       putMMXReg(gregOfRM(modrm), mkexpr(dst64));
9544       goto decode_success;
9545    }
9546
9547    /* 66 0F 5A = CVTPD2PS -- convert 2 x F64 in mem/xmm to 2 x F32 in
9548       lo half xmm(G), and zero upper half */
9549    /* Note, this is practically identical to CVTPD2DQ.  It would have
9550       been nicer to merge them together, but the insn[] offsets differ
9551       by one. */
9552    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x5A) {
9553       IRTemp argV  = newTemp(Ity_V128);
9554       IRTemp rmode = newTemp(Ity_I32);
9555
9556       modrm = getIByte(delta+2);
9557       if (epartIsReg(modrm)) {
9558          assign( argV, getXMMReg(eregOfRM(modrm)) );
9559          delta += 2+1;
9560          DIP("cvtpd2ps %s,%s\n", nameXMMReg(eregOfRM(modrm)),
9561                                  nameXMMReg(gregOfRM(modrm)));
9562       } else {
9563          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
9564          assign( argV, loadLE(Ity_V128, mkexpr(addr)) );
9565          delta += 2+alen;
9566          DIP("cvtpd2ps %s,%s\n", dis_buf,
9567                                  nameXMMReg(gregOfRM(modrm)) );
9568       }
9569          
9570       assign( rmode, get_sse_roundingmode() );
9571       t0 = newTemp(Ity_F64);
9572       t1 = newTemp(Ity_F64);
9573       assign( t0, unop(Iop_ReinterpI64asF64, 
9574                        unop(Iop_V128to64, mkexpr(argV))) );
9575       assign( t1, unop(Iop_ReinterpI64asF64, 
9576                        unop(Iop_V128HIto64, mkexpr(argV))) );
9577       
9578 #     define CVT(_t)  binop( Iop_F64toF32,                    \
9579                              mkexpr(rmode),                   \
9580                              mkexpr(_t) )
9581       
9582       putXMMRegLane32(  gregOfRM(modrm), 3, mkU32(0) );
9583       putXMMRegLane32(  gregOfRM(modrm), 2, mkU32(0) );
9584       putXMMRegLane32F( gregOfRM(modrm), 1, CVT(t1) );
9585       putXMMRegLane32F( gregOfRM(modrm), 0, CVT(t0) );
9586
9587 #     undef CVT
9588
9589       goto decode_success;
9590    }
9591
9592    /* 66 0F 2A = CVTPI2PD -- convert 2 x I32 in mem/mmx to 2 x F64 in
9593       xmm(G) */
9594    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x2A) {
9595       IRTemp arg64 = newTemp(Ity_I64);
9596
9597       modrm = getIByte(delta+2);
9598       if (epartIsReg(modrm)) {
9599          /* Only switch to MMX mode if the source is a MMX register.
9600             This is inconsistent with all other instructions which
9601             convert between XMM and (M64 or MMX), which always switch
9602             to MMX mode even if 64-bit operand is M64 and not MMX.  At
9603             least, that's what the Intel docs seem to me to say.
9604             Fixes #210264. */
9605          do_MMX_preamble();
9606          assign( arg64, getMMXReg(eregOfRM(modrm)) );
9607          delta += 2+1;
9608          DIP("cvtpi2pd %s,%s\n", nameMMXReg(eregOfRM(modrm)),
9609                                  nameXMMReg(gregOfRM(modrm)));
9610       } else {
9611          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
9612          assign( arg64, loadLE(Ity_I64, mkexpr(addr)) );
9613          delta += 2+alen;
9614          DIP("cvtpi2pd %s,%s\n", dis_buf,
9615                                  nameXMMReg(gregOfRM(modrm)) );
9616       }
9617
9618       putXMMRegLane64F( 
9619          gregOfRM(modrm), 0,
9620          unop(Iop_I32StoF64, unop(Iop_64to32, mkexpr(arg64)) )
9621       );
9622
9623       putXMMRegLane64F( 
9624          gregOfRM(modrm), 1,
9625          unop(Iop_I32StoF64, unop(Iop_64HIto32, mkexpr(arg64)) )
9626       );
9627
9628       goto decode_success;
9629    }
9630
9631    /* 66 0F 5B = CVTPS2DQ -- convert 4 x F32 in mem/xmm to 4 x I32 in
9632       xmm(G) */
9633    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x5B) {
9634       IRTemp argV  = newTemp(Ity_V128);
9635       IRTemp rmode = newTemp(Ity_I32);
9636
9637       modrm = getIByte(delta+2);
9638       if (epartIsReg(modrm)) {
9639          assign( argV, getXMMReg(eregOfRM(modrm)) );
9640          delta += 2+1;
9641          DIP("cvtps2dq %s,%s\n", nameXMMReg(eregOfRM(modrm)),
9642                                  nameXMMReg(gregOfRM(modrm)));
9643       } else {
9644          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
9645          assign( argV, loadLE(Ity_V128, mkexpr(addr)) );
9646          delta += 2+alen;
9647          DIP("cvtps2dq %s,%s\n", dis_buf,
9648                                  nameXMMReg(gregOfRM(modrm)) );
9649       }
9650          
9651       assign( rmode, get_sse_roundingmode() );
9652       breakup128to32s( argV, &t3, &t2, &t1, &t0 );
9653
9654       /* This is less than ideal.  If it turns out to be a performance
9655          bottleneck it can be improved. */
9656 #     define CVT(_t)                            \
9657         binop( Iop_F64toI32S,                   \
9658                mkexpr(rmode),                   \
9659                unop( Iop_F32toF64,              \
9660                      unop( Iop_ReinterpI32asF32, mkexpr(_t))) )
9661       
9662       putXMMRegLane32( gregOfRM(modrm), 3, CVT(t3) );
9663       putXMMRegLane32( gregOfRM(modrm), 2, CVT(t2) );
9664       putXMMRegLane32( gregOfRM(modrm), 1, CVT(t1) );
9665       putXMMRegLane32( gregOfRM(modrm), 0, CVT(t0) );
9666
9667 #     undef CVT
9668
9669       goto decode_success;
9670    }
9671
9672    /* 0F 5A = CVTPS2PD -- convert 2 x F32 in low half mem/xmm to 2 x
9673       F64 in xmm(G). */
9674    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x5A) {
9675       IRTemp f32lo = newTemp(Ity_F32);
9676       IRTemp f32hi = newTemp(Ity_F32);
9677
9678       modrm = getIByte(delta+2);
9679       if (epartIsReg(modrm)) {
9680          assign( f32lo, getXMMRegLane32F(eregOfRM(modrm), 0) );
9681          assign( f32hi, getXMMRegLane32F(eregOfRM(modrm), 1) );
9682          delta += 2+1;
9683          DIP("cvtps2pd %s,%s\n", nameXMMReg(eregOfRM(modrm)),
9684                                  nameXMMReg(gregOfRM(modrm)));
9685       } else {
9686          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
9687          assign( f32lo, loadLE(Ity_F32, mkexpr(addr)) );
9688          assign( f32hi, loadLE(Ity_F32, 
9689                                binop(Iop_Add32,mkexpr(addr),mkU32(4))) );
9690          delta += 2+alen;
9691          DIP("cvtps2pd %s,%s\n", dis_buf,
9692                                  nameXMMReg(gregOfRM(modrm)) );
9693       }
9694
9695       putXMMRegLane64F( gregOfRM(modrm), 1,
9696                         unop(Iop_F32toF64, mkexpr(f32hi)) );
9697       putXMMRegLane64F( gregOfRM(modrm), 0,
9698                         unop(Iop_F32toF64, mkexpr(f32lo)) );
9699
9700       goto decode_success;
9701    }
9702
9703    /* F2 0F 2D = CVTSD2SI -- convert F64 in mem/low half xmm to
9704       I32 in ireg, according to prevailing SSE rounding mode */
9705    /* F2 0F 2C = CVTTSD2SI -- convert F64 in mem/low half xmm to
9706       I32 in ireg, rounding towards zero */
9707    if (insn[0] == 0xF2 && insn[1] == 0x0F 
9708        && (insn[2] == 0x2D || insn[2] == 0x2C)) {
9709       IRTemp rmode = newTemp(Ity_I32);
9710       IRTemp f64lo = newTemp(Ity_F64);
9711       Bool   r2zero = toBool(insn[2] == 0x2C);
9712       vassert(sz == 4);
9713
9714       modrm = getIByte(delta+3);
9715       if (epartIsReg(modrm)) {
9716          delta += 3+1;
9717          assign(f64lo, getXMMRegLane64F(eregOfRM(modrm), 0));
9718          DIP("cvt%ssd2si %s,%s\n", r2zero ? "t" : "",
9719                                    nameXMMReg(eregOfRM(modrm)),
9720                                    nameIReg(4, gregOfRM(modrm)));
9721       } else {
9722          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
9723          assign(f64lo, loadLE(Ity_F64, mkexpr(addr)));
9724          delta += 3+alen;
9725          DIP("cvt%ssd2si %s,%s\n", r2zero ? "t" : "",
9726                                    dis_buf,
9727                                    nameIReg(4, gregOfRM(modrm)));
9728       }
9729
9730       if (r2zero) {
9731          assign( rmode, mkU32((UInt)Irrm_ZERO) );
9732       } else {
9733          assign( rmode, get_sse_roundingmode() );
9734       }
9735
9736       putIReg(4, gregOfRM(modrm),
9737                  binop( Iop_F64toI32S, mkexpr(rmode), mkexpr(f64lo)) );
9738
9739       goto decode_success;
9740    }
9741
9742    /* F2 0F 5A = CVTSD2SS -- convert F64 in mem/low half xmm to F32 in
9743       low 1/4 xmm(G), according to prevailing SSE rounding mode */
9744    if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x5A) {
9745       IRTemp rmode = newTemp(Ity_I32);
9746       IRTemp f64lo = newTemp(Ity_F64);
9747       vassert(sz == 4);
9748
9749       modrm = getIByte(delta+3);
9750       if (epartIsReg(modrm)) {
9751          delta += 3+1;
9752          assign(f64lo, getXMMRegLane64F(eregOfRM(modrm), 0));
9753          DIP("cvtsd2ss %s,%s\n", nameXMMReg(eregOfRM(modrm)),
9754                                  nameXMMReg(gregOfRM(modrm)));
9755       } else {
9756          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
9757          assign(f64lo, loadLE(Ity_F64, mkexpr(addr)));
9758          delta += 3+alen;
9759          DIP("cvtsd2ss %s,%s\n", dis_buf,
9760                                  nameXMMReg(gregOfRM(modrm)));
9761       }
9762
9763       assign( rmode, get_sse_roundingmode() );
9764       putXMMRegLane32F( 
9765          gregOfRM(modrm), 0, 
9766          binop( Iop_F64toF32, mkexpr(rmode), mkexpr(f64lo) )
9767       );
9768
9769       goto decode_success;
9770    }
9771
9772    /* F2 0F 2A = CVTSI2SD -- convert I32 in mem/ireg to F64 in low
9773       half xmm */
9774    if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x2A) {
9775       IRTemp arg32 = newTemp(Ity_I32);
9776       vassert(sz == 4);
9777
9778       modrm = getIByte(delta+3);
9779       if (epartIsReg(modrm)) {
9780          assign( arg32, getIReg(4, eregOfRM(modrm)) );
9781          delta += 3+1;
9782          DIP("cvtsi2sd %s,%s\n", nameIReg(4, eregOfRM(modrm)),
9783                                  nameXMMReg(gregOfRM(modrm)));
9784       } else {
9785          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
9786          assign( arg32, loadLE(Ity_I32, mkexpr(addr)) );
9787          delta += 3+alen;
9788          DIP("cvtsi2sd %s,%s\n", dis_buf,
9789                                  nameXMMReg(gregOfRM(modrm)) );
9790       }
9791
9792       putXMMRegLane64F( 
9793          gregOfRM(modrm), 0,
9794          unop(Iop_I32StoF64, mkexpr(arg32)) );
9795
9796       goto decode_success;
9797    }
9798
9799    /* F3 0F 5A = CVTSS2SD -- convert F32 in mem/low 1/4 xmm to F64 in
9800       low half xmm(G) */
9801    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x5A) {
9802       IRTemp f32lo = newTemp(Ity_F32);
9803       vassert(sz == 4);
9804
9805       modrm = getIByte(delta+3);
9806       if (epartIsReg(modrm)) {
9807          delta += 3+1;
9808          assign(f32lo, getXMMRegLane32F(eregOfRM(modrm), 0));
9809          DIP("cvtss2sd %s,%s\n", nameXMMReg(eregOfRM(modrm)),
9810                                  nameXMMReg(gregOfRM(modrm)));
9811       } else {
9812          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
9813          assign(f32lo, loadLE(Ity_F32, mkexpr(addr)));
9814          delta += 3+alen;
9815          DIP("cvtss2sd %s,%s\n", dis_buf,
9816                                  nameXMMReg(gregOfRM(modrm)));
9817       }
9818
9819       putXMMRegLane64F( gregOfRM(modrm), 0, 
9820                         unop( Iop_F32toF64, mkexpr(f32lo) ) );
9821
9822       goto decode_success;
9823    }
9824
9825    /* 66 0F E6 = CVTTPD2DQ -- convert 2 x F64 in mem/xmm to 2 x I32 in
9826       lo half xmm(G), and zero upper half, rounding towards zero */
9827    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xE6) {
9828       IRTemp argV  = newTemp(Ity_V128);
9829       IRTemp rmode = newTemp(Ity_I32);
9830
9831       modrm = getIByte(delta+2);
9832       if (epartIsReg(modrm)) {
9833          assign( argV, getXMMReg(eregOfRM(modrm)) );
9834          delta += 2+1;
9835          DIP("cvttpd2dq %s,%s\n", nameXMMReg(eregOfRM(modrm)),
9836                                   nameXMMReg(gregOfRM(modrm)));
9837       } else {
9838          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
9839          assign( argV, loadLE(Ity_V128, mkexpr(addr)) );
9840          delta += 2+alen;
9841          DIP("cvttpd2dq %s,%s\n", dis_buf,
9842                                   nameXMMReg(gregOfRM(modrm)) );
9843       }
9844
9845       assign( rmode, mkU32((UInt)Irrm_ZERO) );
9846
9847       t0 = newTemp(Ity_F64);
9848       t1 = newTemp(Ity_F64);
9849       assign( t0, unop(Iop_ReinterpI64asF64, 
9850                        unop(Iop_V128to64, mkexpr(argV))) );
9851       assign( t1, unop(Iop_ReinterpI64asF64, 
9852                        unop(Iop_V128HIto64, mkexpr(argV))) );
9853       
9854 #     define CVT(_t)  binop( Iop_F64toI32S,                   \
9855                              mkexpr(rmode),                   \
9856                              mkexpr(_t) )
9857       
9858       putXMMRegLane32( gregOfRM(modrm), 3, mkU32(0) );
9859       putXMMRegLane32( gregOfRM(modrm), 2, mkU32(0) );
9860       putXMMRegLane32( gregOfRM(modrm), 1, CVT(t1) );
9861       putXMMRegLane32( gregOfRM(modrm), 0, CVT(t0) );
9862
9863 #     undef CVT
9864
9865       goto decode_success;
9866    }
9867
9868    /* F3 0F 5B = CVTTPS2DQ -- convert 4 x F32 in mem/xmm to 4 x I32 in
9869       xmm(G), rounding towards zero */
9870    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x5B) {
9871       IRTemp argV  = newTemp(Ity_V128);
9872       IRTemp rmode = newTemp(Ity_I32);
9873       vassert(sz == 4);
9874
9875       modrm = getIByte(delta+3);
9876       if (epartIsReg(modrm)) {
9877          assign( argV, getXMMReg(eregOfRM(modrm)) );
9878          delta += 3+1;
9879          DIP("cvttps2dq %s,%s\n", nameXMMReg(eregOfRM(modrm)),
9880                                   nameXMMReg(gregOfRM(modrm)));
9881       } else {
9882          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
9883          assign( argV, loadLE(Ity_V128, mkexpr(addr)) );
9884          delta += 3+alen;
9885          DIP("cvttps2dq %s,%s\n", dis_buf,
9886                                   nameXMMReg(gregOfRM(modrm)) );
9887       }
9888          
9889       assign( rmode, mkU32((UInt)Irrm_ZERO) );
9890       breakup128to32s( argV, &t3, &t2, &t1, &t0 );
9891
9892       /* This is less than ideal.  If it turns out to be a performance
9893          bottleneck it can be improved. */
9894 #     define CVT(_t)                            \
9895         binop( Iop_F64toI32S,                   \
9896                mkexpr(rmode),                   \
9897                unop( Iop_F32toF64,              \
9898                      unop( Iop_ReinterpI32asF32, mkexpr(_t))) )
9899       
9900       putXMMRegLane32( gregOfRM(modrm), 3, CVT(t3) );
9901       putXMMRegLane32( gregOfRM(modrm), 2, CVT(t2) );
9902       putXMMRegLane32( gregOfRM(modrm), 1, CVT(t1) );
9903       putXMMRegLane32( gregOfRM(modrm), 0, CVT(t0) );
9904
9905 #     undef CVT
9906
9907       goto decode_success;
9908    }
9909
9910    /* 66 0F 5E = DIVPD -- div 64Fx2 from R/M to R */
9911    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x5E) {
9912       delta = dis_SSE_E_to_G_all( sorb, delta+2, "divpd", Iop_Div64Fx2 );
9913       goto decode_success;
9914    }
9915
9916    /* F2 0F 5E = DIVSD -- div 64F0x2 from R/M to R */
9917    if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x5E) {
9918       vassert(sz == 4);
9919       delta = dis_SSE_E_to_G_lo64( sorb, delta+3, "divsd", Iop_Div64F0x2 );
9920       goto decode_success;
9921    }
9922
9923    /* 0F AE /5 = LFENCE -- flush pending operations to memory */
9924    /* 0F AE /6 = MFENCE -- flush pending operations to memory */
9925    if (insn[0] == 0x0F && insn[1] == 0xAE
9926        && epartIsReg(insn[2]) 
9927        && (gregOfRM(insn[2]) == 5 || gregOfRM(insn[2]) == 6)) {
9928       vassert(sz == 4);
9929       delta += 3;
9930       /* Insert a memory fence.  It's sometimes important that these
9931          are carried through to the generated code. */
9932       stmt( IRStmt_MBE(Imbe_Fence) );
9933       DIP("%sfence\n", gregOfRM(insn[2])==5 ? "l" : "m");
9934       goto decode_success;
9935    }
9936
9937    /* 66 0F 5F = MAXPD -- max 64Fx2 from R/M to R */
9938    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x5F) {
9939       delta = dis_SSE_E_to_G_all( sorb, delta+2, "maxpd", Iop_Max64Fx2 );
9940       goto decode_success;
9941    }
9942
9943    /* F2 0F 5F = MAXSD -- max 64F0x2 from R/M to R */
9944    if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x5F) {
9945       vassert(sz == 4);
9946       delta = dis_SSE_E_to_G_lo64( sorb, delta+3, "maxsd", Iop_Max64F0x2 );
9947       goto decode_success;
9948    }
9949
9950    /* 66 0F 5D = MINPD -- min 64Fx2 from R/M to R */
9951    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x5D) {
9952       delta = dis_SSE_E_to_G_all( sorb, delta+2, "minpd", Iop_Min64Fx2 );
9953       goto decode_success;
9954    }
9955
9956    /* F2 0F 5D = MINSD -- min 64F0x2 from R/M to R */
9957    if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x5D) {
9958       vassert(sz == 4);
9959       delta = dis_SSE_E_to_G_lo64( sorb, delta+3, "minsd", Iop_Min64F0x2 );
9960       goto decode_success;
9961    }
9962
9963    /* 66 0F 28 = MOVAPD -- move from E (mem or xmm) to G (xmm). */
9964    /* 66 0F 10 = MOVUPD -- move from E (mem or xmm) to G (xmm). */
9965    /* 66 0F 6F = MOVDQA -- move from E (mem or xmm) to G (xmm). */
9966    if (sz == 2 && insn[0] == 0x0F 
9967        && (insn[1] == 0x28 || insn[1] == 0x10 || insn[1] == 0x6F)) {
9968       HChar* wot = insn[1]==0x28 ? "apd" :
9969                    insn[1]==0x10 ? "upd" : "dqa";
9970       modrm = getIByte(delta+2);
9971       if (epartIsReg(modrm)) {
9972          putXMMReg( gregOfRM(modrm), 
9973                     getXMMReg( eregOfRM(modrm) ));
9974          DIP("mov%s %s,%s\n", wot, nameXMMReg(eregOfRM(modrm)),
9975                                    nameXMMReg(gregOfRM(modrm)));
9976          delta += 2+1;
9977       } else {
9978          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
9979          putXMMReg( gregOfRM(modrm), 
9980                     loadLE(Ity_V128, mkexpr(addr)) );
9981          DIP("mov%s %s,%s\n", wot, dis_buf,
9982                                    nameXMMReg(gregOfRM(modrm)));
9983          delta += 2+alen;
9984       }
9985       goto decode_success;
9986    }
9987
9988    /* 66 0F 29 = MOVAPD -- move from G (xmm) to E (mem or xmm). */
9989    /* 66 0F 11 = MOVUPD -- move from G (xmm) to E (mem or xmm). */
9990    if (sz == 2 && insn[0] == 0x0F 
9991        && (insn[1] == 0x29 || insn[1] == 0x11)) {
9992       HChar* wot = insn[1]==0x29 ? "apd" : "upd";
9993       modrm = getIByte(delta+2);
9994       if (epartIsReg(modrm)) {
9995          /* fall through; awaiting test case */
9996       } else {
9997          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
9998          storeLE( mkexpr(addr), getXMMReg(gregOfRM(modrm)) );
9999          DIP("mov%s %s,%s\n", wot, nameXMMReg(gregOfRM(modrm)),
10000                                    dis_buf );
10001          delta += 2+alen;
10002          goto decode_success;
10003       }
10004    }
10005
10006    /* 66 0F 6E = MOVD from r/m32 to xmm, zeroing high 3/4 of xmm. */
10007    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x6E) {
10008       modrm = getIByte(delta+2);
10009       if (epartIsReg(modrm)) {
10010          delta += 2+1;
10011          putXMMReg(
10012             gregOfRM(modrm),
10013             unop( Iop_32UtoV128, getIReg(4, eregOfRM(modrm)) ) 
10014          );
10015          DIP("movd %s, %s\n", 
10016              nameIReg(4,eregOfRM(modrm)), nameXMMReg(gregOfRM(modrm)));
10017       } else {
10018          addr = disAMode( &alen, sorb, delta+2, dis_buf );
10019          delta += 2+alen;
10020          putXMMReg(
10021             gregOfRM(modrm),
10022             unop( Iop_32UtoV128,loadLE(Ity_I32, mkexpr(addr)) ) 
10023          );
10024          DIP("movd %s, %s\n", dis_buf, nameXMMReg(gregOfRM(modrm)));
10025       }
10026       goto decode_success;
10027    }
10028
10029    /* 66 0F 7E = MOVD from xmm low 1/4 to r/m32. */
10030    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x7E) {
10031       modrm = getIByte(delta+2);
10032       if (epartIsReg(modrm)) {
10033          delta += 2+1;
10034          putIReg( 4, eregOfRM(modrm),
10035                   getXMMRegLane32(gregOfRM(modrm), 0) );
10036          DIP("movd %s, %s\n", 
10037              nameXMMReg(gregOfRM(modrm)), nameIReg(4,eregOfRM(modrm)));
10038       } else {
10039          addr = disAMode( &alen, sorb, delta+2, dis_buf );
10040          delta += 2+alen;
10041          storeLE( mkexpr(addr),
10042                   getXMMRegLane32(gregOfRM(modrm), 0) );
10043          DIP("movd %s, %s\n", nameXMMReg(gregOfRM(modrm)), dis_buf);
10044       }
10045       goto decode_success;
10046    }
10047
10048    /* 66 0F 7F = MOVDQA -- move from G (xmm) to E (mem or xmm). */
10049    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x7F) {
10050       modrm = getIByte(delta+2);
10051       if (epartIsReg(modrm)) {
10052          delta += 2+1;
10053          putXMMReg( eregOfRM(modrm),
10054                     getXMMReg(gregOfRM(modrm)) );
10055          DIP("movdqa %s, %s\n", nameXMMReg(gregOfRM(modrm)), 
10056                                 nameXMMReg(eregOfRM(modrm)));
10057       } else {
10058          addr = disAMode( &alen, sorb, delta+2, dis_buf );
10059          delta += 2+alen;
10060          storeLE( mkexpr(addr), getXMMReg(gregOfRM(modrm)) );
10061          DIP("movdqa %s, %s\n", nameXMMReg(gregOfRM(modrm)), dis_buf);
10062       }
10063       goto decode_success;
10064    }
10065
10066    /* F3 0F 6F = MOVDQU -- move from E (mem or xmm) to G (xmm). */
10067    /* Unfortunately can't simply use the MOVDQA case since the
10068       prefix lengths are different (66 vs F3) */
10069    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x6F) {
10070       vassert(sz == 4);
10071       modrm = getIByte(delta+3);
10072       if (epartIsReg(modrm)) {
10073          putXMMReg( gregOfRM(modrm), 
10074                     getXMMReg( eregOfRM(modrm) ));
10075          DIP("movdqu %s,%s\n", nameXMMReg(eregOfRM(modrm)),
10076                                nameXMMReg(gregOfRM(modrm)));
10077          delta += 3+1;
10078       } else {
10079          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
10080          putXMMReg( gregOfRM(modrm), 
10081                     loadLE(Ity_V128, mkexpr(addr)) );
10082          DIP("movdqu %s,%s\n", dis_buf,
10083                                nameXMMReg(gregOfRM(modrm)));
10084          delta += 3+alen;
10085       }
10086       goto decode_success;
10087    }
10088
10089    /* F3 0F 7F = MOVDQU -- move from G (xmm) to E (mem or xmm). */
10090    /* Unfortunately can't simply use the MOVDQA case since the
10091       prefix lengths are different (66 vs F3) */
10092    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x7F) {
10093       vassert(sz == 4);
10094       modrm = getIByte(delta+3);
10095       if (epartIsReg(modrm)) {
10096          delta += 3+1;
10097          putXMMReg( eregOfRM(modrm),
10098                     getXMMReg(gregOfRM(modrm)) );
10099          DIP("movdqu %s, %s\n", nameXMMReg(gregOfRM(modrm)), 
10100                                 nameXMMReg(eregOfRM(modrm)));
10101       } else {
10102          addr = disAMode( &alen, sorb, delta+3, dis_buf );
10103          delta += 3+alen;
10104          storeLE( mkexpr(addr), getXMMReg(gregOfRM(modrm)) );
10105          DIP("movdqu %s, %s\n", nameXMMReg(gregOfRM(modrm)), dis_buf);
10106       }
10107       goto decode_success;
10108    }
10109
10110    /* F2 0F D6 = MOVDQ2Q -- move from E (lo half xmm, not mem) to G (mmx). */
10111    if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0xD6) {
10112       vassert(sz == 4);
10113       modrm = getIByte(delta+3);
10114       if (epartIsReg(modrm)) {
10115          do_MMX_preamble();
10116          putMMXReg( gregOfRM(modrm), 
10117                     getXMMRegLane64( eregOfRM(modrm), 0 ));
10118          DIP("movdq2q %s,%s\n", nameXMMReg(eregOfRM(modrm)),
10119                                 nameMMXReg(gregOfRM(modrm)));
10120          delta += 3+1;
10121          goto decode_success;
10122       } else {
10123          /* fall through, apparently no mem case for this insn */
10124       }
10125    }
10126
10127    /* 66 0F 16 = MOVHPD -- move from mem to high half of XMM. */
10128    /* These seems identical to MOVHPS.  This instruction encoding is
10129       completely crazy. */
10130    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x16) {
10131       modrm = getIByte(delta+2);
10132       if (epartIsReg(modrm)) {
10133          /* fall through; apparently reg-reg is not possible */
10134       } else {
10135          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
10136          delta += 2+alen;
10137          putXMMRegLane64( gregOfRM(modrm), 1/*upper lane*/,
10138                           loadLE(Ity_I64, mkexpr(addr)) );
10139          DIP("movhpd %s,%s\n", dis_buf, 
10140                                nameXMMReg( gregOfRM(modrm) ));
10141          goto decode_success;
10142       }
10143    }
10144
10145    /* 66 0F 17 = MOVHPD -- move from high half of XMM to mem. */
10146    /* Again, this seems identical to MOVHPS. */
10147    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x17) {
10148       if (!epartIsReg(insn[2])) {
10149          delta += 2;
10150          addr = disAMode ( &alen, sorb, delta, dis_buf );
10151          delta += alen;
10152          storeLE( mkexpr(addr), 
10153                   getXMMRegLane64( gregOfRM(insn[2]),
10154                                    1/*upper lane*/ ) );
10155          DIP("movhpd %s,%s\n", nameXMMReg( gregOfRM(insn[2]) ),
10156                                dis_buf);
10157          goto decode_success;
10158       }
10159       /* else fall through */
10160    }
10161
10162    /* 66 0F 12 = MOVLPD -- move from mem to low half of XMM. */
10163    /* Identical to MOVLPS ? */
10164    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x12) {
10165       modrm = getIByte(delta+2);
10166       if (epartIsReg(modrm)) {
10167          /* fall through; apparently reg-reg is not possible */
10168       } else {
10169          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
10170          delta += 2+alen;
10171          putXMMRegLane64( gregOfRM(modrm),  0/*lower lane*/,
10172                           loadLE(Ity_I64, mkexpr(addr)) );
10173          DIP("movlpd %s, %s\n", 
10174              dis_buf, nameXMMReg( gregOfRM(modrm) ));
10175          goto decode_success;
10176       }
10177    }
10178
10179    /* 66 0F 13 = MOVLPD -- move from low half of XMM to mem. */
10180    /* Identical to MOVLPS ? */
10181    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x13) {
10182       if (!epartIsReg(insn[2])) {
10183          delta += 2;
10184          addr = disAMode ( &alen, sorb, delta, dis_buf );
10185          delta += alen;
10186          storeLE( mkexpr(addr), 
10187                   getXMMRegLane64( gregOfRM(insn[2]), 
10188                                    0/*lower lane*/ ) );
10189          DIP("movlpd %s, %s\n", nameXMMReg( gregOfRM(insn[2]) ),
10190                                 dis_buf);
10191          goto decode_success;
10192       }
10193       /* else fall through */
10194    }
10195
10196    /* 66 0F 50 = MOVMSKPD - move 2 sign bits from 2 x F64 in xmm(E) to
10197       2 lowest bits of ireg(G) */
10198    if (insn[0] == 0x0F && insn[1] == 0x50) {
10199       modrm = getIByte(delta+2);
10200       if (sz == 2 && epartIsReg(modrm)) {
10201          Int src;
10202          t0 = newTemp(Ity_I32);
10203          t1 = newTemp(Ity_I32);
10204          delta += 2+1;
10205          src = eregOfRM(modrm);
10206          assign( t0, binop( Iop_And32,
10207                             binop(Iop_Shr32, getXMMRegLane32(src,1), mkU8(31)),
10208                             mkU32(1) ));
10209          assign( t1, binop( Iop_And32,
10210                             binop(Iop_Shr32, getXMMRegLane32(src,3), mkU8(30)),
10211                             mkU32(2) ));
10212          putIReg(4, gregOfRM(modrm),
10213                     binop(Iop_Or32, mkexpr(t0), mkexpr(t1))
10214                  );
10215          DIP("movmskpd %s,%s\n", nameXMMReg(src), 
10216                                  nameIReg(4, gregOfRM(modrm)));
10217          goto decode_success;
10218       }
10219       /* else fall through */
10220    }
10221
10222    /* 66 0F F7 = MASKMOVDQU -- store selected bytes of double quadword */
10223    if (insn[0] == 0x0F && insn[1] == 0xF7) {
10224       modrm = getIByte(delta+2);
10225       if (sz == 2 && epartIsReg(modrm)) {
10226          IRTemp regD    = newTemp(Ity_V128);
10227          IRTemp mask    = newTemp(Ity_V128);
10228          IRTemp olddata = newTemp(Ity_V128);
10229          IRTemp newdata = newTemp(Ity_V128);
10230                 addr    = newTemp(Ity_I32);
10231
10232          assign( addr, handleSegOverride( sorb, getIReg(4, R_EDI) ));
10233          assign( regD, getXMMReg( gregOfRM(modrm) ));
10234
10235          /* Unfortunately can't do the obvious thing with SarN8x16
10236             here since that can't be re-emitted as SSE2 code - no such
10237             insn. */
10238          assign( 
10239             mask, 
10240             binop(Iop_64HLtoV128,
10241                   binop(Iop_SarN8x8, 
10242                         getXMMRegLane64( eregOfRM(modrm), 1 ), 
10243                         mkU8(7) ),
10244                   binop(Iop_SarN8x8, 
10245                         getXMMRegLane64( eregOfRM(modrm), 0 ), 
10246                         mkU8(7) ) ));
10247          assign( olddata, loadLE( Ity_V128, mkexpr(addr) ));
10248          assign( newdata, 
10249                  binop(Iop_OrV128, 
10250                        binop(Iop_AndV128, 
10251                              mkexpr(regD), 
10252                              mkexpr(mask) ),
10253                        binop(Iop_AndV128, 
10254                              mkexpr(olddata),
10255                              unop(Iop_NotV128, mkexpr(mask)))) );
10256          storeLE( mkexpr(addr), mkexpr(newdata) );
10257
10258          delta += 2+1;
10259          DIP("maskmovdqu %s,%s\n", nameXMMReg( eregOfRM(modrm) ),
10260                                    nameXMMReg( gregOfRM(modrm) ) );
10261          goto decode_success;
10262       }
10263       /* else fall through */
10264    }
10265
10266    /* 66 0F E7 = MOVNTDQ -- for us, just a plain SSE store. */
10267    if (insn[0] == 0x0F && insn[1] == 0xE7) {
10268       modrm = getIByte(delta+2);
10269       if (sz == 2 && !epartIsReg(modrm)) {
10270          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
10271          storeLE( mkexpr(addr), getXMMReg(gregOfRM(modrm)) );
10272          DIP("movntdq %s,%s\n", dis_buf,
10273                                 nameXMMReg(gregOfRM(modrm)));
10274          delta += 2+alen;
10275          goto decode_success;
10276       }
10277       /* else fall through */
10278    }
10279
10280    /* 0F C3 = MOVNTI -- for us, just a plain ireg store. */
10281    if (insn[0] == 0x0F && insn[1] == 0xC3) {
10282       vassert(sz == 4);
10283       modrm = getIByte(delta+2);
10284       if (!epartIsReg(modrm)) {
10285          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
10286          storeLE( mkexpr(addr), getIReg(4, gregOfRM(modrm)) );
10287          DIP("movnti %s,%s\n", dis_buf,
10288                                nameIReg(4, gregOfRM(modrm)));
10289          delta += 2+alen;
10290          goto decode_success;
10291       }
10292       /* else fall through */
10293    }
10294
10295    /* 66 0F D6 = MOVQ -- move 64 bits from G (lo half xmm) to E (mem
10296       or lo half xmm).  */
10297    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xD6) {
10298       modrm = getIByte(delta+2);
10299       if (epartIsReg(modrm)) {
10300          /* fall through, awaiting test case */
10301          /* dst: lo half copied, hi half zeroed */
10302       } else {
10303          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
10304          storeLE( mkexpr(addr), 
10305                   getXMMRegLane64( gregOfRM(modrm), 0 ));
10306          DIP("movq %s,%s\n", nameXMMReg(gregOfRM(modrm)), dis_buf );
10307          delta += 2+alen;
10308          goto decode_success;
10309       }
10310    }
10311
10312    /* F3 0F D6 = MOVQ2DQ -- move from E (mmx) to G (lo half xmm, zero
10313       hi half). */
10314    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0xD6) {
10315       vassert(sz == 4);
10316       modrm = getIByte(delta+3);
10317       if (epartIsReg(modrm)) {
10318          do_MMX_preamble();
10319          putXMMReg( gregOfRM(modrm), 
10320                     unop(Iop_64UtoV128, getMMXReg( eregOfRM(modrm) )) );
10321          DIP("movq2dq %s,%s\n", nameMMXReg(eregOfRM(modrm)),
10322                                 nameXMMReg(gregOfRM(modrm)));
10323          delta += 3+1;
10324          goto decode_success;
10325       } else {
10326          /* fall through, apparently no mem case for this insn */
10327       }
10328    }
10329
10330    /* F3 0F 7E = MOVQ -- move 64 bits from E (mem or lo half xmm) to
10331       G (lo half xmm).  Upper half of G is zeroed out. */
10332    /* F2 0F 10 = MOVSD -- move 64 bits from E (mem or lo half xmm) to
10333       G (lo half xmm).  If E is mem, upper half of G is zeroed out.
10334       If E is reg, upper half of G is unchanged. */
10335    if ((insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x10)
10336        || (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x7E)) {
10337       vassert(sz == 4);
10338       modrm = getIByte(delta+3);
10339       if (epartIsReg(modrm)) {
10340          putXMMRegLane64( gregOfRM(modrm), 0,
10341                           getXMMRegLane64( eregOfRM(modrm), 0 ));
10342          if (insn[0] == 0xF3/*MOVQ*/) {
10343             /* zero bits 127:64 */
10344             putXMMRegLane64( gregOfRM(modrm), 1, mkU64(0) );
10345          }
10346          DIP("movsd %s,%s\n", nameXMMReg(eregOfRM(modrm)),
10347                               nameXMMReg(gregOfRM(modrm)));
10348          delta += 3+1;
10349       } else {
10350          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
10351          /* zero bits 127:64 */
10352          putXMMRegLane64( gregOfRM(modrm), 1, mkU64(0) );
10353          /* write bits 63:0 */
10354          putXMMRegLane64( gregOfRM(modrm), 0,
10355                           loadLE(Ity_I64, mkexpr(addr)) );
10356          DIP("movsd %s,%s\n", dis_buf,
10357                               nameXMMReg(gregOfRM(modrm)));
10358          delta += 3+alen;
10359       }
10360       goto decode_success;
10361    }
10362
10363    /* F2 0F 11 = MOVSD -- move 64 bits from G (lo half xmm) to E (mem
10364       or lo half xmm). */
10365    if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x11) {
10366       vassert(sz == 4);
10367       modrm = getIByte(delta+3);
10368       if (epartIsReg(modrm)) {
10369          putXMMRegLane64( eregOfRM(modrm), 0,
10370                           getXMMRegLane64( gregOfRM(modrm), 0 ));
10371          DIP("movsd %s,%s\n", nameXMMReg(gregOfRM(modrm)),
10372                               nameXMMReg(eregOfRM(modrm)));
10373          delta += 3+1;
10374       } else {
10375          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
10376          storeLE( mkexpr(addr),
10377                   getXMMRegLane64(gregOfRM(modrm), 0) );
10378          DIP("movsd %s,%s\n", nameXMMReg(gregOfRM(modrm)),
10379                               dis_buf);
10380          delta += 3+alen;
10381       }
10382       goto decode_success;
10383    }
10384
10385    /* 66 0F 59 = MULPD -- mul 64Fx2 from R/M to R */
10386    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x59) {
10387       delta = dis_SSE_E_to_G_all( sorb, delta+2, "mulpd", Iop_Mul64Fx2 );
10388       goto decode_success;
10389    }
10390
10391    /* F2 0F 59 = MULSD -- mul 64F0x2 from R/M to R */
10392    if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x59) {
10393       vassert(sz == 4);
10394       delta = dis_SSE_E_to_G_lo64( sorb, delta+3, "mulsd", Iop_Mul64F0x2 );
10395       goto decode_success;
10396    }
10397
10398    /* 66 0F 56 = ORPD -- G = G and E */
10399    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x56) {
10400       delta = dis_SSE_E_to_G_all( sorb, delta+2, "orpd", Iop_OrV128 );
10401       goto decode_success;
10402    }
10403
10404    /* 66 0F C6 /r ib = SHUFPD -- shuffle packed F64s */
10405    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xC6) {
10406       Int    select;
10407       IRTemp sV = newTemp(Ity_V128);
10408       IRTemp dV = newTemp(Ity_V128);
10409       IRTemp s1 = newTemp(Ity_I64);
10410       IRTemp s0 = newTemp(Ity_I64);
10411       IRTemp d1 = newTemp(Ity_I64);
10412       IRTemp d0 = newTemp(Ity_I64);
10413
10414       modrm = insn[2];
10415       assign( dV, getXMMReg(gregOfRM(modrm)) );
10416
10417       if (epartIsReg(modrm)) {
10418          assign( sV, getXMMReg(eregOfRM(modrm)) );
10419          select = (Int)insn[3];
10420          delta += 2+2;
10421          DIP("shufpd $%d,%s,%s\n", select, 
10422                                    nameXMMReg(eregOfRM(modrm)),
10423                                    nameXMMReg(gregOfRM(modrm)));
10424       } else {
10425          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
10426          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
10427          select = (Int)insn[2+alen];
10428          delta += 3+alen;
10429          DIP("shufpd $%d,%s,%s\n", select, 
10430                                    dis_buf,
10431                                    nameXMMReg(gregOfRM(modrm)));
10432       }
10433
10434       assign( d1, unop(Iop_V128HIto64, mkexpr(dV)) );
10435       assign( d0, unop(Iop_V128to64,   mkexpr(dV)) );
10436       assign( s1, unop(Iop_V128HIto64, mkexpr(sV)) );
10437       assign( s0, unop(Iop_V128to64,   mkexpr(sV)) );
10438
10439 #     define SELD(n) mkexpr((n)==0 ? d0 : d1)
10440 #     define SELS(n) mkexpr((n)==0 ? s0 : s1)
10441
10442       putXMMReg(
10443          gregOfRM(modrm), 
10444          binop(Iop_64HLtoV128, SELS((select>>1)&1), SELD((select>>0)&1) )
10445       );
10446
10447 #     undef SELD
10448 #     undef SELS
10449
10450       goto decode_success;
10451    }
10452
10453    /* 66 0F 51 = SQRTPD -- approx sqrt 64Fx2 from R/M to R */
10454    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x51) {
10455       delta = dis_SSE_E_to_G_unary_all( sorb, delta+2, 
10456                                         "sqrtpd", Iop_Sqrt64Fx2 );
10457       goto decode_success;
10458    }
10459
10460    /* F2 0F 51 = SQRTSD -- approx sqrt 64F0x2 from R/M to R */
10461    if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x51) {
10462       vassert(sz == 4);
10463       delta = dis_SSE_E_to_G_unary_lo64( sorb, delta+3, 
10464                                          "sqrtsd", Iop_Sqrt64F0x2 );
10465       goto decode_success;
10466    }
10467
10468    /* 66 0F 5C = SUBPD -- sub 64Fx2 from R/M to R */
10469    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x5C) {
10470       delta = dis_SSE_E_to_G_all( sorb, delta+2, "subpd", Iop_Sub64Fx2 );
10471       goto decode_success;
10472    }
10473
10474    /* F2 0F 5C = SUBSD -- sub 64F0x2 from R/M to R */
10475    if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x5C) {
10476       vassert(sz == 4);
10477       delta = dis_SSE_E_to_G_lo64( sorb, delta+3, "subsd", Iop_Sub64F0x2 );
10478       goto decode_success;
10479    }
10480
10481    /* 66 0F 15 = UNPCKHPD -- unpack and interleave high part F64s */
10482    /* 66 0F 14 = UNPCKLPD -- unpack and interleave low part F64s */
10483    /* These just appear to be special cases of SHUFPS */
10484    if (sz == 2 && insn[0] == 0x0F && (insn[1] == 0x15 || insn[1] == 0x14)) {
10485       IRTemp s1 = newTemp(Ity_I64);
10486       IRTemp s0 = newTemp(Ity_I64);
10487       IRTemp d1 = newTemp(Ity_I64);
10488       IRTemp d0 = newTemp(Ity_I64);
10489       IRTemp sV = newTemp(Ity_V128);
10490       IRTemp dV = newTemp(Ity_V128);
10491       Bool   hi = toBool(insn[1] == 0x15);
10492
10493       modrm = insn[2];
10494       assign( dV, getXMMReg(gregOfRM(modrm)) );
10495
10496       if (epartIsReg(modrm)) {
10497          assign( sV, getXMMReg(eregOfRM(modrm)) );
10498          delta += 2+1;
10499          DIP("unpck%sps %s,%s\n", hi ? "h" : "l",
10500                                   nameXMMReg(eregOfRM(modrm)),
10501                                   nameXMMReg(gregOfRM(modrm)));
10502       } else {
10503          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
10504          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
10505          delta += 2+alen;
10506          DIP("unpck%sps %s,%s\n", hi ? "h" : "l",
10507                                   dis_buf,
10508                                   nameXMMReg(gregOfRM(modrm)));
10509       }
10510
10511       assign( d1, unop(Iop_V128HIto64, mkexpr(dV)) );
10512       assign( d0, unop(Iop_V128to64,   mkexpr(dV)) );
10513       assign( s1, unop(Iop_V128HIto64, mkexpr(sV)) );
10514       assign( s0, unop(Iop_V128to64,   mkexpr(sV)) );
10515
10516       if (hi) {
10517          putXMMReg( gregOfRM(modrm), 
10518                     binop(Iop_64HLtoV128, mkexpr(s1), mkexpr(d1)) );
10519       } else {
10520          putXMMReg( gregOfRM(modrm), 
10521                     binop(Iop_64HLtoV128, mkexpr(s0), mkexpr(d0)) );
10522       }
10523
10524       goto decode_success;
10525    }
10526
10527    /* 66 0F 57 = XORPD -- G = G and E */
10528    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x57) {
10529       delta = dis_SSE_E_to_G_all( sorb, delta+2, "xorpd", Iop_XorV128 );
10530       goto decode_success;
10531    }
10532
10533    /* 66 0F 6B = PACKSSDW */
10534    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x6B) {
10535       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10536                                  "packssdw", Iop_QNarrow32Sx4, True );
10537       goto decode_success;
10538    }
10539
10540    /* 66 0F 63 = PACKSSWB */
10541    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x63) {
10542       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10543                                  "packsswb", Iop_QNarrow16Sx8, True );
10544       goto decode_success;
10545    }
10546
10547    /* 66 0F 67 = PACKUSWB */
10548    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x67) {
10549       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10550                                  "packuswb", Iop_QNarrow16Ux8, True );
10551       goto decode_success;
10552    }
10553
10554    /* 66 0F FC = PADDB */
10555    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xFC) {
10556       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10557                                  "paddb", Iop_Add8x16, False );
10558       goto decode_success;
10559    }
10560
10561    /* 66 0F FE = PADDD */
10562    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xFE) {
10563       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10564                                  "paddd", Iop_Add32x4, False );
10565       goto decode_success;
10566    }
10567
10568    /* ***--- this is an MMX class insn introduced in SSE2 ---*** */
10569    /* 0F D4 = PADDQ -- add 64x1 */
10570    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xD4) {
10571       do_MMX_preamble();
10572       delta = dis_MMXop_regmem_to_reg ( 
10573                 sorb, delta+2, insn[1], "paddq", False );
10574       goto decode_success;
10575    }
10576
10577    /* 66 0F D4 = PADDQ */
10578    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xD4) {
10579       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10580                                  "paddq", Iop_Add64x2, False );
10581       goto decode_success;
10582    }
10583
10584    /* 66 0F FD = PADDW */
10585    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xFD) {
10586       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10587                                  "paddw", Iop_Add16x8, False );
10588       goto decode_success;
10589    }
10590
10591    /* 66 0F EC = PADDSB */
10592    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xEC) {
10593       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10594                                  "paddsb", Iop_QAdd8Sx16, False );
10595       goto decode_success;
10596    }
10597
10598    /* 66 0F ED = PADDSW */
10599    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xED) {
10600       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10601                                  "paddsw", Iop_QAdd16Sx8, False );
10602       goto decode_success;
10603    }
10604
10605    /* 66 0F DC = PADDUSB */
10606    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xDC) {
10607       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10608                                  "paddusb", Iop_QAdd8Ux16, False );
10609       goto decode_success;
10610    }
10611
10612    /* 66 0F DD = PADDUSW */
10613    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xDD) {
10614       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10615                                  "paddusw", Iop_QAdd16Ux8, False );
10616       goto decode_success;
10617    }
10618
10619    /* 66 0F DB = PAND */
10620    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xDB) {
10621       delta = dis_SSE_E_to_G_all( sorb, delta+2, "pand", Iop_AndV128 );
10622       goto decode_success;
10623    }
10624
10625    /* 66 0F DF = PANDN */
10626    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xDF) {
10627       delta = dis_SSE_E_to_G_all_invG( sorb, delta+2, "pandn", Iop_AndV128 );
10628       goto decode_success;
10629    }
10630
10631    /* 66 0F E0 = PAVGB */
10632    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xE0) {
10633       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10634                                  "pavgb", Iop_Avg8Ux16, False );
10635       goto decode_success;
10636    }
10637
10638    /* 66 0F E3 = PAVGW */
10639    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xE3) {
10640       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10641                                  "pavgw", Iop_Avg16Ux8, False );
10642       goto decode_success;
10643    }
10644
10645    /* 66 0F 74 = PCMPEQB */
10646    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x74) {
10647       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10648                                  "pcmpeqb", Iop_CmpEQ8x16, False );
10649       goto decode_success;
10650    }
10651
10652    /* 66 0F 76 = PCMPEQD */
10653    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x76) {
10654       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10655                                  "pcmpeqd", Iop_CmpEQ32x4, False );
10656       goto decode_success;
10657    }
10658
10659    /* 66 0F 75 = PCMPEQW */
10660    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x75) {
10661       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10662                                  "pcmpeqw", Iop_CmpEQ16x8, False );
10663       goto decode_success;
10664    }
10665
10666    /* 66 0F 64 = PCMPGTB */
10667    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x64) {
10668       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10669                                  "pcmpgtb", Iop_CmpGT8Sx16, False );
10670       goto decode_success;
10671    }
10672
10673    /* 66 0F 66 = PCMPGTD */
10674    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x66) {
10675       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10676                                  "pcmpgtd", Iop_CmpGT32Sx4, False );
10677       goto decode_success;
10678    }
10679
10680    /* 66 0F 65 = PCMPGTW */
10681    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x65) {
10682       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10683                                  "pcmpgtw", Iop_CmpGT16Sx8, False );
10684       goto decode_success;
10685    }
10686
10687    /* 66 0F C5 = PEXTRW -- extract 16-bit field from xmm(E) and put 
10688       zero-extend of it in ireg(G). */
10689    if (insn[0] == 0x0F && insn[1] == 0xC5) {
10690       modrm = insn[2];
10691       if (sz == 2 && epartIsReg(modrm)) {
10692          t5 = newTemp(Ity_V128);
10693          t4 = newTemp(Ity_I16);
10694          assign(t5, getXMMReg(eregOfRM(modrm)));
10695          breakup128to32s( t5, &t3, &t2, &t1, &t0 );
10696          switch (insn[3] & 7) {
10697             case 0:  assign(t4, unop(Iop_32to16,   mkexpr(t0))); break;
10698             case 1:  assign(t4, unop(Iop_32HIto16, mkexpr(t0))); break;
10699             case 2:  assign(t4, unop(Iop_32to16,   mkexpr(t1))); break;
10700             case 3:  assign(t4, unop(Iop_32HIto16, mkexpr(t1))); break;
10701             case 4:  assign(t4, unop(Iop_32to16,   mkexpr(t2))); break;
10702             case 5:  assign(t4, unop(Iop_32HIto16, mkexpr(t2))); break;
10703             case 6:  assign(t4, unop(Iop_32to16,   mkexpr(t3))); break;
10704             case 7:  assign(t4, unop(Iop_32HIto16, mkexpr(t3))); break;
10705             default: vassert(0); /*NOTREACHED*/
10706          }
10707          putIReg(4, gregOfRM(modrm), unop(Iop_16Uto32, mkexpr(t4)));
10708          DIP("pextrw $%d,%s,%s\n",
10709              (Int)insn[3], nameXMMReg(eregOfRM(modrm)),
10710                            nameIReg(4,gregOfRM(modrm)));
10711          delta += 4;
10712          goto decode_success;
10713       } 
10714       /* else fall through */
10715    }
10716
10717    /* 66 0F C4 = PINSRW -- get 16 bits from E(mem or low half ireg) and
10718       put it into the specified lane of xmm(G). */
10719    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xC4) {
10720       Int lane;
10721       t4 = newTemp(Ity_I16);
10722       modrm = insn[2];
10723
10724       if (epartIsReg(modrm)) {
10725          assign(t4, getIReg(2, eregOfRM(modrm)));
10726          delta += 3+1;
10727          lane = insn[3+1-1];
10728          DIP("pinsrw $%d,%s,%s\n", (Int)lane, 
10729                                    nameIReg(2,eregOfRM(modrm)),
10730                                    nameXMMReg(gregOfRM(modrm)));
10731       } else {
10732          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
10733          delta += 3+alen;
10734          lane = insn[3+alen-1];
10735          assign(t4, loadLE(Ity_I16, mkexpr(addr)));
10736          DIP("pinsrw $%d,%s,%s\n", (Int)lane, 
10737                                    dis_buf,
10738                                    nameXMMReg(gregOfRM(modrm)));
10739       }
10740
10741       putXMMRegLane16( gregOfRM(modrm), lane & 7, mkexpr(t4) );
10742       goto decode_success;
10743    }
10744
10745    /* 66 0F F5 = PMADDWD -- Multiply and add packed integers from
10746       E(xmm or mem) to G(xmm) */
10747    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xF5) {
10748       IRTemp s1V  = newTemp(Ity_V128);
10749       IRTemp s2V  = newTemp(Ity_V128);
10750       IRTemp dV   = newTemp(Ity_V128);
10751       IRTemp s1Hi = newTemp(Ity_I64);
10752       IRTemp s1Lo = newTemp(Ity_I64);
10753       IRTemp s2Hi = newTemp(Ity_I64);
10754       IRTemp s2Lo = newTemp(Ity_I64);
10755       IRTemp dHi  = newTemp(Ity_I64);
10756       IRTemp dLo  = newTemp(Ity_I64);
10757       modrm = insn[2];
10758       if (epartIsReg(modrm)) {
10759          assign( s1V, getXMMReg(eregOfRM(modrm)) );
10760          delta += 2+1;
10761          DIP("pmaddwd %s,%s\n", nameXMMReg(eregOfRM(modrm)),
10762                                 nameXMMReg(gregOfRM(modrm)));
10763       } else {
10764          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
10765          assign( s1V, loadLE(Ity_V128, mkexpr(addr)) );
10766          delta += 2+alen;
10767          DIP("pmaddwd %s,%s\n", dis_buf,
10768                                 nameXMMReg(gregOfRM(modrm)));
10769       }
10770       assign( s2V, getXMMReg(gregOfRM(modrm)) );
10771       assign( s1Hi, unop(Iop_V128HIto64, mkexpr(s1V)) );
10772       assign( s1Lo, unop(Iop_V128to64,   mkexpr(s1V)) );
10773       assign( s2Hi, unop(Iop_V128HIto64, mkexpr(s2V)) );
10774       assign( s2Lo, unop(Iop_V128to64,   mkexpr(s2V)) );
10775       assign( dHi, mkIRExprCCall(
10776                       Ity_I64, 0/*regparms*/,
10777                       "x86g_calculate_mmx_pmaddwd", 
10778                       &x86g_calculate_mmx_pmaddwd,
10779                       mkIRExprVec_2( mkexpr(s1Hi), mkexpr(s2Hi))
10780                    ));
10781       assign( dLo, mkIRExprCCall(
10782                       Ity_I64, 0/*regparms*/,
10783                       "x86g_calculate_mmx_pmaddwd", 
10784                       &x86g_calculate_mmx_pmaddwd,
10785                       mkIRExprVec_2( mkexpr(s1Lo), mkexpr(s2Lo))
10786                    ));
10787       assign( dV, binop(Iop_64HLtoV128, mkexpr(dHi), mkexpr(dLo))) ;
10788       putXMMReg(gregOfRM(modrm), mkexpr(dV));
10789       goto decode_success;
10790    }
10791
10792    /* 66 0F EE = PMAXSW -- 16x8 signed max */
10793    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xEE) {
10794       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10795                                  "pmaxsw", Iop_Max16Sx8, False );
10796       goto decode_success;
10797    }
10798
10799    /* 66 0F DE = PMAXUB -- 8x16 unsigned max */
10800    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xDE) {
10801       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10802                                  "pmaxub", Iop_Max8Ux16, False );
10803       goto decode_success;
10804    }
10805
10806    /* 66 0F EA = PMINSW -- 16x8 signed min */
10807    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xEA) {
10808       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10809                                  "pminsw", Iop_Min16Sx8, False );
10810       goto decode_success;
10811    }
10812
10813    /* 66 0F DA = PMINUB -- 8x16 unsigned min */
10814    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xDA) {
10815       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10816                                  "pminub", Iop_Min8Ux16, False );
10817       goto decode_success;
10818    }
10819
10820    /* 66 0F D7 = PMOVMSKB -- extract sign bits from each of 16 lanes in
10821       xmm(G), turn them into a byte, and put zero-extend of it in
10822       ireg(G).  Doing this directly is just too cumbersome; give up
10823       therefore and call a helper. */
10824    /* UInt x86g_calculate_sse_pmovmskb ( ULong w64hi, ULong w64lo ); */
10825    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xD7) {
10826       modrm = insn[2];
10827       if (epartIsReg(modrm)) {
10828          t0 = newTemp(Ity_I64);
10829          t1 = newTemp(Ity_I64);
10830          assign(t0, getXMMRegLane64(eregOfRM(modrm), 0));
10831          assign(t1, getXMMRegLane64(eregOfRM(modrm), 1));
10832          t5 = newTemp(Ity_I32);
10833          assign(t5, mkIRExprCCall(
10834                        Ity_I32, 0/*regparms*/, 
10835                        "x86g_calculate_sse_pmovmskb",
10836                        &x86g_calculate_sse_pmovmskb,
10837                        mkIRExprVec_2( mkexpr(t1), mkexpr(t0) )));
10838          putIReg(4, gregOfRM(modrm), mkexpr(t5));
10839          DIP("pmovmskb %s,%s\n", nameXMMReg(eregOfRM(modrm)),
10840                                  nameIReg(4,gregOfRM(modrm)));
10841          delta += 3;
10842          goto decode_success;
10843       } 
10844       /* else fall through */
10845    }
10846
10847    /* 66 0F E4 = PMULHUW -- 16x8 hi-half of unsigned widening multiply */
10848    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xE4) {
10849       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10850                                  "pmulhuw", Iop_MulHi16Ux8, False );
10851       goto decode_success;
10852    }
10853
10854    /* 66 0F E5 = PMULHW -- 16x8 hi-half of signed widening multiply */
10855    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xE5) {
10856       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10857                                  "pmulhw", Iop_MulHi16Sx8, False );
10858       goto decode_success;
10859    }
10860
10861    /* 66 0F D5 = PMULHL -- 16x8 multiply */
10862    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xD5) {
10863       delta = dis_SSEint_E_to_G( sorb, delta+2, 
10864                                  "pmullw", Iop_Mul16x8, False );
10865       goto decode_success;
10866    }
10867
10868    /* ***--- this is an MMX class insn introduced in SSE2 ---*** */
10869    /* 0F F4 = PMULUDQ -- unsigned widening multiply of 32-lanes 0 x
10870       0 to form 64-bit result */
10871    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xF4) {
10872       IRTemp sV = newTemp(Ity_I64);
10873       IRTemp dV = newTemp(Ity_I64);
10874       t1 = newTemp(Ity_I32);
10875       t0 = newTemp(Ity_I32);
10876       modrm = insn[2];
10877
10878       do_MMX_preamble();
10879       assign( dV, getMMXReg(gregOfRM(modrm)) );
10880
10881       if (epartIsReg(modrm)) {
10882          assign( sV, getMMXReg(eregOfRM(modrm)) );
10883          delta += 2+1;
10884          DIP("pmuludq %s,%s\n", nameMMXReg(eregOfRM(modrm)),
10885                                 nameMMXReg(gregOfRM(modrm)));
10886       } else {
10887          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
10888          assign( sV, loadLE(Ity_I64, mkexpr(addr)) );
10889          delta += 2+alen;
10890          DIP("pmuludq %s,%s\n", dis_buf,
10891                                 nameMMXReg(gregOfRM(modrm)));
10892       }
10893
10894       assign( t0, unop(Iop_64to32, mkexpr(dV)) );
10895       assign( t1, unop(Iop_64to32, mkexpr(sV)) );
10896       putMMXReg( gregOfRM(modrm),
10897                  binop( Iop_MullU32, mkexpr(t0), mkexpr(t1) ) );
10898       goto decode_success;
10899    }
10900
10901    /* 66 0F F4 = PMULUDQ -- unsigned widening multiply of 32-lanes 0 x
10902       0 to form lower 64-bit half and lanes 2 x 2 to form upper 64-bit
10903       half */
10904    /* This is a really poor translation -- could be improved if
10905       performance critical */
10906    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xF4) {
10907       IRTemp sV, dV;
10908       IRTemp s3, s2, s1, s0, d3, d2, d1, d0;
10909       sV = newTemp(Ity_V128);
10910       dV = newTemp(Ity_V128);
10911       s3 = s2 = s1 = s0 = d3 = d2 = d1 = d0 = IRTemp_INVALID;
10912       t1 = newTemp(Ity_I64);
10913       t0 = newTemp(Ity_I64);
10914       modrm = insn[2];
10915       assign( dV, getXMMReg(gregOfRM(modrm)) );
10916
10917       if (epartIsReg(modrm)) {
10918          assign( sV, getXMMReg(eregOfRM(modrm)) );
10919          delta += 2+1;
10920          DIP("pmuludq %s,%s\n", nameXMMReg(eregOfRM(modrm)),
10921                                 nameXMMReg(gregOfRM(modrm)));
10922       } else {
10923          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
10924          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
10925          delta += 2+alen;
10926          DIP("pmuludq %s,%s\n", dis_buf,
10927                                 nameXMMReg(gregOfRM(modrm)));
10928       }
10929
10930       breakup128to32s( dV, &d3, &d2, &d1, &d0 );
10931       breakup128to32s( sV, &s3, &s2, &s1, &s0 );
10932
10933       assign( t0, binop( Iop_MullU32, mkexpr(d0), mkexpr(s0)) );
10934       putXMMRegLane64( gregOfRM(modrm), 0, mkexpr(t0) );
10935       assign( t1, binop( Iop_MullU32, mkexpr(d2), mkexpr(s2)) );
10936       putXMMRegLane64( gregOfRM(modrm), 1, mkexpr(t1) );
10937       goto decode_success;
10938    }
10939
10940    /* 66 0F EB = POR */
10941    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xEB) {
10942       delta = dis_SSE_E_to_G_all( sorb, delta+2, "por", Iop_OrV128 );
10943       goto decode_success;
10944    }
10945
10946    /* 66 0F F6 = PSADBW -- 2 x (8x8 -> 48 zeroes ++ u16) Sum Abs Diffs
10947       from E(xmm or mem) to G(xmm) */
10948    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xF6) {
10949       IRTemp s1V  = newTemp(Ity_V128);
10950       IRTemp s2V  = newTemp(Ity_V128);
10951       IRTemp dV   = newTemp(Ity_V128);
10952       IRTemp s1Hi = newTemp(Ity_I64);
10953       IRTemp s1Lo = newTemp(Ity_I64);
10954       IRTemp s2Hi = newTemp(Ity_I64);
10955       IRTemp s2Lo = newTemp(Ity_I64);
10956       IRTemp dHi  = newTemp(Ity_I64);
10957       IRTemp dLo  = newTemp(Ity_I64);
10958       modrm = insn[2];
10959       if (epartIsReg(modrm)) {
10960          assign( s1V, getXMMReg(eregOfRM(modrm)) );
10961          delta += 2+1;
10962          DIP("psadbw %s,%s\n", nameXMMReg(eregOfRM(modrm)),
10963                                nameXMMReg(gregOfRM(modrm)));
10964       } else {
10965          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
10966          assign( s1V, loadLE(Ity_V128, mkexpr(addr)) );
10967          delta += 2+alen;
10968          DIP("psadbw %s,%s\n", dis_buf,
10969                                nameXMMReg(gregOfRM(modrm)));
10970       }
10971       assign( s2V, getXMMReg(gregOfRM(modrm)) );
10972       assign( s1Hi, unop(Iop_V128HIto64, mkexpr(s1V)) );
10973       assign( s1Lo, unop(Iop_V128to64,   mkexpr(s1V)) );
10974       assign( s2Hi, unop(Iop_V128HIto64, mkexpr(s2V)) );
10975       assign( s2Lo, unop(Iop_V128to64,   mkexpr(s2V)) );
10976       assign( dHi, mkIRExprCCall(
10977                       Ity_I64, 0/*regparms*/,
10978                       "x86g_calculate_mmx_psadbw", 
10979                       &x86g_calculate_mmx_psadbw,
10980                       mkIRExprVec_2( mkexpr(s1Hi), mkexpr(s2Hi))
10981                    ));
10982       assign( dLo, mkIRExprCCall(
10983                       Ity_I64, 0/*regparms*/,
10984                       "x86g_calculate_mmx_psadbw", 
10985                       &x86g_calculate_mmx_psadbw,
10986                       mkIRExprVec_2( mkexpr(s1Lo), mkexpr(s2Lo))
10987                    ));
10988       assign( dV, binop(Iop_64HLtoV128, mkexpr(dHi), mkexpr(dLo))) ;
10989       putXMMReg(gregOfRM(modrm), mkexpr(dV));
10990       goto decode_success;
10991    }
10992
10993    /* 66 0F 70 = PSHUFD -- rearrange 4x32 from E(xmm or mem) to G(xmm) */
10994    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x70) {
10995       Int order;
10996       IRTemp sV, dV, s3, s2, s1, s0;
10997       s3 = s2 = s1 = s0 = IRTemp_INVALID;
10998       sV = newTemp(Ity_V128);
10999       dV = newTemp(Ity_V128);
11000       modrm = insn[2];
11001       if (epartIsReg(modrm)) {
11002          assign( sV, getXMMReg(eregOfRM(modrm)) );
11003          order = (Int)insn[3];
11004          delta += 2+2;
11005          DIP("pshufd $%d,%s,%s\n", order, 
11006                                    nameXMMReg(eregOfRM(modrm)),
11007                                    nameXMMReg(gregOfRM(modrm)));
11008       } else {
11009          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
11010          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
11011          order = (Int)insn[2+alen];
11012          delta += 3+alen;
11013          DIP("pshufd $%d,%s,%s\n", order, 
11014                                    dis_buf,
11015                                    nameXMMReg(gregOfRM(modrm)));
11016       }
11017       breakup128to32s( sV, &s3, &s2, &s1, &s0 );
11018
11019 #     define SEL(n) \
11020                 ((n)==0 ? s0 : ((n)==1 ? s1 : ((n)==2 ? s2 : s3)))
11021       assign(dV,
11022              mk128from32s( SEL((order>>6)&3), SEL((order>>4)&3),
11023                            SEL((order>>2)&3), SEL((order>>0)&3) )
11024       );
11025       putXMMReg(gregOfRM(modrm), mkexpr(dV));
11026 #     undef SEL
11027       goto decode_success;
11028    }
11029
11030    /* F3 0F 70 = PSHUFHW -- rearrange upper half 4x16 from E(xmm or
11031       mem) to G(xmm), and copy lower half */
11032    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x70) {
11033       Int order;
11034       IRTemp sVhi, dVhi, sV, dV, s3, s2, s1, s0;
11035       s3 = s2 = s1 = s0 = IRTemp_INVALID;
11036       sV   = newTemp(Ity_V128);
11037       dV   = newTemp(Ity_V128);
11038       sVhi = newTemp(Ity_I64);
11039       dVhi = newTemp(Ity_I64);
11040       modrm = insn[3];
11041       if (epartIsReg(modrm)) {
11042          assign( sV, getXMMReg(eregOfRM(modrm)) );
11043          order = (Int)insn[4];
11044          delta += 4+1;
11045          DIP("pshufhw $%d,%s,%s\n", order, 
11046                                     nameXMMReg(eregOfRM(modrm)),
11047                                     nameXMMReg(gregOfRM(modrm)));
11048       } else {
11049          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
11050          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
11051          order = (Int)insn[3+alen];
11052          delta += 4+alen;
11053          DIP("pshufhw $%d,%s,%s\n", order, 
11054                                     dis_buf,
11055                                     nameXMMReg(gregOfRM(modrm)));
11056       }
11057       assign( sVhi, unop(Iop_V128HIto64, mkexpr(sV)) );
11058       breakup64to16s( sVhi, &s3, &s2, &s1, &s0 );
11059
11060 #     define SEL(n) \
11061                 ((n)==0 ? s0 : ((n)==1 ? s1 : ((n)==2 ? s2 : s3)))
11062       assign(dVhi,
11063              mk64from16s( SEL((order>>6)&3), SEL((order>>4)&3),
11064                           SEL((order>>2)&3), SEL((order>>0)&3) )
11065       );
11066       assign(dV, binop( Iop_64HLtoV128, 
11067                         mkexpr(dVhi),
11068                         unop(Iop_V128to64, mkexpr(sV))) );
11069       putXMMReg(gregOfRM(modrm), mkexpr(dV));
11070 #     undef SEL
11071       goto decode_success;
11072    }
11073
11074    /* F2 0F 70 = PSHUFLW -- rearrange lower half 4x16 from E(xmm or
11075       mem) to G(xmm), and copy upper half */
11076    if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x70) {
11077       Int order;
11078       IRTemp sVlo, dVlo, sV, dV, s3, s2, s1, s0;
11079       s3 = s2 = s1 = s0 = IRTemp_INVALID;
11080       sV   = newTemp(Ity_V128);
11081       dV   = newTemp(Ity_V128);
11082       sVlo = newTemp(Ity_I64);
11083       dVlo = newTemp(Ity_I64);
11084       modrm = insn[3];
11085       if (epartIsReg(modrm)) {
11086          assign( sV, getXMMReg(eregOfRM(modrm)) );
11087          order = (Int)insn[4];
11088          delta += 4+1;
11089          DIP("pshuflw $%d,%s,%s\n", order, 
11090                                     nameXMMReg(eregOfRM(modrm)),
11091                                     nameXMMReg(gregOfRM(modrm)));
11092       } else {
11093          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
11094          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
11095          order = (Int)insn[3+alen];
11096          delta += 4+alen;
11097          DIP("pshuflw $%d,%s,%s\n", order, 
11098                                     dis_buf,
11099                                     nameXMMReg(gregOfRM(modrm)));
11100       }
11101       assign( sVlo, unop(Iop_V128to64, mkexpr(sV)) );
11102       breakup64to16s( sVlo, &s3, &s2, &s1, &s0 );
11103
11104 #     define SEL(n) \
11105                 ((n)==0 ? s0 : ((n)==1 ? s1 : ((n)==2 ? s2 : s3)))
11106       assign(dVlo,
11107              mk64from16s( SEL((order>>6)&3), SEL((order>>4)&3),
11108                           SEL((order>>2)&3), SEL((order>>0)&3) )
11109       );
11110       assign(dV, binop( Iop_64HLtoV128,
11111                         unop(Iop_V128HIto64, mkexpr(sV)),
11112                         mkexpr(dVlo) ) );
11113       putXMMReg(gregOfRM(modrm), mkexpr(dV));
11114 #     undef SEL
11115       goto decode_success;
11116    }
11117
11118    /* 66 0F 72 /6 ib = PSLLD by immediate */
11119    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x72
11120        && epartIsReg(insn[2])
11121        && gregOfRM(insn[2]) == 6) {
11122       delta = dis_SSE_shiftE_imm( delta+2, "pslld", Iop_ShlN32x4 );
11123       goto decode_success;
11124    }
11125
11126    /* 66 0F F2 = PSLLD by E */
11127    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xF2) {
11128       delta = dis_SSE_shiftG_byE( sorb, delta+2, "pslld", Iop_ShlN32x4 );
11129       goto decode_success;
11130    }
11131
11132    /* 66 0F 73 /7 ib = PSLLDQ by immediate */
11133    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x73
11134        && epartIsReg(insn[2])
11135        && gregOfRM(insn[2]) == 7) {
11136       IRTemp sV, dV, hi64, lo64, hi64r, lo64r;
11137       Int    imm = (Int)insn[3];
11138       Int    reg = eregOfRM(insn[2]);
11139       DIP("pslldq $%d,%s\n", imm, nameXMMReg(reg));
11140       vassert(imm >= 0 && imm <= 255);
11141       delta += 4;
11142
11143       sV    = newTemp(Ity_V128);
11144       dV    = newTemp(Ity_V128);
11145       hi64  = newTemp(Ity_I64);
11146       lo64  = newTemp(Ity_I64);
11147       hi64r = newTemp(Ity_I64);
11148       lo64r = newTemp(Ity_I64);
11149
11150       if (imm >= 16) {
11151          putXMMReg(reg, mkV128(0x0000));
11152          goto decode_success;
11153       }
11154
11155       assign( sV, getXMMReg(reg) );
11156       assign( hi64, unop(Iop_V128HIto64, mkexpr(sV)) );
11157       assign( lo64, unop(Iop_V128to64, mkexpr(sV)) );
11158
11159       if (imm == 0) {
11160          assign( lo64r, mkexpr(lo64) );
11161          assign( hi64r, mkexpr(hi64) );
11162       }
11163       else
11164       if (imm == 8) {
11165          assign( lo64r, mkU64(0) );
11166          assign( hi64r, mkexpr(lo64) );
11167       }
11168       else
11169       if (imm > 8) {
11170          assign( lo64r, mkU64(0) );
11171          assign( hi64r, binop( Iop_Shl64, 
11172                                mkexpr(lo64),
11173                                mkU8( 8*(imm-8) ) ));
11174       } else {
11175          assign( lo64r, binop( Iop_Shl64, 
11176                                mkexpr(lo64),
11177                                mkU8(8 * imm) ));
11178          assign( hi64r, 
11179                  binop( Iop_Or64,
11180                         binop(Iop_Shl64, mkexpr(hi64), 
11181                                          mkU8(8 * imm)),
11182                         binop(Iop_Shr64, mkexpr(lo64),
11183                                          mkU8(8 * (8 - imm)) )
11184                       )
11185                );
11186       }
11187       assign( dV, binop(Iop_64HLtoV128, mkexpr(hi64r), mkexpr(lo64r)) );
11188       putXMMReg(reg, mkexpr(dV));
11189       goto decode_success;
11190    }
11191
11192    /* 66 0F 73 /6 ib = PSLLQ by immediate */
11193    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x73
11194        && epartIsReg(insn[2])
11195        && gregOfRM(insn[2]) == 6) {
11196       delta = dis_SSE_shiftE_imm( delta+2, "psllq", Iop_ShlN64x2 );
11197       goto decode_success;
11198    }
11199
11200    /* 66 0F F3 = PSLLQ by E */
11201    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xF3) {
11202       delta = dis_SSE_shiftG_byE( sorb, delta+2, "psllq", Iop_ShlN64x2 );
11203       goto decode_success;
11204    }
11205
11206    /* 66 0F 71 /6 ib = PSLLW by immediate */
11207    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x71
11208        && epartIsReg(insn[2])
11209        && gregOfRM(insn[2]) == 6) {
11210       delta = dis_SSE_shiftE_imm( delta+2, "psllw", Iop_ShlN16x8 );
11211       goto decode_success;
11212    }
11213
11214    /* 66 0F F1 = PSLLW by E */
11215    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xF1) {
11216       delta = dis_SSE_shiftG_byE( sorb, delta+2, "psllw", Iop_ShlN16x8 );
11217       goto decode_success;
11218    }
11219
11220    /* 66 0F 72 /4 ib = PSRAD by immediate */
11221    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x72
11222        && epartIsReg(insn[2])
11223        && gregOfRM(insn[2]) == 4) {
11224       delta = dis_SSE_shiftE_imm( delta+2, "psrad", Iop_SarN32x4 );
11225       goto decode_success;
11226    }
11227
11228    /* 66 0F E2 = PSRAD by E */
11229    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xE2) {
11230       delta = dis_SSE_shiftG_byE( sorb, delta+2, "psrad", Iop_SarN32x4 );
11231       goto decode_success;
11232    }
11233
11234    /* 66 0F 71 /4 ib = PSRAW by immediate */
11235    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x71
11236        && epartIsReg(insn[2])
11237        && gregOfRM(insn[2]) == 4) {
11238       delta = dis_SSE_shiftE_imm( delta+2, "psraw", Iop_SarN16x8 );
11239       goto decode_success;
11240    }
11241
11242    /* 66 0F E1 = PSRAW by E */
11243    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xE1) {
11244       delta = dis_SSE_shiftG_byE( sorb, delta+2, "psraw", Iop_SarN16x8 );
11245       goto decode_success;
11246    }
11247
11248    /* 66 0F 72 /2 ib = PSRLD by immediate */
11249    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x72
11250        && epartIsReg(insn[2])
11251        && gregOfRM(insn[2]) == 2) {
11252       delta = dis_SSE_shiftE_imm( delta+2, "psrld", Iop_ShrN32x4 );
11253       goto decode_success;
11254    }
11255
11256    /* 66 0F D2 = PSRLD by E */
11257    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xD2) {
11258       delta = dis_SSE_shiftG_byE( sorb, delta+2, "psrld", Iop_ShrN32x4 );
11259       goto decode_success;
11260    }
11261
11262    /* 66 0F 73 /3 ib = PSRLDQ by immediate */
11263    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x73
11264        && epartIsReg(insn[2])
11265        && gregOfRM(insn[2]) == 3) {
11266       IRTemp sV, dV, hi64, lo64, hi64r, lo64r;
11267       Int    imm = (Int)insn[3];
11268       Int    reg = eregOfRM(insn[2]);
11269       DIP("psrldq $%d,%s\n", imm, nameXMMReg(reg));
11270       vassert(imm >= 0 && imm <= 255);
11271       delta += 4;
11272
11273       sV    = newTemp(Ity_V128);
11274       dV    = newTemp(Ity_V128);
11275       hi64  = newTemp(Ity_I64);
11276       lo64  = newTemp(Ity_I64);
11277       hi64r = newTemp(Ity_I64);
11278       lo64r = newTemp(Ity_I64);
11279
11280       if (imm >= 16) {
11281          putXMMReg(reg, mkV128(0x0000));
11282          goto decode_success;
11283       }
11284
11285       assign( sV, getXMMReg(reg) );
11286       assign( hi64, unop(Iop_V128HIto64, mkexpr(sV)) );
11287       assign( lo64, unop(Iop_V128to64, mkexpr(sV)) );
11288
11289       if (imm == 0) {
11290          assign( lo64r, mkexpr(lo64) );
11291          assign( hi64r, mkexpr(hi64) );
11292       }
11293       else
11294       if (imm == 8) {
11295          assign( hi64r, mkU64(0) );
11296          assign( lo64r, mkexpr(hi64) );
11297       }
11298       else 
11299       if (imm > 8) {
11300          assign( hi64r, mkU64(0) );
11301          assign( lo64r, binop( Iop_Shr64, 
11302                                mkexpr(hi64),
11303                                mkU8( 8*(imm-8) ) ));
11304       } else {
11305          assign( hi64r, binop( Iop_Shr64, 
11306                                mkexpr(hi64),
11307                                mkU8(8 * imm) ));
11308          assign( lo64r, 
11309                  binop( Iop_Or64,
11310                         binop(Iop_Shr64, mkexpr(lo64), 
11311                                          mkU8(8 * imm)),
11312                         binop(Iop_Shl64, mkexpr(hi64),
11313                                          mkU8(8 * (8 - imm)) )
11314                       )
11315                );
11316       }
11317
11318       assign( dV, binop(Iop_64HLtoV128, mkexpr(hi64r), mkexpr(lo64r)) );
11319       putXMMReg(reg, mkexpr(dV));
11320       goto decode_success;
11321    }
11322
11323    /* 66 0F 73 /2 ib = PSRLQ by immediate */
11324    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x73
11325        && epartIsReg(insn[2])
11326        && gregOfRM(insn[2]) == 2) {
11327       delta = dis_SSE_shiftE_imm( delta+2, "psrlq", Iop_ShrN64x2 );
11328       goto decode_success;
11329    }
11330
11331    /* 66 0F D3 = PSRLQ by E */
11332    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xD3) {
11333       delta = dis_SSE_shiftG_byE( sorb, delta+2, "psrlq", Iop_ShrN64x2 );
11334       goto decode_success;
11335    }
11336
11337    /* 66 0F 71 /2 ib = PSRLW by immediate */
11338    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x71
11339        && epartIsReg(insn[2])
11340        && gregOfRM(insn[2]) == 2) {
11341       delta = dis_SSE_shiftE_imm( delta+2, "psrlw", Iop_ShrN16x8 );
11342       goto decode_success;
11343    }
11344
11345    /* 66 0F D1 = PSRLW by E */
11346    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xD1) {
11347       delta = dis_SSE_shiftG_byE( sorb, delta+2, "psrlw", Iop_ShrN16x8 );
11348       goto decode_success;
11349    }
11350
11351    /* 66 0F F8 = PSUBB */
11352    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xF8) {
11353       delta = dis_SSEint_E_to_G( sorb, delta+2, 
11354                                  "psubb", Iop_Sub8x16, False );
11355       goto decode_success;
11356    }
11357
11358    /* 66 0F FA = PSUBD */
11359    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xFA) {
11360       delta = dis_SSEint_E_to_G( sorb, delta+2, 
11361                                  "psubd", Iop_Sub32x4, False );
11362       goto decode_success;
11363    }
11364
11365    /* ***--- this is an MMX class insn introduced in SSE2 ---*** */
11366    /* 0F FB = PSUBQ -- sub 64x1 */
11367    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xFB) {
11368       do_MMX_preamble();
11369       delta = dis_MMXop_regmem_to_reg ( 
11370                 sorb, delta+2, insn[1], "psubq", False );
11371       goto decode_success;
11372    }
11373
11374    /* 66 0F FB = PSUBQ */
11375    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xFB) {
11376       delta = dis_SSEint_E_to_G( sorb, delta+2, 
11377                                  "psubq", Iop_Sub64x2, False );
11378       goto decode_success;
11379    }
11380
11381    /* 66 0F F9 = PSUBW */
11382    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xF9) {
11383       delta = dis_SSEint_E_to_G( sorb, delta+2, 
11384                                  "psubw", Iop_Sub16x8, False );
11385       goto decode_success;
11386    }
11387
11388    /* 66 0F E8 = PSUBSB */
11389    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xE8) {
11390       delta = dis_SSEint_E_to_G( sorb, delta+2, 
11391                                  "psubsb", Iop_QSub8Sx16, False );
11392       goto decode_success;
11393    }
11394
11395    /* 66 0F E9 = PSUBSW */
11396    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xE9) {
11397       delta = dis_SSEint_E_to_G( sorb, delta+2, 
11398                                  "psubsw", Iop_QSub16Sx8, False );
11399       goto decode_success;
11400    }
11401
11402    /* 66 0F D8 = PSUBSB */
11403    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xD8) {
11404       delta = dis_SSEint_E_to_G( sorb, delta+2, 
11405                                  "psubusb", Iop_QSub8Ux16, False );
11406       goto decode_success;
11407    }
11408
11409    /* 66 0F D9 = PSUBSW */
11410    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xD9) {
11411       delta = dis_SSEint_E_to_G( sorb, delta+2, 
11412                                  "psubusw", Iop_QSub16Ux8, False );
11413       goto decode_success;
11414    }
11415
11416    /* 66 0F 68 = PUNPCKHBW */
11417    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x68) {
11418       delta = dis_SSEint_E_to_G( sorb, delta+2, 
11419                                  "punpckhbw",
11420                                  Iop_InterleaveHI8x16, True );
11421       goto decode_success;
11422    }
11423
11424    /* 66 0F 6A = PUNPCKHDQ */
11425    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x6A) {
11426       delta = dis_SSEint_E_to_G( sorb, delta+2, 
11427                                  "punpckhdq",
11428                                  Iop_InterleaveHI32x4, True );
11429       goto decode_success;
11430    }
11431
11432    /* 66 0F 6D = PUNPCKHQDQ */
11433    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x6D) {
11434       delta = dis_SSEint_E_to_G( sorb, delta+2, 
11435                                  "punpckhqdq",
11436                                  Iop_InterleaveHI64x2, True );
11437       goto decode_success;
11438    }
11439
11440    /* 66 0F 69 = PUNPCKHWD */
11441    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x69) {
11442       delta = dis_SSEint_E_to_G( sorb, delta+2, 
11443                                  "punpckhwd",
11444                                  Iop_InterleaveHI16x8, True );
11445       goto decode_success;
11446    }
11447
11448    /* 66 0F 60 = PUNPCKLBW */
11449    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x60) {
11450       delta = dis_SSEint_E_to_G( sorb, delta+2, 
11451                                  "punpcklbw",
11452                                  Iop_InterleaveLO8x16, True );
11453       goto decode_success;
11454    }
11455
11456    /* 66 0F 62 = PUNPCKLDQ */
11457    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x62) {
11458       delta = dis_SSEint_E_to_G( sorb, delta+2, 
11459                                  "punpckldq",
11460                                  Iop_InterleaveLO32x4, True );
11461       goto decode_success;
11462    }
11463
11464    /* 66 0F 6C = PUNPCKLQDQ */
11465    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x6C) {
11466       delta = dis_SSEint_E_to_G( sorb, delta+2, 
11467                                  "punpcklqdq",
11468                                  Iop_InterleaveLO64x2, True );
11469       goto decode_success;
11470    }
11471
11472    /* 66 0F 61 = PUNPCKLWD */
11473    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x61) {
11474       delta = dis_SSEint_E_to_G( sorb, delta+2, 
11475                                  "punpcklwd",
11476                                  Iop_InterleaveLO16x8, True );
11477       goto decode_success;
11478    }
11479
11480    /* 66 0F EF = PXOR */
11481    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xEF) {
11482       delta = dis_SSE_E_to_G_all( sorb, delta+2, "pxor", Iop_XorV128 );
11483       goto decode_success;
11484    }
11485
11486 //--    /* FXSAVE/FXRSTOR m32 -- load/store the FPU/MMX/SSE state. */
11487 //--    if (insn[0] == 0x0F && insn[1] == 0xAE 
11488 //--        && (!epartIsReg(insn[2]))
11489 //--        && (gregOfRM(insn[2]) == 1 || gregOfRM(insn[2]) == 0) ) {
11490 //--       Bool store = gregOfRM(insn[2]) == 0;
11491 //--       vg_assert(sz == 4);
11492 //--       pair = disAMode ( cb, sorb, eip+2, dis_buf );
11493 //--       t1   = LOW24(pair);
11494 //--       eip += 2+HI8(pair);
11495 //--       uInstr3(cb, store ? SSE2a_MemWr : SSE2a_MemRd, 512,
11496 //--                   Lit16, (((UShort)insn[0]) << 8) | (UShort)insn[1],
11497 //--                   Lit16, (UShort)insn[2],
11498 //--                   TempReg, t1 );
11499 //--       DIP("fx%s %s\n", store ? "save" : "rstor", dis_buf );
11500 //--       goto decode_success;
11501 //--    }
11502
11503    /* 0F AE /7 = CLFLUSH -- flush cache line */
11504    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xAE
11505        && !epartIsReg(insn[2]) && gregOfRM(insn[2]) == 7) {
11506
11507       /* This is something of a hack.  We need to know the size of the
11508          cache line containing addr.  Since we don't (easily), assume
11509          256 on the basis that no real cache would have a line that
11510          big.  It's safe to invalidate more stuff than we need, just
11511          inefficient. */
11512       UInt lineszB = 256;
11513
11514       addr = disAMode ( &alen, sorb, delta+2, dis_buf );
11515       delta += 2+alen;
11516
11517       /* Round addr down to the start of the containing block. */
11518       stmt( IRStmt_Put(
11519                OFFB_TISTART,
11520                binop( Iop_And32, 
11521                       mkexpr(addr), 
11522                       mkU32( ~(lineszB-1) ))) );
11523
11524       stmt( IRStmt_Put(OFFB_TILEN, mkU32(lineszB) ) );
11525
11526       irsb->jumpkind = Ijk_TInval;
11527       irsb->next     = mkU32(guest_EIP_bbstart+delta);
11528       dres.whatNext  = Dis_StopHere;
11529
11530       DIP("clflush %s\n", dis_buf);
11531       goto decode_success;
11532    }
11533
11534    /* ---------------------------------------------------- */
11535    /* --- end of the SSE2 decoder.                     --- */
11536    /* ---------------------------------------------------- */
11537
11538    /* ---------------------------------------------------- */
11539    /* --- start of the SSE3 decoder.                   --- */
11540    /* ---------------------------------------------------- */
11541
11542    /* Skip parts of the decoder which don't apply given the stated
11543       guest subarchitecture. */
11544    /* if (0 == (archinfo->hwcaps & VEX_HWCAPS_X86_SSE3)) */
11545    /* In fact this is highly bogus; we accept SSE3 insns even on a
11546       SSE2-only guest since they turn into IR which can be re-emitted
11547       successfully on an SSE2 host. */
11548    if (0 == (archinfo->hwcaps & VEX_HWCAPS_X86_SSE2))
11549       goto after_sse_decoders; /* no SSE3 capabilities */
11550
11551    insn = (UChar*)&guest_code[delta];
11552
11553    /* F3 0F 12 = MOVSLDUP -- move from E (mem or xmm) to G (xmm),
11554       duplicating some lanes (2:2:0:0). */
11555    /* F3 0F 16 = MOVSHDUP -- move from E (mem or xmm) to G (xmm),
11556       duplicating some lanes (3:3:1:1). */
11557    if (sz == 4 && insn[0] == 0xF3 && insn[1] == 0x0F 
11558        && (insn[2] == 0x12 || insn[2] == 0x16)) {
11559       IRTemp s3, s2, s1, s0;
11560       IRTemp sV  = newTemp(Ity_V128);
11561       Bool   isH = insn[2] == 0x16;
11562       s3 = s2 = s1 = s0 = IRTemp_INVALID;
11563
11564       modrm = insn[3];
11565       if (epartIsReg(modrm)) {
11566          assign( sV, getXMMReg( eregOfRM(modrm)) );
11567          DIP("movs%cdup %s,%s\n", isH ? 'h' : 'l',
11568                                   nameXMMReg(eregOfRM(modrm)),
11569                                   nameXMMReg(gregOfRM(modrm)));
11570          delta += 3+1;
11571       } else {
11572          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
11573          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
11574          DIP("movs%cdup %s,%s\n", isH ? 'h' : 'l',
11575              dis_buf,
11576              nameXMMReg(gregOfRM(modrm)));
11577          delta += 3+alen;
11578       }
11579
11580       breakup128to32s( sV, &s3, &s2, &s1, &s0 );
11581       putXMMReg( gregOfRM(modrm), 
11582                  isH ? mk128from32s( s3, s3, s1, s1 )
11583                      : mk128from32s( s2, s2, s0, s0 ) );
11584       goto decode_success;
11585    }
11586
11587    /* F2 0F 12 = MOVDDUP -- move from E (mem or xmm) to G (xmm),
11588       duplicating some lanes (0:1:0:1). */
11589    if (sz == 4 && insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x12) {
11590       IRTemp sV = newTemp(Ity_V128);
11591       IRTemp d0 = newTemp(Ity_I64);
11592
11593       modrm = insn[3];
11594       if (epartIsReg(modrm)) {
11595          assign( sV, getXMMReg( eregOfRM(modrm)) );
11596          DIP("movddup %s,%s\n", nameXMMReg(eregOfRM(modrm)),
11597                                 nameXMMReg(gregOfRM(modrm)));
11598          delta += 3+1;
11599          assign ( d0, unop(Iop_V128to64, mkexpr(sV)) );
11600       } else {
11601          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
11602          assign( d0, loadLE(Ity_I64, mkexpr(addr)) );
11603          DIP("movddup %s,%s\n", dis_buf,
11604                                 nameXMMReg(gregOfRM(modrm)));
11605          delta += 3+alen;
11606       }
11607
11608       putXMMReg( gregOfRM(modrm), binop(Iop_64HLtoV128,mkexpr(d0),mkexpr(d0)) );
11609       goto decode_success;
11610    }
11611
11612    /* F2 0F D0 = ADDSUBPS -- 32x4 +/-/+/- from E (mem or xmm) to G (xmm). */
11613    if (sz == 4 && insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0xD0) {
11614       IRTemp a3, a2, a1, a0, s3, s2, s1, s0;
11615       IRTemp eV   = newTemp(Ity_V128);
11616       IRTemp gV   = newTemp(Ity_V128);
11617       IRTemp addV = newTemp(Ity_V128);
11618       IRTemp subV = newTemp(Ity_V128);
11619       a3 = a2 = a1 = a0 = s3 = s2 = s1 = s0 = IRTemp_INVALID;
11620
11621       modrm = insn[3];
11622       if (epartIsReg(modrm)) {
11623          assign( eV, getXMMReg( eregOfRM(modrm)) );
11624          DIP("addsubps %s,%s\n", nameXMMReg(eregOfRM(modrm)),
11625                                  nameXMMReg(gregOfRM(modrm)));
11626          delta += 3+1;
11627       } else {
11628          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
11629          assign( eV, loadLE(Ity_V128, mkexpr(addr)) );
11630          DIP("addsubps %s,%s\n", dis_buf,
11631                                  nameXMMReg(gregOfRM(modrm)));
11632          delta += 3+alen;
11633       }
11634
11635       assign( gV, getXMMReg(gregOfRM(modrm)) );
11636
11637       assign( addV, binop(Iop_Add32Fx4, mkexpr(gV), mkexpr(eV)) );
11638       assign( subV, binop(Iop_Sub32Fx4, mkexpr(gV), mkexpr(eV)) );
11639
11640       breakup128to32s( addV, &a3, &a2, &a1, &a0 );
11641       breakup128to32s( subV, &s3, &s2, &s1, &s0 );
11642
11643       putXMMReg( gregOfRM(modrm), mk128from32s( a3, s2, a1, s0 ));
11644       goto decode_success;
11645    }
11646
11647    /* 66 0F D0 = ADDSUBPD -- 64x4 +/- from E (mem or xmm) to G (xmm). */
11648    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xD0) {
11649       IRTemp eV   = newTemp(Ity_V128);
11650       IRTemp gV   = newTemp(Ity_V128);
11651       IRTemp addV = newTemp(Ity_V128);
11652       IRTemp subV = newTemp(Ity_V128);
11653       IRTemp a1     = newTemp(Ity_I64);
11654       IRTemp s0     = newTemp(Ity_I64);
11655
11656       modrm = insn[2];
11657       if (epartIsReg(modrm)) {
11658          assign( eV, getXMMReg( eregOfRM(modrm)) );
11659          DIP("addsubpd %s,%s\n", nameXMMReg(eregOfRM(modrm)),
11660                                  nameXMMReg(gregOfRM(modrm)));
11661          delta += 2+1;
11662       } else {
11663          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
11664          assign( eV, loadLE(Ity_V128, mkexpr(addr)) );
11665          DIP("addsubpd %s,%s\n", dis_buf,
11666                                  nameXMMReg(gregOfRM(modrm)));
11667          delta += 2+alen;
11668       }
11669
11670       assign( gV, getXMMReg(gregOfRM(modrm)) );
11671
11672       assign( addV, binop(Iop_Add64Fx2, mkexpr(gV), mkexpr(eV)) );
11673       assign( subV, binop(Iop_Sub64Fx2, mkexpr(gV), mkexpr(eV)) );
11674
11675       assign( a1, unop(Iop_V128HIto64, mkexpr(addV) ));
11676       assign( s0, unop(Iop_V128to64,   mkexpr(subV) ));
11677
11678       putXMMReg( gregOfRM(modrm), 
11679                  binop(Iop_64HLtoV128, mkexpr(a1), mkexpr(s0)) );
11680       goto decode_success;
11681    }
11682
11683    /* F2 0F 7D = HSUBPS -- 32x4 sub across from E (mem or xmm) to G (xmm). */
11684    /* F2 0F 7C = HADDPS -- 32x4 add across from E (mem or xmm) to G (xmm). */
11685    if (sz == 4 && insn[0] == 0xF2 && insn[1] == 0x0F 
11686        && (insn[2] == 0x7C || insn[2] == 0x7D)) {
11687       IRTemp e3, e2, e1, e0, g3, g2, g1, g0;
11688       IRTemp eV     = newTemp(Ity_V128);
11689       IRTemp gV     = newTemp(Ity_V128);
11690       IRTemp leftV  = newTemp(Ity_V128);
11691       IRTemp rightV = newTemp(Ity_V128);
11692       Bool   isAdd  = insn[2] == 0x7C;
11693       HChar* str    = isAdd ? "add" : "sub";
11694       e3 = e2 = e1 = e0 = g3 = g2 = g1 = g0 = IRTemp_INVALID;
11695
11696       modrm = insn[3];
11697       if (epartIsReg(modrm)) {
11698          assign( eV, getXMMReg( eregOfRM(modrm)) );
11699          DIP("h%sps %s,%s\n", str, nameXMMReg(eregOfRM(modrm)),
11700                                    nameXMMReg(gregOfRM(modrm)));
11701          delta += 3+1;
11702       } else {
11703          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
11704          assign( eV, loadLE(Ity_V128, mkexpr(addr)) );
11705          DIP("h%sps %s,%s\n", str, dis_buf,
11706                                    nameXMMReg(gregOfRM(modrm)));
11707          delta += 3+alen;
11708       }
11709
11710       assign( gV, getXMMReg(gregOfRM(modrm)) );
11711
11712       breakup128to32s( eV, &e3, &e2, &e1, &e0 );
11713       breakup128to32s( gV, &g3, &g2, &g1, &g0 );
11714
11715       assign( leftV,  mk128from32s( e2, e0, g2, g0 ) );
11716       assign( rightV, mk128from32s( e3, e1, g3, g1 ) );
11717
11718       putXMMReg( gregOfRM(modrm), 
11719                  binop(isAdd ? Iop_Add32Fx4 : Iop_Sub32Fx4, 
11720                        mkexpr(leftV), mkexpr(rightV) ) );
11721       goto decode_success;
11722    }
11723
11724    /* 66 0F 7D = HSUBPD -- 64x2 sub across from E (mem or xmm) to G (xmm). */
11725    /* 66 0F 7C = HADDPD -- 64x2 add across from E (mem or xmm) to G (xmm). */
11726    if (sz == 2 && insn[0] == 0x0F && (insn[1] == 0x7C || insn[1] == 0x7D)) {
11727       IRTemp e1     = newTemp(Ity_I64);
11728       IRTemp e0     = newTemp(Ity_I64);
11729       IRTemp g1     = newTemp(Ity_I64);
11730       IRTemp g0     = newTemp(Ity_I64);
11731       IRTemp eV     = newTemp(Ity_V128);
11732       IRTemp gV     = newTemp(Ity_V128);
11733       IRTemp leftV  = newTemp(Ity_V128);
11734       IRTemp rightV = newTemp(Ity_V128);
11735       Bool   isAdd  = insn[1] == 0x7C;
11736       HChar* str    = isAdd ? "add" : "sub";
11737
11738       modrm = insn[2];
11739       if (epartIsReg(modrm)) {
11740          assign( eV, getXMMReg( eregOfRM(modrm)) );
11741          DIP("h%spd %s,%s\n", str, nameXMMReg(eregOfRM(modrm)),
11742                                    nameXMMReg(gregOfRM(modrm)));
11743          delta += 2+1;
11744       } else {
11745          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
11746          assign( eV, loadLE(Ity_V128, mkexpr(addr)) );
11747          DIP("h%spd %s,%s\n", str, dis_buf,
11748                               nameXMMReg(gregOfRM(modrm)));
11749          delta += 2+alen;
11750       }
11751
11752       assign( gV, getXMMReg(gregOfRM(modrm)) );
11753
11754       assign( e1, unop(Iop_V128HIto64, mkexpr(eV) ));
11755       assign( e0, unop(Iop_V128to64, mkexpr(eV) ));
11756       assign( g1, unop(Iop_V128HIto64, mkexpr(gV) ));
11757       assign( g0, unop(Iop_V128to64, mkexpr(gV) ));
11758
11759       assign( leftV,  binop(Iop_64HLtoV128, mkexpr(e0),mkexpr(g0)) );
11760       assign( rightV, binop(Iop_64HLtoV128, mkexpr(e1),mkexpr(g1)) );
11761
11762       putXMMReg( gregOfRM(modrm), 
11763                  binop(isAdd ? Iop_Add64Fx2 : Iop_Sub64Fx2, 
11764                        mkexpr(leftV), mkexpr(rightV) ) );
11765       goto decode_success;
11766    }
11767
11768    /* F2 0F F0 = LDDQU -- move from E (mem or xmm) to G (xmm). */
11769    if (sz == 4 && insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0xF0) {
11770       modrm = getIByte(delta+3);
11771       if (epartIsReg(modrm)) {
11772          goto decode_failure;
11773       } else {
11774          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
11775          putXMMReg( gregOfRM(modrm), 
11776                     loadLE(Ity_V128, mkexpr(addr)) );
11777          DIP("lddqu %s,%s\n", dis_buf,
11778                               nameXMMReg(gregOfRM(modrm)));
11779          delta += 3+alen;
11780       }
11781       goto decode_success;
11782    }
11783
11784    /* ---------------------------------------------------- */
11785    /* --- end of the SSE3 decoder.                     --- */
11786    /* ---------------------------------------------------- */
11787
11788    /* ---------------------------------------------------- */
11789    /* --- start of the SSSE3 decoder.                  --- */
11790    /* ---------------------------------------------------- */
11791
11792    /* 0F 38 04 = PMADDUBSW -- Multiply and Add Packed Signed and
11793       Unsigned Bytes (MMX) */
11794    if (sz == 4
11795        && insn[0] == 0x0F && insn[1] == 0x38 && insn[2] == 0x04) {
11796       IRTemp sV        = newTemp(Ity_I64);
11797       IRTemp dV        = newTemp(Ity_I64);
11798       IRTemp sVoddsSX  = newTemp(Ity_I64);
11799       IRTemp sVevensSX = newTemp(Ity_I64);
11800       IRTemp dVoddsZX  = newTemp(Ity_I64);
11801       IRTemp dVevensZX = newTemp(Ity_I64);
11802
11803       modrm = insn[3];
11804       do_MMX_preamble();
11805       assign( dV, getMMXReg(gregOfRM(modrm)) );
11806
11807       if (epartIsReg(modrm)) {
11808          assign( sV, getMMXReg(eregOfRM(modrm)) );
11809          delta += 3+1;
11810          DIP("pmaddubsw %s,%s\n", nameMMXReg(eregOfRM(modrm)),
11811                                   nameMMXReg(gregOfRM(modrm)));
11812       } else {
11813          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
11814          assign( sV, loadLE(Ity_I64, mkexpr(addr)) );
11815          delta += 3+alen;
11816          DIP("pmaddubsw %s,%s\n", dis_buf,
11817                                   nameMMXReg(gregOfRM(modrm)));
11818       }
11819
11820       /* compute dV unsigned x sV signed */
11821       assign( sVoddsSX,
11822               binop(Iop_SarN16x4, mkexpr(sV), mkU8(8)) );
11823       assign( sVevensSX,
11824               binop(Iop_SarN16x4, 
11825                     binop(Iop_ShlN16x4, mkexpr(sV), mkU8(8)), 
11826                     mkU8(8)) );
11827       assign( dVoddsZX,
11828               binop(Iop_ShrN16x4, mkexpr(dV), mkU8(8)) );
11829       assign( dVevensZX,
11830               binop(Iop_ShrN16x4,
11831                     binop(Iop_ShlN16x4, mkexpr(dV), mkU8(8)),
11832                     mkU8(8)) );
11833
11834       putMMXReg(
11835          gregOfRM(modrm),
11836          binop(Iop_QAdd16Sx4,
11837                binop(Iop_Mul16x4, mkexpr(sVoddsSX), mkexpr(dVoddsZX)),
11838                binop(Iop_Mul16x4, mkexpr(sVevensSX), mkexpr(dVevensZX))
11839          )
11840       );
11841       goto decode_success;
11842    }
11843
11844    /* 66 0F 38 04 = PMADDUBSW -- Multiply and Add Packed Signed and
11845       Unsigned Bytes (XMM) */
11846    if (sz == 2
11847        && insn[0] == 0x0F && insn[1] == 0x38 && insn[2] == 0x04) {
11848       IRTemp sV        = newTemp(Ity_V128);
11849       IRTemp dV        = newTemp(Ity_V128);
11850       IRTemp sVoddsSX  = newTemp(Ity_V128);
11851       IRTemp sVevensSX = newTemp(Ity_V128);
11852       IRTemp dVoddsZX  = newTemp(Ity_V128);
11853       IRTemp dVevensZX = newTemp(Ity_V128);
11854
11855       modrm = insn[3];
11856       assign( dV, getXMMReg(gregOfRM(modrm)) );
11857
11858       if (epartIsReg(modrm)) {
11859          assign( sV, getXMMReg(eregOfRM(modrm)) );
11860          delta += 3+1;
11861          DIP("pmaddubsw %s,%s\n", nameXMMReg(eregOfRM(modrm)),
11862                                   nameXMMReg(gregOfRM(modrm)));
11863       } else {
11864          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
11865          gen_SEGV_if_not_16_aligned( addr );
11866          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
11867          delta += 3+alen;
11868          DIP("pmaddubsw %s,%s\n", dis_buf,
11869                                   nameXMMReg(gregOfRM(modrm)));
11870       }
11871
11872       /* compute dV unsigned x sV signed */
11873       assign( sVoddsSX,
11874               binop(Iop_SarN16x8, mkexpr(sV), mkU8(8)) );
11875       assign( sVevensSX,
11876               binop(Iop_SarN16x8, 
11877                     binop(Iop_ShlN16x8, mkexpr(sV), mkU8(8)), 
11878                     mkU8(8)) );
11879       assign( dVoddsZX,
11880               binop(Iop_ShrN16x8, mkexpr(dV), mkU8(8)) );
11881       assign( dVevensZX,
11882               binop(Iop_ShrN16x8,
11883                     binop(Iop_ShlN16x8, mkexpr(dV), mkU8(8)),
11884                     mkU8(8)) );
11885
11886       putXMMReg(
11887          gregOfRM(modrm),
11888          binop(Iop_QAdd16Sx8,
11889                binop(Iop_Mul16x8, mkexpr(sVoddsSX), mkexpr(dVoddsZX)),
11890                binop(Iop_Mul16x8, mkexpr(sVevensSX), mkexpr(dVevensZX))
11891          )
11892       );
11893       goto decode_success;
11894    }
11895
11896    /* ***--- these are MMX class insns introduced in SSSE3 ---*** */
11897    /* 0F 38 03 = PHADDSW -- 16x4 signed qadd across from E (mem or
11898       mmx) and G to G (mmx). */
11899    /* 0F 38 07 = PHSUBSW -- 16x4 signed qsub across from E (mem or
11900       mmx) and G to G (mmx). */
11901    /* 0F 38 01 = PHADDW -- 16x4 add across from E (mem or mmx) and G
11902       to G (mmx). */
11903    /* 0F 38 05 = PHSUBW -- 16x4 sub across from E (mem or mmx) and G
11904       to G (mmx). */
11905    /* 0F 38 02 = PHADDD -- 32x2 add across from E (mem or mmx) and G
11906       to G (mmx). */
11907    /* 0F 38 06 = PHSUBD -- 32x2 sub across from E (mem or mmx) and G
11908       to G (mmx). */
11909
11910    if (sz == 4 
11911        && insn[0] == 0x0F && insn[1] == 0x38 
11912        && (insn[2] == 0x03 || insn[2] == 0x07 || insn[2] == 0x01
11913            || insn[2] == 0x05 || insn[2] == 0x02 || insn[2] == 0x06)) {
11914       HChar* str    = "???";
11915       IROp   opV64  = Iop_INVALID;
11916       IROp   opCatO = Iop_CatOddLanes16x4;
11917       IROp   opCatE = Iop_CatEvenLanes16x4;
11918       IRTemp sV     = newTemp(Ity_I64);
11919       IRTemp dV     = newTemp(Ity_I64);
11920
11921       modrm = insn[3];
11922
11923       switch (insn[2]) {
11924          case 0x03: opV64 = Iop_QAdd16Sx4; str = "addsw"; break;
11925          case 0x07: opV64 = Iop_QSub16Sx4; str = "subsw"; break;
11926          case 0x01: opV64 = Iop_Add16x4;   str = "addw";  break;
11927          case 0x05: opV64 = Iop_Sub16x4;   str = "subw";  break;
11928          case 0x02: opV64 = Iop_Add32x2;   str = "addd";  break;
11929          case 0x06: opV64 = Iop_Sub32x2;   str = "subd";  break;
11930          default: vassert(0);
11931       }
11932       if (insn[2] == 0x02 || insn[2] == 0x06) {
11933          opCatO = Iop_InterleaveHI32x2;
11934          opCatE = Iop_InterleaveLO32x2;
11935       }
11936
11937       do_MMX_preamble();
11938       assign( dV, getMMXReg(gregOfRM(modrm)) );
11939
11940       if (epartIsReg(modrm)) {
11941          assign( sV, getMMXReg(eregOfRM(modrm)) );
11942          delta += 3+1;
11943          DIP("ph%s %s,%s\n", str, nameMMXReg(eregOfRM(modrm)),
11944                                   nameMMXReg(gregOfRM(modrm)));
11945       } else {
11946          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
11947          assign( sV, loadLE(Ity_I64, mkexpr(addr)) );
11948          delta += 3+alen;
11949          DIP("ph%s %s,%s\n", str, dis_buf,
11950                                   nameMMXReg(gregOfRM(modrm)));
11951       }
11952
11953       putMMXReg(
11954          gregOfRM(modrm),
11955          binop(opV64,
11956                binop(opCatE,mkexpr(sV),mkexpr(dV)),
11957                binop(opCatO,mkexpr(sV),mkexpr(dV))
11958          )
11959       );
11960       goto decode_success;
11961    }
11962
11963    /* 66 0F 38 03 = PHADDSW -- 16x8 signed qadd across from E (mem or
11964       xmm) and G to G (xmm). */
11965    /* 66 0F 38 07 = PHSUBSW -- 16x8 signed qsub across from E (mem or
11966       xmm) and G to G (xmm). */
11967    /* 66 0F 38 01 = PHADDW -- 16x8 add across from E (mem or xmm) and
11968       G to G (xmm). */
11969    /* 66 0F 38 05 = PHSUBW -- 16x8 sub across from E (mem or xmm) and
11970       G to G (xmm). */
11971    /* 66 0F 38 02 = PHADDD -- 32x4 add across from E (mem or xmm) and
11972       G to G (xmm). */
11973    /* 66 0F 38 06 = PHSUBD -- 32x4 sub across from E (mem or xmm) and
11974       G to G (xmm). */
11975
11976    if (sz == 2
11977        && insn[0] == 0x0F && insn[1] == 0x38 
11978        && (insn[2] == 0x03 || insn[2] == 0x07 || insn[2] == 0x01
11979            || insn[2] == 0x05 || insn[2] == 0x02 || insn[2] == 0x06)) {
11980       HChar* str    = "???";
11981       IROp   opV64  = Iop_INVALID;
11982       IROp   opCatO = Iop_CatOddLanes16x4;
11983       IROp   opCatE = Iop_CatEvenLanes16x4;
11984       IRTemp sV     = newTemp(Ity_V128);
11985       IRTemp dV     = newTemp(Ity_V128);
11986       IRTemp sHi    = newTemp(Ity_I64);
11987       IRTemp sLo    = newTemp(Ity_I64);
11988       IRTemp dHi    = newTemp(Ity_I64);
11989       IRTemp dLo    = newTemp(Ity_I64);
11990
11991       modrm = insn[3];
11992
11993       switch (insn[2]) {
11994          case 0x03: opV64 = Iop_QAdd16Sx4; str = "addsw"; break;
11995          case 0x07: opV64 = Iop_QSub16Sx4; str = "subsw"; break;
11996          case 0x01: opV64 = Iop_Add16x4;   str = "addw";  break;
11997          case 0x05: opV64 = Iop_Sub16x4;   str = "subw";  break;
11998          case 0x02: opV64 = Iop_Add32x2;   str = "addd";  break;
11999          case 0x06: opV64 = Iop_Sub32x2;   str = "subd";  break;
12000          default: vassert(0);
12001       }
12002       if (insn[2] == 0x02 || insn[2] == 0x06) {
12003          opCatO = Iop_InterleaveHI32x2;
12004          opCatE = Iop_InterleaveLO32x2;
12005       }
12006
12007       assign( dV, getXMMReg(gregOfRM(modrm)) );
12008
12009       if (epartIsReg(modrm)) {
12010          assign( sV, getXMMReg( eregOfRM(modrm)) );
12011          DIP("ph%s %s,%s\n", str, nameXMMReg(eregOfRM(modrm)),
12012                                   nameXMMReg(gregOfRM(modrm)));
12013          delta += 3+1;
12014       } else {
12015          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
12016          gen_SEGV_if_not_16_aligned( addr );
12017          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
12018          DIP("ph%s %s,%s\n", str, dis_buf,
12019                              nameXMMReg(gregOfRM(modrm)));
12020          delta += 3+alen;
12021       }
12022
12023       assign( dHi, unop(Iop_V128HIto64, mkexpr(dV)) );
12024       assign( dLo, unop(Iop_V128to64,   mkexpr(dV)) );
12025       assign( sHi, unop(Iop_V128HIto64, mkexpr(sV)) );
12026       assign( sLo, unop(Iop_V128to64,   mkexpr(sV)) );
12027
12028       /* This isn't a particularly efficient way to compute the
12029          result, but at least it avoids a proliferation of IROps,
12030          hence avoids complication all the backends. */
12031       putXMMReg(
12032          gregOfRM(modrm), 
12033          binop(Iop_64HLtoV128,
12034                binop(opV64,
12035                      binop(opCatE,mkexpr(sHi),mkexpr(sLo)),
12036                      binop(opCatO,mkexpr(sHi),mkexpr(sLo))
12037                ),
12038                binop(opV64,
12039                      binop(opCatE,mkexpr(dHi),mkexpr(dLo)),
12040                      binop(opCatO,mkexpr(dHi),mkexpr(dLo))
12041                )
12042          )
12043       );
12044       goto decode_success;
12045    }
12046
12047    /* 0F 38 0B = PMULHRSW -- Packed Multiply High with Round and Scale
12048       (MMX) */
12049    if (sz == 4 
12050        && insn[0] == 0x0F && insn[1] == 0x38 && insn[2] == 0x0B) {
12051       IRTemp sV = newTemp(Ity_I64);
12052       IRTemp dV = newTemp(Ity_I64);
12053
12054       modrm = insn[3];
12055       do_MMX_preamble();
12056       assign( dV, getMMXReg(gregOfRM(modrm)) );
12057
12058       if (epartIsReg(modrm)) {
12059          assign( sV, getMMXReg(eregOfRM(modrm)) );
12060          delta += 3+1;
12061          DIP("pmulhrsw %s,%s\n", nameMMXReg(eregOfRM(modrm)),
12062                                  nameMMXReg(gregOfRM(modrm)));
12063       } else {
12064          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
12065          assign( sV, loadLE(Ity_I64, mkexpr(addr)) );
12066          delta += 3+alen;
12067          DIP("pmulhrsw %s,%s\n", dis_buf,
12068                                  nameMMXReg(gregOfRM(modrm)));
12069       }
12070
12071       putMMXReg(
12072          gregOfRM(modrm),
12073          dis_PMULHRSW_helper( mkexpr(sV), mkexpr(dV) )
12074       );
12075       goto decode_success;
12076    }
12077
12078    /* 66 0F 38 0B = PMULHRSW -- Packed Multiply High with Round and
12079       Scale (XMM) */
12080    if (sz == 2
12081        && insn[0] == 0x0F && insn[1] == 0x38 && insn[2] == 0x0B) {
12082       IRTemp sV  = newTemp(Ity_V128);
12083       IRTemp dV  = newTemp(Ity_V128);
12084       IRTemp sHi = newTemp(Ity_I64);
12085       IRTemp sLo = newTemp(Ity_I64);
12086       IRTemp dHi = newTemp(Ity_I64);
12087       IRTemp dLo = newTemp(Ity_I64);
12088
12089       modrm = insn[3];
12090       assign( dV, getXMMReg(gregOfRM(modrm)) );
12091
12092       if (epartIsReg(modrm)) {
12093          assign( sV, getXMMReg(eregOfRM(modrm)) );
12094          delta += 3+1;
12095          DIP("pmulhrsw %s,%s\n", nameXMMReg(eregOfRM(modrm)),
12096                                  nameXMMReg(gregOfRM(modrm)));
12097       } else {
12098          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
12099          gen_SEGV_if_not_16_aligned( addr );
12100          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
12101          delta += 3+alen;
12102          DIP("pmulhrsw %s,%s\n", dis_buf,
12103                                  nameXMMReg(gregOfRM(modrm)));
12104       }
12105
12106       assign( dHi, unop(Iop_V128HIto64, mkexpr(dV)) );
12107       assign( dLo, unop(Iop_V128to64,   mkexpr(dV)) );
12108       assign( sHi, unop(Iop_V128HIto64, mkexpr(sV)) );
12109       assign( sLo, unop(Iop_V128to64,   mkexpr(sV)) );
12110
12111       putXMMReg(
12112          gregOfRM(modrm),
12113          binop(Iop_64HLtoV128,
12114                dis_PMULHRSW_helper( mkexpr(sHi), mkexpr(dHi) ),
12115                dis_PMULHRSW_helper( mkexpr(sLo), mkexpr(dLo) )
12116          )
12117       );
12118       goto decode_success;
12119    }
12120
12121    /* 0F 38 08 = PSIGNB -- Packed Sign 8x8  (MMX) */
12122    /* 0F 38 09 = PSIGNW -- Packed Sign 16x4 (MMX) */
12123    /* 0F 38 09 = PSIGND -- Packed Sign 32x2 (MMX) */
12124    if (sz == 4 
12125        && insn[0] == 0x0F && insn[1] == 0x38 
12126        && (insn[2] == 0x08 || insn[2] == 0x09 || insn[2] == 0x0A)) {
12127       IRTemp sV      = newTemp(Ity_I64);
12128       IRTemp dV      = newTemp(Ity_I64);
12129       HChar* str     = "???";
12130       Int    laneszB = 0;
12131
12132       switch (insn[2]) {
12133          case 0x08: laneszB = 1; str = "b"; break;
12134          case 0x09: laneszB = 2; str = "w"; break;
12135          case 0x0A: laneszB = 4; str = "d"; break;
12136          default: vassert(0);
12137       }
12138
12139       modrm = insn[3];
12140       do_MMX_preamble();
12141       assign( dV, getMMXReg(gregOfRM(modrm)) );
12142
12143       if (epartIsReg(modrm)) {
12144          assign( sV, getMMXReg(eregOfRM(modrm)) );
12145          delta += 3+1;
12146          DIP("psign%s %s,%s\n", str, nameMMXReg(eregOfRM(modrm)),
12147                                      nameMMXReg(gregOfRM(modrm)));
12148       } else {
12149          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
12150          assign( sV, loadLE(Ity_I64, mkexpr(addr)) );
12151          delta += 3+alen;
12152          DIP("psign%s %s,%s\n", str, dis_buf,
12153                                      nameMMXReg(gregOfRM(modrm)));
12154       }
12155
12156       putMMXReg(
12157          gregOfRM(modrm),
12158          dis_PSIGN_helper( mkexpr(sV), mkexpr(dV), laneszB )
12159       );
12160       goto decode_success;
12161    }
12162
12163    /* 66 0F 38 08 = PSIGNB -- Packed Sign 8x16 (XMM) */
12164    /* 66 0F 38 09 = PSIGNW -- Packed Sign 16x8 (XMM) */
12165    /* 66 0F 38 09 = PSIGND -- Packed Sign 32x4 (XMM) */
12166    if (sz == 2
12167        && insn[0] == 0x0F && insn[1] == 0x38 
12168        && (insn[2] == 0x08 || insn[2] == 0x09 || insn[2] == 0x0A)) {
12169       IRTemp sV      = newTemp(Ity_V128);
12170       IRTemp dV      = newTemp(Ity_V128);
12171       IRTemp sHi     = newTemp(Ity_I64);
12172       IRTemp sLo     = newTemp(Ity_I64);
12173       IRTemp dHi     = newTemp(Ity_I64);
12174       IRTemp dLo     = newTemp(Ity_I64);
12175       HChar* str     = "???";
12176       Int    laneszB = 0;
12177
12178       switch (insn[2]) {
12179          case 0x08: laneszB = 1; str = "b"; break;
12180          case 0x09: laneszB = 2; str = "w"; break;
12181          case 0x0A: laneszB = 4; str = "d"; break;
12182          default: vassert(0);
12183       }
12184
12185       modrm = insn[3];
12186       assign( dV, getXMMReg(gregOfRM(modrm)) );
12187
12188       if (epartIsReg(modrm)) {
12189          assign( sV, getXMMReg(eregOfRM(modrm)) );
12190          delta += 3+1;
12191          DIP("psign%s %s,%s\n", str, nameXMMReg(eregOfRM(modrm)),
12192                                      nameXMMReg(gregOfRM(modrm)));
12193       } else {
12194          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
12195          gen_SEGV_if_not_16_aligned( addr );
12196          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
12197          delta += 3+alen;
12198          DIP("psign%s %s,%s\n", str, dis_buf,
12199                                      nameXMMReg(gregOfRM(modrm)));
12200       }
12201
12202       assign( dHi, unop(Iop_V128HIto64, mkexpr(dV)) );
12203       assign( dLo, unop(Iop_V128to64,   mkexpr(dV)) );
12204       assign( sHi, unop(Iop_V128HIto64, mkexpr(sV)) );
12205       assign( sLo, unop(Iop_V128to64,   mkexpr(sV)) );
12206
12207       putXMMReg(
12208          gregOfRM(modrm),
12209          binop(Iop_64HLtoV128,
12210                dis_PSIGN_helper( mkexpr(sHi), mkexpr(dHi), laneszB ),
12211                dis_PSIGN_helper( mkexpr(sLo), mkexpr(dLo), laneszB )
12212          )
12213       );
12214       goto decode_success;
12215    }
12216
12217    /* 0F 38 1C = PABSB -- Packed Absolute Value 8x8  (MMX) */
12218    /* 0F 38 1D = PABSW -- Packed Absolute Value 16x4 (MMX) */
12219    /* 0F 38 1E = PABSD -- Packed Absolute Value 32x2 (MMX) */
12220    if (sz == 4 
12221        && insn[0] == 0x0F && insn[1] == 0x38 
12222        && (insn[2] == 0x1C || insn[2] == 0x1D || insn[2] == 0x1E)) {
12223       IRTemp sV      = newTemp(Ity_I64);
12224       HChar* str     = "???";
12225       Int    laneszB = 0;
12226
12227       switch (insn[2]) {
12228          case 0x1C: laneszB = 1; str = "b"; break;
12229          case 0x1D: laneszB = 2; str = "w"; break;
12230          case 0x1E: laneszB = 4; str = "d"; break;
12231          default: vassert(0);
12232       }
12233
12234       modrm = insn[3];
12235       do_MMX_preamble();
12236
12237       if (epartIsReg(modrm)) {
12238          assign( sV, getMMXReg(eregOfRM(modrm)) );
12239          delta += 3+1;
12240          DIP("pabs%s %s,%s\n", str, nameMMXReg(eregOfRM(modrm)),
12241                                     nameMMXReg(gregOfRM(modrm)));
12242       } else {
12243          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
12244          assign( sV, loadLE(Ity_I64, mkexpr(addr)) );
12245          delta += 3+alen;
12246          DIP("pabs%s %s,%s\n", str, dis_buf,
12247                                     nameMMXReg(gregOfRM(modrm)));
12248       }
12249
12250       putMMXReg(
12251          gregOfRM(modrm),
12252          dis_PABS_helper( mkexpr(sV), laneszB )
12253       );
12254       goto decode_success;
12255    }
12256
12257    /* 66 0F 38 1C = PABSB -- Packed Absolute Value 8x16 (XMM) */
12258    /* 66 0F 38 1D = PABSW -- Packed Absolute Value 16x8 (XMM) */
12259    /* 66 0F 38 1E = PABSD -- Packed Absolute Value 32x4 (XMM) */
12260    if (sz == 2
12261        && insn[0] == 0x0F && insn[1] == 0x38 
12262        && (insn[2] == 0x1C || insn[2] == 0x1D || insn[2] == 0x1E)) {
12263       IRTemp sV      = newTemp(Ity_V128);
12264       IRTemp sHi     = newTemp(Ity_I64);
12265       IRTemp sLo     = newTemp(Ity_I64);
12266       HChar* str     = "???";
12267       Int    laneszB = 0;
12268
12269       switch (insn[2]) {
12270          case 0x1C: laneszB = 1; str = "b"; break;
12271          case 0x1D: laneszB = 2; str = "w"; break;
12272          case 0x1E: laneszB = 4; str = "d"; break;
12273          default: vassert(0);
12274       }
12275
12276       modrm = insn[3];
12277
12278       if (epartIsReg(modrm)) {
12279          assign( sV, getXMMReg(eregOfRM(modrm)) );
12280          delta += 3+1;
12281          DIP("pabs%s %s,%s\n", str, nameXMMReg(eregOfRM(modrm)),
12282                                     nameXMMReg(gregOfRM(modrm)));
12283       } else {
12284          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
12285          gen_SEGV_if_not_16_aligned( addr );
12286          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
12287          delta += 3+alen;
12288          DIP("pabs%s %s,%s\n", str, dis_buf,
12289                                     nameXMMReg(gregOfRM(modrm)));
12290       }
12291
12292       assign( sHi, unop(Iop_V128HIto64, mkexpr(sV)) );
12293       assign( sLo, unop(Iop_V128to64,   mkexpr(sV)) );
12294
12295       putXMMReg(
12296          gregOfRM(modrm),
12297          binop(Iop_64HLtoV128,
12298                dis_PABS_helper( mkexpr(sHi), laneszB ),
12299                dis_PABS_helper( mkexpr(sLo), laneszB )
12300          )
12301       );
12302       goto decode_success;
12303    }
12304
12305    /* 0F 3A 0F = PALIGNR -- Packed Align Right (MMX) */
12306    if (sz == 4 
12307        && insn[0] == 0x0F && insn[1] == 0x3A && insn[2] == 0x0F) {
12308       IRTemp sV  = newTemp(Ity_I64);
12309       IRTemp dV  = newTemp(Ity_I64);
12310       IRTemp res = newTemp(Ity_I64);
12311
12312       modrm = insn[3];
12313       do_MMX_preamble();
12314       assign( dV, getMMXReg(gregOfRM(modrm)) );
12315
12316       if (epartIsReg(modrm)) {
12317          assign( sV, getMMXReg(eregOfRM(modrm)) );
12318          d32 = (UInt)insn[3+1];
12319          delta += 3+1+1;
12320          DIP("palignr $%d,%s,%s\n",  (Int)d32, 
12321                                      nameMMXReg(eregOfRM(modrm)),
12322                                      nameMMXReg(gregOfRM(modrm)));
12323       } else {
12324          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
12325          assign( sV, loadLE(Ity_I64, mkexpr(addr)) );
12326          d32 = (UInt)insn[3+alen];
12327          delta += 3+alen+1;
12328          DIP("palignr $%d%s,%s\n", (Int)d32,
12329                                    dis_buf,
12330                                    nameMMXReg(gregOfRM(modrm)));
12331       }
12332
12333       if (d32 == 0) {
12334          assign( res, mkexpr(sV) );
12335       }
12336       else if (d32 >= 1 && d32 <= 7) {
12337          assign(res, 
12338                 binop(Iop_Or64,
12339                       binop(Iop_Shr64, mkexpr(sV), mkU8(8*d32)),
12340                       binop(Iop_Shl64, mkexpr(dV), mkU8(8*(8-d32))
12341                      )));
12342       }
12343       else if (d32 == 8) {
12344         assign( res, mkexpr(dV) );
12345       }
12346       else if (d32 >= 9 && d32 <= 15) {
12347          assign( res, binop(Iop_Shr64, mkexpr(dV), mkU8(8*(d32-8))) );
12348       }
12349       else if (d32 >= 16 && d32 <= 255) {
12350          assign( res, mkU64(0) );
12351       }
12352       else
12353          vassert(0);
12354
12355       putMMXReg( gregOfRM(modrm), mkexpr(res) );
12356       goto decode_success;
12357    }
12358
12359    /* 66 0F 3A 0F = PALIGNR -- Packed Align Right (XMM) */
12360    if (sz == 2
12361        && insn[0] == 0x0F && insn[1] == 0x3A && insn[2] == 0x0F) {
12362       IRTemp sV  = newTemp(Ity_V128);
12363       IRTemp dV  = newTemp(Ity_V128);
12364       IRTemp sHi = newTemp(Ity_I64);
12365       IRTemp sLo = newTemp(Ity_I64);
12366       IRTemp dHi = newTemp(Ity_I64);
12367       IRTemp dLo = newTemp(Ity_I64);
12368       IRTemp rHi = newTemp(Ity_I64);
12369       IRTemp rLo = newTemp(Ity_I64);
12370
12371       modrm = insn[3];
12372       assign( dV, getXMMReg(gregOfRM(modrm)) );
12373
12374       if (epartIsReg(modrm)) {
12375          assign( sV, getXMMReg(eregOfRM(modrm)) );
12376          d32 = (UInt)insn[3+1];
12377          delta += 3+1+1;
12378          DIP("palignr $%d,%s,%s\n", (Int)d32,
12379                                     nameXMMReg(eregOfRM(modrm)),
12380                                     nameXMMReg(gregOfRM(modrm)));
12381       } else {
12382          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
12383          gen_SEGV_if_not_16_aligned( addr );
12384          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
12385          d32 = (UInt)insn[3+alen];
12386          delta += 3+alen+1;
12387          DIP("palignr $%d,%s,%s\n", (Int)d32,
12388                                     dis_buf,
12389                                     nameXMMReg(gregOfRM(modrm)));
12390       }
12391
12392       assign( dHi, unop(Iop_V128HIto64, mkexpr(dV)) );
12393       assign( dLo, unop(Iop_V128to64,   mkexpr(dV)) );
12394       assign( sHi, unop(Iop_V128HIto64, mkexpr(sV)) );
12395       assign( sLo, unop(Iop_V128to64,   mkexpr(sV)) );
12396
12397       if (d32 == 0) {
12398          assign( rHi, mkexpr(sHi) );
12399          assign( rLo, mkexpr(sLo) );
12400       }
12401       else if (d32 >= 1 && d32 <= 7) {
12402          assign( rHi, dis_PALIGNR_XMM_helper(dLo, sHi, d32) );
12403          assign( rLo, dis_PALIGNR_XMM_helper(sHi, sLo, d32) );
12404       }
12405       else if (d32 == 8) {
12406          assign( rHi, mkexpr(dLo) );
12407          assign( rLo, mkexpr(sHi) );
12408       }
12409       else if (d32 >= 9 && d32 <= 15) {
12410          assign( rHi, dis_PALIGNR_XMM_helper(dHi, dLo, d32-8) );
12411          assign( rLo, dis_PALIGNR_XMM_helper(dLo, sHi, d32-8) );
12412       }
12413       else if (d32 == 16) {
12414          assign( rHi, mkexpr(dHi) );
12415          assign( rLo, mkexpr(dLo) );
12416       }
12417       else if (d32 >= 17 && d32 <= 23) {
12418          assign( rHi, binop(Iop_Shr64, mkexpr(dHi), mkU8(8*(d32-16))) );
12419          assign( rLo, dis_PALIGNR_XMM_helper(dHi, dLo, d32-16) );
12420       }
12421       else if (d32 == 24) {
12422          assign( rHi, mkU64(0) );
12423          assign( rLo, mkexpr(dHi) );
12424       }
12425       else if (d32 >= 25 && d32 <= 31) {
12426          assign( rHi, mkU64(0) );
12427          assign( rLo, binop(Iop_Shr64, mkexpr(dHi), mkU8(8*(d32-24))) );
12428       }
12429       else if (d32 >= 32 && d32 <= 255) {
12430          assign( rHi, mkU64(0) );
12431          assign( rLo, mkU64(0) );
12432       }
12433       else
12434          vassert(0);
12435
12436       putXMMReg(
12437          gregOfRM(modrm),
12438          binop(Iop_64HLtoV128, mkexpr(rHi), mkexpr(rLo))
12439       );
12440       goto decode_success;
12441    }
12442
12443    /* 0F 38 00 = PSHUFB -- Packed Shuffle Bytes 8x8 (MMX) */
12444    if (sz == 4 
12445        && insn[0] == 0x0F && insn[1] == 0x38 && insn[2] == 0x00) {
12446       IRTemp sV      = newTemp(Ity_I64);
12447       IRTemp dV      = newTemp(Ity_I64);
12448
12449       modrm = insn[3];
12450       do_MMX_preamble();
12451       assign( dV, getMMXReg(gregOfRM(modrm)) );
12452
12453       if (epartIsReg(modrm)) {
12454          assign( sV, getMMXReg(eregOfRM(modrm)) );
12455          delta += 3+1;
12456          DIP("pshufb %s,%s\n", nameMMXReg(eregOfRM(modrm)),
12457                                nameMMXReg(gregOfRM(modrm)));
12458       } else {
12459          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
12460          assign( sV, loadLE(Ity_I64, mkexpr(addr)) );
12461          delta += 3+alen;
12462          DIP("pshufb %s,%s\n", dis_buf,
12463                                nameMMXReg(gregOfRM(modrm)));
12464       }
12465
12466       putMMXReg(
12467          gregOfRM(modrm),
12468          binop(
12469             Iop_And64,
12470             /* permute the lanes */
12471             binop(
12472                Iop_Perm8x8,
12473                mkexpr(dV),
12474                binop(Iop_And64, mkexpr(sV), mkU64(0x0707070707070707ULL))
12475             ),
12476             /* mask off lanes which have (index & 0x80) == 0x80 */
12477             unop(Iop_Not64, binop(Iop_SarN8x8, mkexpr(sV), mkU8(7)))
12478          )
12479       );
12480       goto decode_success;
12481    }
12482
12483    /* 66 0F 38 00 = PSHUFB -- Packed Shuffle Bytes 8x16 (XMM) */
12484    if (sz == 2
12485        && insn[0] == 0x0F && insn[1] == 0x38 && insn[2] == 0x00) {
12486       IRTemp sV         = newTemp(Ity_V128);
12487       IRTemp dV         = newTemp(Ity_V128);
12488       IRTemp sHi        = newTemp(Ity_I64);
12489       IRTemp sLo        = newTemp(Ity_I64);
12490       IRTemp dHi        = newTemp(Ity_I64);
12491       IRTemp dLo        = newTemp(Ity_I64);
12492       IRTemp rHi        = newTemp(Ity_I64);
12493       IRTemp rLo        = newTemp(Ity_I64);
12494       IRTemp sevens     = newTemp(Ity_I64);
12495       IRTemp mask0x80hi = newTemp(Ity_I64);
12496       IRTemp mask0x80lo = newTemp(Ity_I64);
12497       IRTemp maskBit3hi = newTemp(Ity_I64);
12498       IRTemp maskBit3lo = newTemp(Ity_I64);
12499       IRTemp sAnd7hi    = newTemp(Ity_I64);
12500       IRTemp sAnd7lo    = newTemp(Ity_I64);
12501       IRTemp permdHi    = newTemp(Ity_I64);
12502       IRTemp permdLo    = newTemp(Ity_I64);
12503
12504       modrm = insn[3];
12505       assign( dV, getXMMReg(gregOfRM(modrm)) );
12506
12507       if (epartIsReg(modrm)) {
12508          assign( sV, getXMMReg(eregOfRM(modrm)) );
12509          delta += 3+1;
12510          DIP("pshufb %s,%s\n", nameXMMReg(eregOfRM(modrm)),
12511                                nameXMMReg(gregOfRM(modrm)));
12512       } else {
12513          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
12514          gen_SEGV_if_not_16_aligned( addr );
12515          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
12516          delta += 3+alen;
12517          DIP("pshufb %s,%s\n", dis_buf,
12518                                nameXMMReg(gregOfRM(modrm)));
12519       }
12520
12521       assign( dHi, unop(Iop_V128HIto64, mkexpr(dV)) );
12522       assign( dLo, unop(Iop_V128to64,   mkexpr(dV)) );
12523       assign( sHi, unop(Iop_V128HIto64, mkexpr(sV)) );
12524       assign( sLo, unop(Iop_V128to64,   mkexpr(sV)) );
12525
12526       assign( sevens, mkU64(0x0707070707070707ULL) );
12527
12528       /*
12529       mask0x80hi = Not(SarN8x8(sHi,7))
12530       maskBit3hi = SarN8x8(ShlN8x8(sHi,4),7)
12531       sAnd7hi    = And(sHi,sevens)
12532       permdHi    = Or( And(Perm8x8(dHi,sAnd7hi),maskBit3hi),
12533                        And(Perm8x8(dLo,sAnd7hi),Not(maskBit3hi)) )
12534       rHi        = And(permdHi,mask0x80hi)
12535       */
12536       assign(
12537          mask0x80hi,
12538          unop(Iop_Not64, binop(Iop_SarN8x8,mkexpr(sHi),mkU8(7))));
12539
12540       assign(
12541          maskBit3hi,
12542          binop(Iop_SarN8x8,
12543                binop(Iop_ShlN8x8,mkexpr(sHi),mkU8(4)),
12544                mkU8(7)));
12545
12546       assign(sAnd7hi, binop(Iop_And64,mkexpr(sHi),mkexpr(sevens)));
12547
12548       assign(
12549          permdHi,
12550          binop(
12551             Iop_Or64,
12552             binop(Iop_And64,
12553                   binop(Iop_Perm8x8,mkexpr(dHi),mkexpr(sAnd7hi)),
12554                   mkexpr(maskBit3hi)),
12555             binop(Iop_And64,
12556                   binop(Iop_Perm8x8,mkexpr(dLo),mkexpr(sAnd7hi)),
12557                   unop(Iop_Not64,mkexpr(maskBit3hi))) ));
12558
12559       assign(rHi, binop(Iop_And64,mkexpr(permdHi),mkexpr(mask0x80hi)) );
12560
12561       /* And the same for the lower half of the result.  What fun. */
12562
12563       assign(
12564          mask0x80lo,
12565          unop(Iop_Not64, binop(Iop_SarN8x8,mkexpr(sLo),mkU8(7))));
12566
12567       assign(
12568          maskBit3lo,
12569          binop(Iop_SarN8x8,
12570                binop(Iop_ShlN8x8,mkexpr(sLo),mkU8(4)),
12571                mkU8(7)));
12572
12573       assign(sAnd7lo, binop(Iop_And64,mkexpr(sLo),mkexpr(sevens)));
12574
12575       assign(
12576          permdLo,
12577          binop(
12578             Iop_Or64,
12579             binop(Iop_And64,
12580                   binop(Iop_Perm8x8,mkexpr(dHi),mkexpr(sAnd7lo)),
12581                   mkexpr(maskBit3lo)),
12582             binop(Iop_And64,
12583                   binop(Iop_Perm8x8,mkexpr(dLo),mkexpr(sAnd7lo)),
12584                   unop(Iop_Not64,mkexpr(maskBit3lo))) ));
12585
12586       assign(rLo, binop(Iop_And64,mkexpr(permdLo),mkexpr(mask0x80lo)) );
12587
12588       putXMMReg(
12589          gregOfRM(modrm),
12590          binop(Iop_64HLtoV128, mkexpr(rHi), mkexpr(rLo))
12591       );
12592       goto decode_success;
12593    }
12594
12595    /* ---------------------------------------------------- */
12596    /* --- end of the SSSE3 decoder.                    --- */
12597    /* ---------------------------------------------------- */
12598
12599    after_sse_decoders:
12600
12601    /* ---------------------------------------------------- */
12602    /* --- deal with misc 0x67 pfxs (addr size override) -- */
12603    /* ---------------------------------------------------- */
12604
12605    /* 67 E3 = JCXZ (for JECXZ see below) */
12606    if (insn[0] == 0x67 && insn[1] == 0xE3 && sz == 4) {
12607       delta += 2;
12608       d32 = (((Addr32)guest_EIP_bbstart)+delta+1) + getSDisp8(delta);
12609       delta ++;
12610       stmt( IRStmt_Exit(
12611                binop(Iop_CmpEQ16, getIReg(2,R_ECX), mkU16(0)),
12612                Ijk_Boring,
12613                IRConst_U32(d32)
12614             ));
12615        DIP("jcxz 0x%x\n", d32);
12616        goto decode_success;
12617    }
12618
12619    /* ---------------------------------------------------- */
12620    /* --- start of the baseline insn decoder            -- */
12621    /* ---------------------------------------------------- */
12622
12623    /* Get the primary opcode. */
12624    opc = getIByte(delta); delta++;
12625
12626    /* We get here if the current insn isn't SSE, or this CPU doesn't
12627       support SSE. */
12628
12629    switch (opc) {
12630
12631    /* ------------------------ Control flow --------------- */
12632
12633    case 0xC2: /* RET imm16 */
12634       d32 = getUDisp16(delta); 
12635       delta += 2;
12636       dis_ret(d32);
12637       dres.whatNext = Dis_StopHere;
12638       DIP("ret %d\n", (Int)d32);
12639       break;
12640    case 0xC3: /* RET */
12641       dis_ret(0);
12642       dres.whatNext = Dis_StopHere;
12643       DIP("ret\n");
12644       break;
12645
12646    case 0xCF: /* IRET */
12647       /* Note, this is an extremely kludgey and limited implementation
12648          of iret.  All it really does is: 
12649             popl %EIP; popl %CS; popl %EFLAGS.
12650          %CS is set but ignored (as it is in (eg) popw %cs)". */
12651       t1 = newTemp(Ity_I32); /* ESP */
12652       t2 = newTemp(Ity_I32); /* new EIP */
12653       t3 = newTemp(Ity_I32); /* new CS */
12654       t4 = newTemp(Ity_I32); /* new EFLAGS */
12655       assign(t1, getIReg(4,R_ESP));
12656       assign(t2, loadLE(Ity_I32, binop(Iop_Add32,mkexpr(t1),mkU32(0) )));
12657       assign(t3, loadLE(Ity_I32, binop(Iop_Add32,mkexpr(t1),mkU32(4) )));
12658       assign(t4, loadLE(Ity_I32, binop(Iop_Add32,mkexpr(t1),mkU32(8) )));
12659       /* Get stuff off stack */
12660       putIReg(4, R_ESP,binop(Iop_Add32, mkexpr(t1), mkU32(12)));
12661       /* set %CS (which is ignored anyway) */
12662       putSReg( R_CS, unop(Iop_32to16, mkexpr(t3)) );
12663       /* set %EFLAGS */
12664       set_EFLAGS_from_value( t4, False/*!emit_AC_emwarn*/, 0/*unused*/ );
12665       /* goto new EIP value */
12666       jmp_treg(Ijk_Ret,t2);
12667       dres.whatNext = Dis_StopHere;
12668       DIP("iret (very kludgey)\n");
12669       break;
12670
12671    case 0xE8: /* CALL J4 */
12672       d32 = getUDisp32(delta); delta += 4;
12673       d32 += (guest_EIP_bbstart+delta); 
12674       /* (guest_eip_bbstart+delta) == return-to addr, d32 == call-to addr */
12675       if (d32 == guest_EIP_bbstart+delta && getIByte(delta) >= 0x58 
12676                                          && getIByte(delta) <= 0x5F) {
12677          /* Specially treat the position-independent-code idiom 
12678                  call X
12679               X: popl %reg
12680             as 
12681                  movl %eip, %reg.
12682             since this generates better code, but for no other reason. */
12683          Int archReg = getIByte(delta) - 0x58;
12684          /* vex_printf("-- fPIC thingy\n"); */
12685          putIReg(4, archReg, mkU32(guest_EIP_bbstart+delta));
12686          delta++; /* Step over the POP */
12687          DIP("call 0x%x ; popl %s\n",d32,nameIReg(4,archReg));
12688       } else {
12689          /* The normal sequence for a call. */
12690          t1 = newTemp(Ity_I32); 
12691          assign(t1, binop(Iop_Sub32, getIReg(4,R_ESP), mkU32(4)));
12692          putIReg(4, R_ESP, mkexpr(t1));
12693          storeLE( mkexpr(t1), mkU32(guest_EIP_bbstart+delta));
12694          if (resteerOkFn( callback_opaque, (Addr64)(Addr32)d32 )) {
12695             /* follow into the call target. */
12696             dres.whatNext   = Dis_ResteerU;
12697             dres.continueAt = (Addr64)(Addr32)d32;
12698          } else {
12699             jmp_lit(Ijk_Call,d32);
12700             dres.whatNext = Dis_StopHere;
12701          }
12702          DIP("call 0x%x\n",d32);
12703       }
12704       break;
12705
12706 //--    case 0xC8: /* ENTER */ 
12707 //--       d32 = getUDisp16(eip); eip += 2;
12708 //--       abyte = getIByte(delta); delta++;
12709 //-- 
12710 //--       vg_assert(sz == 4);           
12711 //--       vg_assert(abyte == 0);
12712 //-- 
12713 //--       t1 = newTemp(cb); t2 = newTemp(cb);
12714 //--       uInstr2(cb, GET,   sz, ArchReg, R_EBP, TempReg, t1);
12715 //--       uInstr2(cb, GET,    4, ArchReg, R_ESP, TempReg, t2);
12716 //--       uInstr2(cb, SUB,    4, Literal, 0,     TempReg, t2);
12717 //--       uLiteral(cb, sz);
12718 //--       uInstr2(cb, PUT,    4, TempReg, t2,    ArchReg, R_ESP);
12719 //--       uInstr2(cb, STORE,  4, TempReg, t1,    TempReg, t2);
12720 //--       uInstr2(cb, PUT,    4, TempReg, t2,    ArchReg, R_EBP);
12721 //--       if (d32) {
12722 //--          uInstr2(cb, SUB,    4, Literal, 0,     TempReg, t2);
12723 //--          uLiteral(cb, d32);
12724 //--          uInstr2(cb, PUT,    4, TempReg, t2,    ArchReg, R_ESP);
12725 //--       }
12726 //--       DIP("enter 0x%x, 0x%x", d32, abyte);
12727 //--       break;
12728
12729    case 0xC9: /* LEAVE */
12730       vassert(sz == 4);
12731       t1 = newTemp(Ity_I32); t2 = newTemp(Ity_I32);
12732       assign(t1, getIReg(4,R_EBP));
12733       /* First PUT ESP looks redundant, but need it because ESP must
12734          always be up-to-date for Memcheck to work... */
12735       putIReg(4, R_ESP, mkexpr(t1));
12736       assign(t2, loadLE(Ity_I32,mkexpr(t1)));
12737       putIReg(4, R_EBP, mkexpr(t2));
12738       putIReg(4, R_ESP, binop(Iop_Add32, mkexpr(t1), mkU32(4)) );
12739       DIP("leave\n");
12740       break;
12741
12742    /* ---------------- Misc weird-ass insns --------------- */
12743
12744    case 0x27: /* DAA */
12745    case 0x2F: /* DAS */
12746    case 0x37: /* AAA */
12747    case 0x3F: /* AAS */
12748       /* An ugly implementation for some ugly instructions.  Oh
12749          well. */
12750       if (sz != 4) goto decode_failure;
12751       t1 = newTemp(Ity_I32);
12752       t2 = newTemp(Ity_I32);
12753       /* Make up a 32-bit value (t1), with the old value of AX in the
12754          bottom 16 bits, and the old OSZACP bitmask in the upper 16
12755          bits. */
12756       assign(t1, 
12757              binop(Iop_16HLto32, 
12758                    unop(Iop_32to16,
12759                         mk_x86g_calculate_eflags_all()),
12760                    getIReg(2, R_EAX)
12761             ));
12762       /* Call the helper fn, to get a new AX and OSZACP value, and
12763          poke both back into the guest state.  Also pass the helper
12764          the actual opcode so it knows which of the 4 instructions it
12765          is doing the computation for. */
12766       vassert(opc == 0x27 || opc == 0x2F || opc == 0x37 || opc == 0x3F);
12767       assign(t2,
12768               mkIRExprCCall(
12769                  Ity_I32, 0/*regparm*/, "x86g_calculate_daa_das_aaa_aas",
12770                  &x86g_calculate_daa_das_aaa_aas,
12771                  mkIRExprVec_2( mkexpr(t1), mkU32( opc & 0xFF) )
12772             ));
12773      putIReg(2, R_EAX, unop(Iop_32to16, mkexpr(t2) ));
12774
12775      stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(X86G_CC_OP_COPY) ));
12776      stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0) ));
12777      stmt( IRStmt_Put( OFFB_CC_DEP1, 
12778                        binop(Iop_And32,
12779                              binop(Iop_Shr32, mkexpr(t2), mkU8(16)),
12780                              mkU32( X86G_CC_MASK_C | X86G_CC_MASK_P 
12781                                     | X86G_CC_MASK_A | X86G_CC_MASK_Z 
12782                                     | X86G_CC_MASK_S| X86G_CC_MASK_O )
12783                             )
12784                       )
12785          );
12786      /* Set NDEP even though it isn't used.  This makes redundant-PUT
12787         elimination of previous stores to this field work better. */
12788      stmt( IRStmt_Put( OFFB_CC_NDEP, mkU32(0) ));
12789      switch (opc) {
12790         case 0x27: DIP("daa\n"); break;
12791         case 0x2F: DIP("das\n"); break;
12792         case 0x37: DIP("aaa\n"); break;
12793         case 0x3F: DIP("aas\n"); break;
12794         default: vassert(0);
12795      }
12796      break;
12797
12798 //--    case 0xD4: /* AAM */
12799 //--    case 0xD5: /* AAD */
12800 //--       d32 = getIByte(delta); delta++;
12801 //--       if (d32 != 10) VG_(core_panic)("disInstr: AAM/AAD but base not 10 !");
12802 //--       t1 = newTemp(cb);
12803 //--       uInstr2(cb, GET, 2, ArchReg, R_EAX, TempReg, t1);
12804 //--       /* Widen %AX to 32 bits, so it's all defined when we push it. */
12805 //--       uInstr1(cb, WIDEN, 4, TempReg, t1);
12806 //--       uWiden(cb, 2, False);
12807 //--       uInstr0(cb, CALLM_S, 0);
12808 //--       uInstr1(cb, PUSH, 4, TempReg, t1);
12809 //--       uInstr1(cb, CALLM, 0, Lit16, 
12810 //--                   opc == 0xD4 ? VGOFF_(helper_AAM) : VGOFF_(helper_AAD) );
12811 //--       uFlagsRWU(cb, FlagsEmpty, FlagsSZP, FlagsEmpty);
12812 //--       uInstr1(cb, POP, 4, TempReg, t1);
12813 //--       uInstr0(cb, CALLM_E, 0);
12814 //--       uInstr2(cb, PUT, 2, TempReg, t1, ArchReg, R_EAX);
12815 //--       DIP(opc == 0xD4 ? "aam\n" : "aad\n");
12816 //--       break;
12817
12818    /* ------------------------ CWD/CDQ -------------------- */
12819
12820    case 0x98: /* CBW */
12821       if (sz == 4) {
12822          putIReg(4, R_EAX, unop(Iop_16Sto32, getIReg(2, R_EAX)));
12823          DIP("cwde\n");
12824       } else {
12825          vassert(sz == 2);
12826          putIReg(2, R_EAX, unop(Iop_8Sto16, getIReg(1, R_EAX)));
12827          DIP("cbw\n");
12828       }
12829       break;
12830
12831    case 0x99: /* CWD/CDQ */
12832       ty = szToITy(sz);
12833       putIReg(sz, R_EDX,
12834                   binop(mkSizedOp(ty,Iop_Sar8), 
12835                         getIReg(sz, R_EAX),
12836                         mkU8(sz == 2 ? 15 : 31)) );
12837       DIP(sz == 2 ? "cwdq\n" : "cdqq\n");
12838       break;
12839
12840    /* ------------------------ FPU ops -------------------- */
12841
12842    case 0x9E: /* SAHF */
12843       codegen_SAHF();
12844       DIP("sahf\n");
12845       break;
12846
12847    case 0x9F: /* LAHF */
12848       codegen_LAHF();
12849       DIP("lahf\n");
12850       break;
12851
12852    case 0x9B: /* FWAIT */
12853       /* ignore? */
12854       DIP("fwait\n");
12855       break;
12856
12857    case 0xD8:
12858    case 0xD9:
12859    case 0xDA:
12860    case 0xDB:
12861    case 0xDC:
12862    case 0xDD:
12863    case 0xDE:
12864    case 0xDF: {
12865       Int  delta0    = delta;
12866       Bool decode_OK = False;
12867       delta = dis_FPU ( &decode_OK, sorb, delta );
12868       if (!decode_OK) {
12869          delta = delta0;
12870          goto decode_failure;
12871       }
12872       break;
12873    }
12874
12875    /* ------------------------ INC & DEC ------------------ */
12876
12877    case 0x40: /* INC eAX */
12878    case 0x41: /* INC eCX */
12879    case 0x42: /* INC eDX */
12880    case 0x43: /* INC eBX */
12881    case 0x44: /* INC eSP */
12882    case 0x45: /* INC eBP */
12883    case 0x46: /* INC eSI */
12884    case 0x47: /* INC eDI */
12885       vassert(sz == 2 || sz == 4);
12886       ty = szToITy(sz);
12887       t1 = newTemp(ty);
12888       assign( t1, binop(mkSizedOp(ty,Iop_Add8),
12889                         getIReg(sz, (UInt)(opc - 0x40)),
12890                         mkU(ty,1)) );
12891       setFlags_INC_DEC( True, t1, ty );
12892       putIReg(sz, (UInt)(opc - 0x40), mkexpr(t1));
12893       DIP("inc%c %s\n", nameISize(sz), nameIReg(sz,opc-0x40));
12894       break;
12895
12896    case 0x48: /* DEC eAX */
12897    case 0x49: /* DEC eCX */
12898    case 0x4A: /* DEC eDX */
12899    case 0x4B: /* DEC eBX */
12900    case 0x4C: /* DEC eSP */
12901    case 0x4D: /* DEC eBP */
12902    case 0x4E: /* DEC eSI */
12903    case 0x4F: /* DEC eDI */
12904       vassert(sz == 2 || sz == 4);
12905       ty = szToITy(sz);
12906       t1 = newTemp(ty);
12907       assign( t1, binop(mkSizedOp(ty,Iop_Sub8),
12908                         getIReg(sz, (UInt)(opc - 0x48)),
12909                         mkU(ty,1)) );
12910       setFlags_INC_DEC( False, t1, ty );
12911       putIReg(sz, (UInt)(opc - 0x48), mkexpr(t1));
12912       DIP("dec%c %s\n", nameISize(sz), nameIReg(sz,opc-0x48));
12913       break;
12914
12915    /* ------------------------ INT ------------------------ */
12916
12917    case 0xCC: /* INT 3 */
12918       jmp_lit(Ijk_SigTRAP,((Addr32)guest_EIP_bbstart)+delta);
12919       dres.whatNext = Dis_StopHere;
12920       DIP("int $0x3\n");
12921       break;
12922
12923    case 0xCD: /* INT imm8 */
12924       d32 = getIByte(delta); delta++;
12925
12926       /* For any of the cases where we emit a jump (that is, for all
12927          currently handled cases), it's important that all ArchRegs
12928          carry their up-to-date value at this point.  So we declare an
12929          end-of-block here, which forces any TempRegs caching ArchRegs
12930          to be flushed. */
12931
12932       /* Handle int $0x30 (l4re syscall) */
12933       if (d32 == 0x30) {
12934           jmp_lit(Ijk_Sys_int48,((Addr32)guest_EIP_bbstart)+delta);
12935          dres.whatNext = Dis_StopHere;
12936          DIP("int $0x30\n");
12937          break;
12938       }
12939
12940       /* Handle int $0x32 (l4re syscall) */
12941       if (d32 == 0x32) {
12942           jmp_lit(Ijk_Sys_int50,((Addr32)guest_EIP_bbstart)+delta);
12943          dres.whatNext = Dis_StopHere;
12944          DIP("int $0x32\n");
12945          break;
12946       }
12947
12948       /* Handle int $0x40 .. $0x43 by synthesising a segfault and a
12949          restart of this instruction (hence the "-2" two lines below,
12950          to get the restart EIP to be this instruction.  This is
12951          probably Linux-specific and it would be more correct to only
12952          do this if the VexAbiInfo says that is what we should do. */
12953       if (d32 >= 0x40 && d32 <= 0x43) {
12954          jmp_lit(Ijk_SigSEGV,((Addr32)guest_EIP_bbstart)+delta-2);
12955          dres.whatNext = Dis_StopHere;
12956          DIP("int $0x%x\n", (Int)d32);
12957          break;
12958       }
12959
12960       /* Handle int $0x80 (linux syscalls), int $0x81 and $0x82
12961          (darwin syscalls).  As part of this, note where we are, so we
12962          can back up the guest to this point if the syscall needs to
12963          be restarted. */
12964       if (d32 == 0x80) {
12965          stmt( IRStmt_Put( OFFB_IP_AT_SYSCALL,
12966                            mkU32(guest_EIP_curr_instr) ) );
12967          jmp_lit(Ijk_Sys_int128,((Addr32)guest_EIP_bbstart)+delta);
12968          dres.whatNext = Dis_StopHere;
12969          DIP("int $0x80\n");
12970          break;
12971       }
12972       if (d32 == 0x81) {
12973          stmt( IRStmt_Put( OFFB_IP_AT_SYSCALL,
12974                            mkU32(guest_EIP_curr_instr) ) );
12975          jmp_lit(Ijk_Sys_int129,((Addr32)guest_EIP_bbstart)+delta);
12976          dres.whatNext = Dis_StopHere;
12977          DIP("int $0x81\n");
12978          break;
12979       }
12980       if (d32 == 0x82) {
12981          stmt( IRStmt_Put( OFFB_IP_AT_SYSCALL,
12982                            mkU32(guest_EIP_curr_instr) ) );
12983          jmp_lit(Ijk_Sys_int130,((Addr32)guest_EIP_bbstart)+delta);
12984          dres.whatNext = Dis_StopHere;
12985          DIP("int $0x82\n");
12986          break;
12987       }
12988
12989       /* none of the above */
12990       goto decode_failure;
12991
12992    /* ------------------------ Jcond, byte offset --------- */
12993
12994    case 0xEB: /* Jb (jump, byte offset) */
12995       d32 = (((Addr32)guest_EIP_bbstart)+delta+1) + getSDisp8(delta); 
12996       delta++;
12997       if (resteerOkFn( callback_opaque, (Addr64)(Addr32)d32) ) {
12998          dres.whatNext   = Dis_ResteerU;
12999          dres.continueAt = (Addr64)(Addr32)d32;
13000       } else {
13001          jmp_lit(Ijk_Boring,d32);
13002          dres.whatNext = Dis_StopHere;
13003       }
13004       DIP("jmp-8 0x%x\n", d32);
13005       break;
13006
13007    case 0xE9: /* Jv (jump, 16/32 offset) */
13008       vassert(sz == 4); /* JRS added 2004 July 11 */
13009       d32 = (((Addr32)guest_EIP_bbstart)+delta+sz) + getSDisp(sz,delta); 
13010       delta += sz;
13011       if (resteerOkFn( callback_opaque, (Addr64)(Addr32)d32) ) {
13012          dres.whatNext   = Dis_ResteerU;
13013          dres.continueAt = (Addr64)(Addr32)d32;
13014       } else {
13015          jmp_lit(Ijk_Boring,d32);
13016          dres.whatNext = Dis_StopHere;
13017       }
13018       DIP("jmp 0x%x\n", d32);
13019       break;
13020
13021    case 0x70:
13022    case 0x71:
13023    case 0x72: /* JBb/JNAEb (jump below) */
13024    case 0x73: /* JNBb/JAEb (jump not below) */
13025    case 0x74: /* JZb/JEb (jump zero) */
13026    case 0x75: /* JNZb/JNEb (jump not zero) */
13027    case 0x76: /* JBEb/JNAb (jump below or equal) */
13028    case 0x77: /* JNBEb/JAb (jump not below or equal) */
13029    case 0x78: /* JSb (jump negative) */
13030    case 0x79: /* JSb (jump not negative) */
13031    case 0x7A: /* JP (jump parity even) */
13032    case 0x7B: /* JNP/JPO (jump parity odd) */
13033    case 0x7C: /* JLb/JNGEb (jump less) */
13034    case 0x7D: /* JGEb/JNLb (jump greater or equal) */
13035    case 0x7E: /* JLEb/JNGb (jump less or equal) */
13036    case 0x7F: /* JGb/JNLEb (jump greater) */
13037     { Int    jmpDelta;
13038       HChar* comment  = "";
13039       jmpDelta = (Int)getSDisp8(delta);
13040       vassert(-128 <= jmpDelta && jmpDelta < 128);
13041       d32 = (((Addr32)guest_EIP_bbstart)+delta+1) + jmpDelta; 
13042       delta++;
13043       if (resteerCisOk
13044           && vex_control.guest_chase_cond
13045           && (Addr32)d32 != (Addr32)guest_EIP_bbstart
13046           && jmpDelta < 0
13047           && resteerOkFn( callback_opaque, (Addr64)(Addr32)d32) ) {
13048          /* Speculation: assume this backward branch is taken.  So we
13049             need to emit a side-exit to the insn following this one,
13050             on the negation of the condition, and continue at the
13051             branch target address (d32).  If we wind up back at the
13052             first instruction of the trace, just stop; it's better to
13053             let the IR loop unroller handle that case. */
13054          stmt( IRStmt_Exit( 
13055                   mk_x86g_calculate_condition((X86Condcode)(1 ^ (opc - 0x70))),
13056                   Ijk_Boring,
13057                   IRConst_U32(guest_EIP_bbstart+delta) ) );
13058          dres.whatNext   = Dis_ResteerC;
13059          dres.continueAt = (Addr64)(Addr32)d32;
13060          comment = "(assumed taken)";
13061       }
13062       else
13063       if (resteerCisOk
13064           && vex_control.guest_chase_cond
13065           && (Addr32)d32 != (Addr32)guest_EIP_bbstart
13066           && jmpDelta >= 0
13067           && resteerOkFn( callback_opaque, 
13068                           (Addr64)(Addr32)(guest_EIP_bbstart+delta)) ) {
13069          /* Speculation: assume this forward branch is not taken.  So
13070             we need to emit a side-exit to d32 (the dest) and continue
13071             disassembling at the insn immediately following this
13072             one. */
13073          stmt( IRStmt_Exit( 
13074                   mk_x86g_calculate_condition((X86Condcode)(opc - 0x70)),
13075                   Ijk_Boring,
13076                   IRConst_U32(d32) ) );
13077          dres.whatNext   = Dis_ResteerC;
13078          dres.continueAt = (Addr64)(Addr32)(guest_EIP_bbstart+delta);
13079          comment = "(assumed not taken)";
13080       }
13081       else {
13082          /* Conservative default translation - end the block at this
13083             point. */
13084          jcc_01( (X86Condcode)(opc - 0x70), 
13085                  (Addr32)(guest_EIP_bbstart+delta), d32);
13086          dres.whatNext = Dis_StopHere;
13087       }
13088       DIP("j%s-8 0x%x %s\n", name_X86Condcode(opc - 0x70), d32, comment);
13089       break;
13090     }
13091
13092    case 0xE3: /* JECXZ (for JCXZ see above) */
13093       if (sz != 4) goto decode_failure;
13094       d32 = (((Addr32)guest_EIP_bbstart)+delta+1) + getSDisp8(delta);
13095       delta ++;
13096       stmt( IRStmt_Exit(
13097                binop(Iop_CmpEQ32, getIReg(4,R_ECX), mkU32(0)),
13098             Ijk_Boring,
13099             IRConst_U32(d32)
13100           ));
13101       DIP("jecxz 0x%x\n", d32);
13102       break;
13103
13104    case 0xE0: /* LOOPNE disp8: decrement count, jump if count != 0 && ZF==0 */
13105    case 0xE1: /* LOOPE  disp8: decrement count, jump if count != 0 && ZF==1 */
13106    case 0xE2: /* LOOP   disp8: decrement count, jump if count != 0 */
13107     { /* Again, the docs say this uses ECX/CX as a count depending on
13108          the address size override, not the operand one.  Since we
13109          don't handle address size overrides, I guess that means
13110          ECX. */
13111       IRExpr* zbit  = NULL;
13112       IRExpr* count = NULL;
13113       IRExpr* cond  = NULL;
13114       HChar*  xtra  = NULL;
13115
13116       if (sz != 4) goto decode_failure;
13117       d32 = (((Addr32)guest_EIP_bbstart)+delta+1) + getSDisp8(delta);
13118       delta++;
13119       putIReg(4, R_ECX, binop(Iop_Sub32, getIReg(4,R_ECX), mkU32(1)));
13120
13121       count = getIReg(4,R_ECX);
13122       cond = binop(Iop_CmpNE32, count, mkU32(0));
13123       switch (opc) {
13124          case 0xE2: 
13125             xtra = ""; 
13126             break;
13127          case 0xE1: 
13128             xtra = "e"; 
13129             zbit = mk_x86g_calculate_condition( X86CondZ );
13130             cond = mkAnd1(cond, zbit);
13131             break;
13132          case 0xE0: 
13133             xtra = "ne";
13134             zbit = mk_x86g_calculate_condition( X86CondNZ );
13135             cond = mkAnd1(cond, zbit);
13136             break;
13137          default:
13138             vassert(0);
13139       }
13140       stmt( IRStmt_Exit(cond, Ijk_Boring, IRConst_U32(d32)) );
13141
13142       DIP("loop%s 0x%x\n", xtra, d32);
13143       break;
13144     }
13145
13146    /* ------------------------ IMUL ----------------------- */
13147
13148    case 0x69: /* IMUL Iv, Ev, Gv */
13149       delta = dis_imul_I_E_G ( sorb, sz, delta, sz );
13150       break;
13151    case 0x6B: /* IMUL Ib, Ev, Gv */
13152       delta = dis_imul_I_E_G ( sorb, sz, delta, 1 );
13153       break;
13154
13155    /* ------------------------ MOV ------------------------ */
13156
13157    case 0x88: /* MOV Gb,Eb */
13158       delta = dis_mov_G_E(sorb, 1, delta);
13159       break;
13160
13161    case 0x89: /* MOV Gv,Ev */
13162       delta = dis_mov_G_E(sorb, sz, delta);
13163       break;
13164
13165    case 0x8A: /* MOV Eb,Gb */
13166       delta = dis_mov_E_G(sorb, 1, delta);
13167       break;
13168  
13169    case 0x8B: /* MOV Ev,Gv */
13170       delta = dis_mov_E_G(sorb, sz, delta);
13171       break;
13172  
13173    case 0x8D: /* LEA M,Gv */
13174       if (sz != 4)
13175          goto decode_failure;
13176       modrm = getIByte(delta);
13177       if (epartIsReg(modrm)) 
13178          goto decode_failure;
13179       /* NOTE!  this is the one place where a segment override prefix
13180          has no effect on the address calculation.  Therefore we pass
13181          zero instead of sorb here. */
13182       addr = disAMode ( &alen, /*sorb*/ 0, delta, dis_buf );
13183       delta += alen;
13184       putIReg(sz, gregOfRM(modrm), mkexpr(addr));
13185       DIP("lea%c %s, %s\n", nameISize(sz), dis_buf, 
13186                             nameIReg(sz,gregOfRM(modrm)));
13187       break;
13188
13189    case 0x8C: /* MOV Sw,Ew -- MOV from a SEGMENT REGISTER */
13190       delta = dis_mov_Sw_Ew(sorb, sz, delta);
13191       break;
13192
13193    case 0x8E: /* MOV Ew,Sw -- MOV to a SEGMENT REGISTER */
13194       delta = dis_mov_Ew_Sw(sorb, delta);
13195       break;
13196  
13197    case 0xA0: /* MOV Ob,AL */
13198       sz = 1;
13199       /* Fall through ... */
13200    case 0xA1: /* MOV Ov,eAX */
13201       d32 = getUDisp32(delta); delta += 4;
13202       ty = szToITy(sz);
13203       addr = newTemp(Ity_I32);
13204       assign( addr, handleSegOverride(sorb, mkU32(d32)) );
13205       putIReg(sz, R_EAX, loadLE(ty, mkexpr(addr)));
13206       DIP("mov%c %s0x%x, %s\n", nameISize(sz), sorbTxt(sorb),
13207                                 d32, nameIReg(sz,R_EAX));
13208       break;
13209
13210    case 0xA2: /* MOV Ob,AL */
13211       sz = 1;
13212       /* Fall through ... */
13213    case 0xA3: /* MOV eAX,Ov */
13214       d32 = getUDisp32(delta); delta += 4;
13215       ty = szToITy(sz);
13216       addr = newTemp(Ity_I32);
13217       assign( addr, handleSegOverride(sorb, mkU32(d32)) );
13218       storeLE( mkexpr(addr), getIReg(sz,R_EAX) );
13219       DIP("mov%c %s, %s0x%x\n", nameISize(sz), nameIReg(sz,R_EAX),
13220                                 sorbTxt(sorb), d32);
13221       break;
13222
13223    case 0xB0: /* MOV imm,AL */
13224    case 0xB1: /* MOV imm,CL */
13225    case 0xB2: /* MOV imm,DL */
13226    case 0xB3: /* MOV imm,BL */
13227    case 0xB4: /* MOV imm,AH */
13228    case 0xB5: /* MOV imm,CH */
13229    case 0xB6: /* MOV imm,DH */
13230    case 0xB7: /* MOV imm,BH */
13231       d32 = getIByte(delta); delta += 1;
13232       putIReg(1, opc-0xB0, mkU8(d32));
13233       DIP("movb $0x%x,%s\n", d32, nameIReg(1,opc-0xB0));
13234       break;
13235
13236    case 0xB8: /* MOV imm,eAX */
13237    case 0xB9: /* MOV imm,eCX */
13238    case 0xBA: /* MOV imm,eDX */
13239    case 0xBB: /* MOV imm,eBX */
13240    case 0xBC: /* MOV imm,eSP */
13241    case 0xBD: /* MOV imm,eBP */
13242    case 0xBE: /* MOV imm,eSI */
13243    case 0xBF: /* MOV imm,eDI */
13244       d32 = getUDisp(sz,delta); delta += sz;
13245       putIReg(sz, opc-0xB8, mkU(szToITy(sz), d32));
13246       DIP("mov%c $0x%x,%s\n", nameISize(sz), d32, nameIReg(sz,opc-0xB8));
13247       break;
13248
13249    case 0xC6: /* MOV Ib,Eb */
13250       sz = 1;
13251       goto do_Mov_I_E;
13252    case 0xC7: /* MOV Iv,Ev */
13253       goto do_Mov_I_E;
13254
13255    do_Mov_I_E:
13256       modrm = getIByte(delta);
13257       if (epartIsReg(modrm)) {
13258          delta++; /* mod/rm byte */
13259          d32 = getUDisp(sz,delta); delta += sz;
13260          putIReg(sz, eregOfRM(modrm), mkU(szToITy(sz), d32));
13261          DIP("mov%c $0x%x, %s\n", nameISize(sz), d32, 
13262                                   nameIReg(sz,eregOfRM(modrm)));
13263       } else {
13264          addr = disAMode ( &alen, sorb, delta, dis_buf );
13265          delta += alen;
13266          d32 = getUDisp(sz,delta); delta += sz;
13267          storeLE(mkexpr(addr), mkU(szToITy(sz), d32));
13268          DIP("mov%c $0x%x, %s\n", nameISize(sz), d32, dis_buf);
13269       }
13270       break;
13271
13272    /* ------------------------ opl imm, A ----------------- */
13273
13274    case 0x04: /* ADD Ib, AL */
13275       delta = dis_op_imm_A(  1, False, Iop_Add8, True, delta, "add" );
13276       break;
13277    case 0x05: /* ADD Iv, eAX */
13278       delta = dis_op_imm_A( sz, False, Iop_Add8, True, delta, "add" );
13279       break;
13280
13281    case 0x0C: /* OR Ib, AL */
13282       delta = dis_op_imm_A(  1, False, Iop_Or8, True, delta, "or" );
13283       break;
13284    case 0x0D: /* OR Iv, eAX */
13285       delta = dis_op_imm_A( sz, False, Iop_Or8, True, delta, "or" );
13286       break;
13287
13288    case 0x14: /* ADC Ib, AL */
13289       delta = dis_op_imm_A(  1, True, Iop_Add8, True, delta, "adc" );
13290       break;
13291    case 0x15: /* ADC Iv, eAX */
13292       delta = dis_op_imm_A( sz, True, Iop_Add8, True, delta, "adc" );
13293       break;
13294
13295    case 0x1C: /* SBB Ib, AL */
13296       delta = dis_op_imm_A( 1, True, Iop_Sub8, True, delta, "sbb" );
13297       break;
13298    case 0x1D: /* SBB Iv, eAX */
13299       delta = dis_op_imm_A( sz, True, Iop_Sub8, True, delta, "sbb" );
13300       break;
13301
13302    case 0x24: /* AND Ib, AL */
13303       delta = dis_op_imm_A(  1, False, Iop_And8, True, delta, "and" );
13304       break;
13305    case 0x25: /* AND Iv, eAX */
13306       delta = dis_op_imm_A( sz, False, Iop_And8, True, delta, "and" );
13307       break;
13308
13309    case 0x2C: /* SUB Ib, AL */
13310       delta = dis_op_imm_A(  1, False, Iop_Sub8, True, delta, "sub" );
13311       break;
13312    case 0x2D: /* SUB Iv, eAX */
13313       delta = dis_op_imm_A( sz, False, Iop_Sub8, True, delta, "sub" );
13314       break;
13315
13316    case 0x34: /* XOR Ib, AL */
13317       delta = dis_op_imm_A(  1, False, Iop_Xor8, True, delta, "xor" );
13318       break;
13319    case 0x35: /* XOR Iv, eAX */
13320       delta = dis_op_imm_A( sz, False, Iop_Xor8, True, delta, "xor" );
13321       break;
13322
13323    case 0x3C: /* CMP Ib, AL */
13324       delta = dis_op_imm_A(  1, False, Iop_Sub8, False, delta, "cmp" );
13325       break;
13326    case 0x3D: /* CMP Iv, eAX */
13327       delta = dis_op_imm_A( sz, False, Iop_Sub8, False, delta, "cmp" );
13328       break;
13329
13330    case 0xA8: /* TEST Ib, AL */
13331       delta = dis_op_imm_A(  1, False, Iop_And8, False, delta, "test" );
13332       break;
13333    case 0xA9: /* TEST Iv, eAX */
13334       delta = dis_op_imm_A( sz, False, Iop_And8, False, delta, "test" );
13335       break;
13336
13337    /* ------------------------ opl Ev, Gv ----------------- */
13338  
13339    case 0x02: /* ADD Eb,Gb */
13340       delta = dis_op2_E_G ( sorb, False, Iop_Add8, True, 1, delta, "add" );
13341       break;
13342    case 0x03: /* ADD Ev,Gv */
13343       delta = dis_op2_E_G ( sorb, False, Iop_Add8, True, sz, delta, "add" );
13344       break;
13345
13346    case 0x0A: /* OR Eb,Gb */
13347       delta = dis_op2_E_G ( sorb, False, Iop_Or8, True, 1, delta, "or" );
13348       break;
13349    case 0x0B: /* OR Ev,Gv */
13350       delta = dis_op2_E_G ( sorb, False, Iop_Or8, True, sz, delta, "or" );
13351       break;
13352
13353    case 0x12: /* ADC Eb,Gb */
13354       delta = dis_op2_E_G ( sorb, True, Iop_Add8, True, 1, delta, "adc" );
13355       break;
13356    case 0x13: /* ADC Ev,Gv */
13357       delta = dis_op2_E_G ( sorb, True, Iop_Add8, True, sz, delta, "adc" );
13358       break;
13359
13360    case 0x1A: /* SBB Eb,Gb */
13361       delta = dis_op2_E_G ( sorb, True, Iop_Sub8, True, 1, delta, "sbb" );
13362       break;
13363    case 0x1B: /* SBB Ev,Gv */
13364       delta = dis_op2_E_G ( sorb, True, Iop_Sub8, True, sz, delta, "sbb" );
13365       break;
13366
13367    case 0x22: /* AND Eb,Gb */
13368       delta = dis_op2_E_G ( sorb, False, Iop_And8, True, 1, delta, "and" );
13369       break;
13370    case 0x23: /* AND Ev,Gv */
13371       delta = dis_op2_E_G ( sorb, False, Iop_And8, True, sz, delta, "and" );
13372       break;
13373
13374    case 0x2A: /* SUB Eb,Gb */
13375       delta = dis_op2_E_G ( sorb, False, Iop_Sub8, True, 1, delta, "sub" );
13376       break;
13377    case 0x2B: /* SUB Ev,Gv */
13378       delta = dis_op2_E_G ( sorb, False, Iop_Sub8, True, sz, delta, "sub" );
13379       break;
13380
13381    case 0x32: /* XOR Eb,Gb */
13382       delta = dis_op2_E_G ( sorb, False, Iop_Xor8, True, 1, delta, "xor" );
13383       break;
13384    case 0x33: /* XOR Ev,Gv */
13385       delta = dis_op2_E_G ( sorb, False, Iop_Xor8, True, sz, delta, "xor" );
13386       break;
13387
13388    case 0x3A: /* CMP Eb,Gb */
13389       delta = dis_op2_E_G ( sorb, False, Iop_Sub8, False, 1, delta, "cmp" );
13390       break;
13391    case 0x3B: /* CMP Ev,Gv */
13392       delta = dis_op2_E_G ( sorb, False, Iop_Sub8, False, sz, delta, "cmp" );
13393       break;
13394
13395    case 0x84: /* TEST Eb,Gb */
13396       delta = dis_op2_E_G ( sorb, False, Iop_And8, False, 1, delta, "test" );
13397       break;
13398    case 0x85: /* TEST Ev,Gv */
13399       delta = dis_op2_E_G ( sorb, False, Iop_And8, False, sz, delta, "test" );
13400       break;
13401
13402    /* ------------------------ opl Gv, Ev ----------------- */
13403
13404    case 0x00: /* ADD Gb,Eb */
13405       delta = dis_op2_G_E ( sorb, pfx_lock, False,
13406                             Iop_Add8, True, 1, delta, "add" );
13407       break;
13408    case 0x01: /* ADD Gv,Ev */
13409       delta = dis_op2_G_E ( sorb, pfx_lock, False,
13410                             Iop_Add8, True, sz, delta, "add" );
13411       break;
13412
13413    case 0x08: /* OR Gb,Eb */
13414       delta = dis_op2_G_E ( sorb, pfx_lock, False,
13415                             Iop_Or8, True, 1, delta, "or" );
13416       break;
13417    case 0x09: /* OR Gv,Ev */
13418       delta = dis_op2_G_E ( sorb, pfx_lock, False,
13419                             Iop_Or8, True, sz, delta, "or" );
13420       break;
13421
13422    case 0x10: /* ADC Gb,Eb */
13423       delta = dis_op2_G_E ( sorb, pfx_lock, True,
13424                             Iop_Add8, True, 1, delta, "adc" );
13425       break;
13426    case 0x11: /* ADC Gv,Ev */
13427       delta = dis_op2_G_E ( sorb, pfx_lock, True,
13428                             Iop_Add8, True, sz, delta, "adc" );
13429       break;
13430
13431    case 0x18: /* SBB Gb,Eb */
13432       delta = dis_op2_G_E ( sorb, pfx_lock, True,
13433                             Iop_Sub8, True, 1, delta, "sbb" );
13434       break;
13435    case 0x19: /* SBB Gv,Ev */
13436       delta = dis_op2_G_E ( sorb, pfx_lock, True,
13437                             Iop_Sub8, True, sz, delta, "sbb" );
13438       break;
13439
13440    case 0x20: /* AND Gb,Eb */
13441       delta = dis_op2_G_E ( sorb, pfx_lock, False,
13442                             Iop_And8, True, 1, delta, "and" );
13443       break;
13444    case 0x21: /* AND Gv,Ev */
13445       delta = dis_op2_G_E ( sorb, pfx_lock, False,
13446                             Iop_And8, True, sz, delta, "and" );
13447       break;
13448
13449    case 0x28: /* SUB Gb,Eb */
13450       delta = dis_op2_G_E ( sorb, pfx_lock, False,
13451                             Iop_Sub8, True, 1, delta, "sub" );
13452       break;
13453    case 0x29: /* SUB Gv,Ev */
13454       delta = dis_op2_G_E ( sorb, pfx_lock, False,
13455                             Iop_Sub8, True, sz, delta, "sub" );
13456       break;
13457
13458    case 0x30: /* XOR Gb,Eb */
13459       delta = dis_op2_G_E ( sorb, pfx_lock, False,
13460                             Iop_Xor8, True, 1, delta, "xor" );
13461       break;
13462    case 0x31: /* XOR Gv,Ev */
13463       delta = dis_op2_G_E ( sorb, pfx_lock, False,
13464                             Iop_Xor8, True, sz, delta, "xor" );
13465       break;
13466
13467    case 0x38: /* CMP Gb,Eb */
13468       delta = dis_op2_G_E ( sorb, pfx_lock, False,
13469                             Iop_Sub8, False, 1, delta, "cmp" );
13470       break;
13471    case 0x39: /* CMP Gv,Ev */
13472       delta = dis_op2_G_E ( sorb, pfx_lock, False,
13473                             Iop_Sub8, False, sz, delta, "cmp" );
13474       break;
13475
13476    /* ------------------------ POP ------------------------ */
13477
13478    case 0x58: /* POP eAX */
13479    case 0x59: /* POP eCX */
13480    case 0x5A: /* POP eDX */
13481    case 0x5B: /* POP eBX */
13482    case 0x5D: /* POP eBP */
13483    case 0x5E: /* POP eSI */
13484    case 0x5F: /* POP eDI */
13485    case 0x5C: /* POP eSP */
13486       vassert(sz == 2 || sz == 4);
13487       t1 = newTemp(szToITy(sz)); t2 = newTemp(Ity_I32);
13488       assign(t2, getIReg(4, R_ESP));
13489       assign(t1, loadLE(szToITy(sz),mkexpr(t2)));
13490       putIReg(4, R_ESP, binop(Iop_Add32, mkexpr(t2), mkU32(sz)));
13491       putIReg(sz, opc-0x58, mkexpr(t1));
13492       DIP("pop%c %s\n", nameISize(sz), nameIReg(sz,opc-0x58));
13493       break;
13494
13495    case 0x9D: /* POPF */
13496       vassert(sz == 2 || sz == 4);
13497       t1 = newTemp(Ity_I32); t2 = newTemp(Ity_I32);
13498       assign(t2, getIReg(4, R_ESP));
13499       assign(t1, widenUto32(loadLE(szToITy(sz),mkexpr(t2))));
13500       putIReg(4, R_ESP, binop(Iop_Add32, mkexpr(t2), mkU32(sz)));
13501
13502       /* Generate IR to set %EFLAGS{O,S,Z,A,C,P,D,ID,AC} from the
13503          value in t1. */
13504       set_EFLAGS_from_value( t1, True/*emit_AC_emwarn*/,
13505                                  ((Addr32)guest_EIP_bbstart)+delta );
13506
13507       DIP("popf%c\n", nameISize(sz));
13508       break;
13509
13510    case 0x61: /* POPA */
13511       /* This is almost certainly wrong for sz==2.  So ... */
13512       if (sz != 4) goto decode_failure;
13513
13514       /* t5 is the old %ESP value. */
13515       t5 = newTemp(Ity_I32);
13516       assign( t5, getIReg(4, R_ESP) );
13517
13518       /* Reload all the registers, except %esp. */
13519       putIReg(4,R_EAX, loadLE(Ity_I32, binop(Iop_Add32,mkexpr(t5),mkU32(28)) ));
13520       putIReg(4,R_ECX, loadLE(Ity_I32, binop(Iop_Add32,mkexpr(t5),mkU32(24)) ));
13521       putIReg(4,R_EDX, loadLE(Ity_I32, binop(Iop_Add32,mkexpr(t5),mkU32(20)) ));
13522       putIReg(4,R_EBX, loadLE(Ity_I32, binop(Iop_Add32,mkexpr(t5),mkU32(16)) ));
13523       /* ignore saved %ESP */
13524       putIReg(4,R_EBP, loadLE(Ity_I32, binop(Iop_Add32,mkexpr(t5),mkU32( 8)) ));
13525       putIReg(4,R_ESI, loadLE(Ity_I32, binop(Iop_Add32,mkexpr(t5),mkU32( 4)) ));
13526       putIReg(4,R_EDI, loadLE(Ity_I32, binop(Iop_Add32,mkexpr(t5),mkU32( 0)) ));
13527
13528       /* and move %ESP back up */
13529       putIReg( 4, R_ESP, binop(Iop_Add32, mkexpr(t5), mkU32(8*4)) );
13530
13531       DIP("popa%c\n", nameISize(sz));
13532       break;
13533
13534    case 0x8F: /* POPL/POPW m32 */
13535      { Int    len;
13536        UChar  rm = getIByte(delta);
13537
13538        /* make sure this instruction is correct POP */
13539        if (epartIsReg(rm) || gregOfRM(rm) != 0)
13540           goto decode_failure;
13541        /* and has correct size */
13542        if (sz != 4 && sz != 2)
13543           goto decode_failure;
13544        ty = szToITy(sz);
13545
13546        t1 = newTemp(Ity_I32); /* stack address */
13547        t3 = newTemp(ty); /* data */
13548        /* set t1 to ESP: t1 = ESP */
13549        assign( t1, getIReg(4, R_ESP) );
13550        /* load M[ESP] to virtual register t3: t3 = M[t1] */
13551        assign( t3, loadLE(ty, mkexpr(t1)) );
13552        
13553        /* increase ESP; must be done before the STORE.  Intel manual says:
13554             If the ESP register is used as a base register for addressing
13555             a destination operand in memory, the POP instruction computes
13556             the effective address of the operand after it increments the
13557             ESP register.
13558        */
13559        putIReg(4, R_ESP, binop(Iop_Add32, mkexpr(t1), mkU32(sz)) );
13560
13561        /* resolve MODR/M */
13562        addr = disAMode ( &len, sorb, delta, dis_buf);
13563        storeLE( mkexpr(addr), mkexpr(t3) );
13564
13565        DIP("pop%c %s\n", sz==2 ? 'w' : 'l', dis_buf);
13566
13567        delta += len;
13568        break;
13569      }
13570
13571    case 0x1F: /* POP %DS */
13572       dis_pop_segreg( R_DS, sz ); break;
13573    case 0x07: /* POP %ES */
13574       dis_pop_segreg( R_ES, sz ); break;
13575    case 0x17: /* POP %SS */
13576       dis_pop_segreg( R_SS, sz ); break;
13577
13578    /* ------------------------ PUSH ----------------------- */
13579
13580    case 0x50: /* PUSH eAX */
13581    case 0x51: /* PUSH eCX */
13582    case 0x52: /* PUSH eDX */
13583    case 0x53: /* PUSH eBX */
13584    case 0x55: /* PUSH eBP */
13585    case 0x56: /* PUSH eSI */
13586    case 0x57: /* PUSH eDI */
13587    case 0x54: /* PUSH eSP */
13588       /* This is the Right Way, in that the value to be pushed is
13589          established before %esp is changed, so that pushl %esp
13590          correctly pushes the old value. */
13591       vassert(sz == 2 || sz == 4);
13592       ty = sz==2 ? Ity_I16 : Ity_I32;
13593       t1 = newTemp(ty); t2 = newTemp(Ity_I32);
13594       assign(t1, getIReg(sz, opc-0x50));
13595       assign(t2, binop(Iop_Sub32, getIReg(4, R_ESP), mkU32(sz)));
13596       putIReg(4, R_ESP, mkexpr(t2) );
13597       storeLE(mkexpr(t2),mkexpr(t1));
13598       DIP("push%c %s\n", nameISize(sz), nameIReg(sz,opc-0x50));
13599       break;
13600
13601
13602    case 0x68: /* PUSH Iv */
13603       d32 = getUDisp(sz,delta); delta += sz;
13604       goto do_push_I;
13605    case 0x6A: /* PUSH Ib, sign-extended to sz */
13606       d32 = getSDisp8(delta); delta += 1;
13607       goto do_push_I;
13608    do_push_I:
13609       ty = szToITy(sz);
13610       t1 = newTemp(Ity_I32); t2 = newTemp(ty);
13611       assign( t1, binop(Iop_Sub32,getIReg(4,R_ESP),mkU32(sz)) );
13612       putIReg(4, R_ESP, mkexpr(t1) );
13613       /* stop mkU16 asserting if d32 is a negative 16-bit number
13614          (bug #132813) */
13615       if (ty == Ity_I16)
13616          d32 &= 0xFFFF;
13617       storeLE( mkexpr(t1), mkU(ty,d32) );
13618       DIP("push%c $0x%x\n", nameISize(sz), d32);
13619       break;
13620
13621    case 0x9C: /* PUSHF */ {
13622       vassert(sz == 2 || sz == 4);
13623
13624       t1 = newTemp(Ity_I32);
13625       assign( t1, binop(Iop_Sub32,getIReg(4,R_ESP),mkU32(sz)) );
13626       putIReg(4, R_ESP, mkexpr(t1) );
13627
13628       /* Calculate OSZACP, and patch in fixed fields as per
13629          Intel docs. 
13630          - bit 1 is always 1
13631          - bit 9 is Interrupt Enable (should always be 1 in user mode?)
13632       */
13633       t2 = newTemp(Ity_I32);
13634       assign( t2, binop(Iop_Or32, 
13635                         mk_x86g_calculate_eflags_all(), 
13636                         mkU32( (1<<1)|(1<<9) ) ));
13637
13638       /* Patch in the D flag.  This can simply be a copy of bit 10 of
13639          baseBlock[OFFB_DFLAG]. */
13640       t3 = newTemp(Ity_I32);
13641       assign( t3, binop(Iop_Or32,
13642                         mkexpr(t2),
13643                         binop(Iop_And32,
13644                               IRExpr_Get(OFFB_DFLAG,Ity_I32),
13645                               mkU32(1<<10))) 
13646             );
13647
13648       /* And patch in the ID flag. */
13649       t4 = newTemp(Ity_I32);
13650       assign( t4, binop(Iop_Or32,
13651                         mkexpr(t3),
13652                         binop(Iop_And32,
13653                               binop(Iop_Shl32, IRExpr_Get(OFFB_IDFLAG,Ity_I32), 
13654                                                mkU8(21)),
13655                               mkU32(1<<21)))
13656             );
13657
13658       /* And patch in the AC flag. */
13659       t5 = newTemp(Ity_I32);
13660       assign( t5, binop(Iop_Or32,
13661                         mkexpr(t4),
13662                         binop(Iop_And32,
13663                               binop(Iop_Shl32, IRExpr_Get(OFFB_ACFLAG,Ity_I32), 
13664                                                mkU8(18)),
13665                               mkU32(1<<18)))
13666             );
13667
13668       /* if sz==2, the stored value needs to be narrowed. */
13669       if (sz == 2)
13670         storeLE( mkexpr(t1), unop(Iop_32to16,mkexpr(t5)) );
13671       else 
13672         storeLE( mkexpr(t1), mkexpr(t5) );
13673
13674       DIP("pushf%c\n", nameISize(sz));
13675       break;
13676    }
13677
13678    case 0x60: /* PUSHA */
13679       /* This is almost certainly wrong for sz==2.  So ... */
13680       if (sz != 4) goto decode_failure;
13681
13682       /* This is the Right Way, in that the value to be pushed is
13683          established before %esp is changed, so that pusha
13684          correctly pushes the old %esp value.  New value of %esp is
13685          pushed at start. */
13686       /* t0 is the %ESP value we're going to push. */
13687       t0 = newTemp(Ity_I32);
13688       assign( t0, getIReg(4, R_ESP) );
13689
13690       /* t5 will be the new %ESP value. */
13691       t5 = newTemp(Ity_I32);
13692       assign( t5, binop(Iop_Sub32, mkexpr(t0), mkU32(8*4)) );
13693
13694       /* Update guest state before prodding memory. */
13695       putIReg(4, R_ESP, mkexpr(t5));
13696
13697       /* Dump all the registers. */
13698       storeLE( binop(Iop_Add32,mkexpr(t5),mkU32(28)), getIReg(4,R_EAX) );
13699       storeLE( binop(Iop_Add32,mkexpr(t5),mkU32(24)), getIReg(4,R_ECX) );
13700       storeLE( binop(Iop_Add32,mkexpr(t5),mkU32(20)), getIReg(4,R_EDX) );
13701       storeLE( binop(Iop_Add32,mkexpr(t5),mkU32(16)), getIReg(4,R_EBX) );
13702       storeLE( binop(Iop_Add32,mkexpr(t5),mkU32(12)), mkexpr(t0) /*esp*/);
13703       storeLE( binop(Iop_Add32,mkexpr(t5),mkU32( 8)), getIReg(4,R_EBP) );
13704       storeLE( binop(Iop_Add32,mkexpr(t5),mkU32( 4)), getIReg(4,R_ESI) );
13705       storeLE( binop(Iop_Add32,mkexpr(t5),mkU32( 0)), getIReg(4,R_EDI) );
13706
13707       DIP("pusha%c\n", nameISize(sz));
13708       break;
13709
13710    case 0x0E: /* PUSH %CS */
13711       dis_push_segreg( R_CS, sz ); break;
13712    case 0x1E: /* PUSH %DS */
13713       dis_push_segreg( R_DS, sz ); break;
13714    case 0x06: /* PUSH %ES */
13715       dis_push_segreg( R_ES, sz ); break;
13716    case 0x16: /* PUSH %SS */
13717       dis_push_segreg( R_SS, sz ); break;
13718
13719    /* ------------------------ SCAS et al ----------------- */
13720
13721    case 0xA4: /* MOVS, no REP prefix */
13722    case 0xA5: 
13723       if (sorb != 0)
13724          goto decode_failure; /* else dis_string_op asserts */
13725       dis_string_op( dis_MOVS, ( opc == 0xA4 ? 1 : sz ), "movs", sorb );
13726       break;
13727
13728   case 0xA6: /* CMPSb, no REP prefix */
13729   case 0xA7:
13730       if (sorb != 0)
13731          goto decode_failure; /* else dis_string_op asserts */
13732       dis_string_op( dis_CMPS, ( opc == 0xA6 ? 1 : sz ), "cmps", sorb );
13733       break;
13734
13735    case 0xAA: /* STOS, no REP prefix */
13736    case 0xAB:
13737       if (sorb != 0)
13738          goto decode_failure; /* else dis_string_op asserts */
13739       dis_string_op( dis_STOS, ( opc == 0xAA ? 1 : sz ), "stos", sorb );
13740       break;
13741
13742    case 0xAC: /* LODS, no REP prefix */
13743    case 0xAD:
13744       if (sorb != 0)
13745          goto decode_failure; /* else dis_string_op asserts */
13746       dis_string_op( dis_LODS, ( opc == 0xAC ? 1 : sz ), "lods", sorb );
13747       break;
13748
13749    case 0xAE: /* SCAS, no REP prefix */
13750    case 0xAF:
13751       if (sorb != 0) 
13752          goto decode_failure; /* else dis_string_op asserts */
13753       dis_string_op( dis_SCAS, ( opc == 0xAE ? 1 : sz ), "scas", sorb );
13754       break;
13755
13756
13757    case 0xFC: /* CLD */
13758       stmt( IRStmt_Put( OFFB_DFLAG, mkU32(1)) );
13759       DIP("cld\n");
13760       break;
13761
13762    case 0xFD: /* STD */
13763       stmt( IRStmt_Put( OFFB_DFLAG, mkU32(0xFFFFFFFF)) );
13764       DIP("std\n");
13765       break;
13766
13767    case 0xF8: /* CLC */
13768    case 0xF9: /* STC */
13769    case 0xF5: /* CMC */
13770       t0 = newTemp(Ity_I32);
13771       t1 = newTemp(Ity_I32);
13772       assign( t0, mk_x86g_calculate_eflags_all() );
13773       switch (opc) {
13774          case 0xF8: 
13775             assign( t1, binop(Iop_And32, mkexpr(t0), 
13776                                          mkU32(~X86G_CC_MASK_C)));
13777             DIP("clc\n");
13778             break;
13779          case 0xF9: 
13780             assign( t1, binop(Iop_Or32, mkexpr(t0), 
13781                                         mkU32(X86G_CC_MASK_C)));
13782             DIP("stc\n");
13783             break;
13784          case 0xF5: 
13785             assign( t1, binop(Iop_Xor32, mkexpr(t0), 
13786                                          mkU32(X86G_CC_MASK_C)));
13787             DIP("cmc\n");
13788             break;
13789          default: 
13790             vpanic("disInstr(x86)(clc/stc/cmc)");
13791       }
13792       stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(X86G_CC_OP_COPY) ));
13793       stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0) ));
13794       stmt( IRStmt_Put( OFFB_CC_DEP1, mkexpr(t1) ));
13795       /* Set NDEP even though it isn't used.  This makes redundant-PUT
13796          elimination of previous stores to this field work better. */
13797       stmt( IRStmt_Put( OFFB_CC_NDEP, mkU32(0) ));
13798       break;
13799
13800    case 0xD6: /* SALC */
13801       t0 = newTemp(Ity_I32);
13802       t1 = newTemp(Ity_I32);
13803       assign( t0,  binop(Iop_And32,
13804                          mk_x86g_calculate_eflags_c(),
13805                          mkU32(1)) );
13806       assign( t1, binop(Iop_Sar32, 
13807                         binop(Iop_Shl32, mkexpr(t0), mkU8(31)), 
13808                         mkU8(31)) );
13809       putIReg(1, R_EAX, unop(Iop_32to8, mkexpr(t1)) );
13810       DIP("salc\n");
13811       break;
13812
13813    /* REPNE prefix insn */
13814    case 0xF2: { 
13815       Addr32 eip_orig = guest_EIP_bbstart + delta_start;
13816       if (sorb != 0) goto decode_failure;
13817       abyte = getIByte(delta); delta++;
13818
13819       if (abyte == 0x66) { sz = 2; abyte = getIByte(delta); delta++; }
13820       dres.whatNext = Dis_StopHere;         
13821
13822       switch (abyte) {
13823       /* According to the Intel manual, "repne movs" should never occur, but
13824        * in practice it has happened, so allow for it here... */
13825       case 0xA4: sz = 1;   /* REPNE MOVS<sz> */
13826       case 0xA5: 
13827          dis_REP_op ( X86CondNZ, dis_MOVS, sz, eip_orig,
13828                                  guest_EIP_bbstart+delta, "repne movs" );
13829          break;
13830
13831       case 0xA6: sz = 1;   /* REPNE CMP<sz> */
13832       case 0xA7:
13833          dis_REP_op ( X86CondNZ, dis_CMPS, sz, eip_orig, 
13834                                  guest_EIP_bbstart+delta, "repne cmps" );
13835          break;
13836
13837       case 0xAA: sz = 1;   /* REPNE STOS<sz> */
13838       case 0xAB:
13839          dis_REP_op ( X86CondNZ, dis_STOS, sz, eip_orig, 
13840                                  guest_EIP_bbstart+delta, "repne stos" );
13841          break;
13842
13843       case 0xAE: sz = 1;   /* REPNE SCAS<sz> */
13844       case 0xAF:
13845          dis_REP_op ( X86CondNZ, dis_SCAS, sz, eip_orig,
13846                                  guest_EIP_bbstart+delta, "repne scas" );
13847          break;
13848
13849       default:
13850          goto decode_failure;
13851       }
13852       break;
13853    }
13854
13855    /* REP/REPE prefix insn (for SCAS and CMPS, 0xF3 means REPE,
13856       for the rest, it means REP) */
13857    case 0xF3: { 
13858       Addr32 eip_orig = guest_EIP_bbstart + delta_start;
13859       if (sorb != 0) goto decode_failure;
13860       abyte = getIByte(delta); delta++;
13861
13862       if (abyte == 0x66) { sz = 2; abyte = getIByte(delta); delta++; }
13863       dres.whatNext = Dis_StopHere;
13864
13865       switch (abyte) {
13866       case 0xA4: sz = 1;   /* REP MOVS<sz> */
13867       case 0xA5:
13868          dis_REP_op ( X86CondAlways, dis_MOVS, sz, eip_orig, 
13869                                      guest_EIP_bbstart+delta, "rep movs" );
13870          break;
13871
13872       case 0xA6: sz = 1;   /* REPE CMP<sz> */
13873       case 0xA7:
13874          dis_REP_op ( X86CondZ, dis_CMPS, sz, eip_orig, 
13875                                 guest_EIP_bbstart+delta, "repe cmps" );
13876          break;
13877
13878       case 0xAA: sz = 1;   /* REP STOS<sz> */
13879       case 0xAB:
13880          dis_REP_op ( X86CondAlways, dis_STOS, sz, eip_orig, 
13881                                      guest_EIP_bbstart+delta, "rep stos" );
13882          break;
13883
13884       case 0xAC: sz = 1;   /* REP LODS<sz> */
13885       case 0xAD:
13886          dis_REP_op ( X86CondAlways, dis_LODS, sz, eip_orig, 
13887                                      guest_EIP_bbstart+delta, "rep lods" );
13888          break;
13889
13890       case 0xAE: sz = 1;   /* REPE SCAS<sz> */
13891       case 0xAF: 
13892          dis_REP_op ( X86CondZ, dis_SCAS, sz, eip_orig, 
13893                                 guest_EIP_bbstart+delta, "repe scas" );
13894          break;
13895       
13896       case 0x90:           /* REP NOP (PAUSE) */
13897          /* a hint to the P4 re spin-wait loop */
13898          DIP("rep nop (P4 pause)\n");
13899          /* "observe" the hint.  The Vex client needs to be careful not
13900             to cause very long delays as a result, though. */
13901          jmp_lit(Ijk_Yield, ((Addr32)guest_EIP_bbstart)+delta);
13902          dres.whatNext = Dis_StopHere;
13903          break;
13904
13905       case 0xC3:           /* REP RET -- same as normal ret? */
13906          dis_ret(0);
13907          dres.whatNext = Dis_StopHere;
13908          DIP("rep ret\n");
13909          break;
13910
13911       default:
13912          goto decode_failure;
13913       }
13914       break;
13915    }
13916
13917    /* ------------------------ XCHG ----------------------- */
13918
13919    /* XCHG reg,mem automatically asserts LOCK# even without a LOCK
13920       prefix; hence it must be translated with an IRCAS (at least, the
13921       memory variant). */
13922    case 0x86: /* XCHG Gb,Eb */
13923       sz = 1;
13924       /* Fall through ... */
13925    case 0x87: /* XCHG Gv,Ev */
13926       modrm = getIByte(delta);
13927       ty = szToITy(sz);
13928       t1 = newTemp(ty); t2 = newTemp(ty);
13929       if (epartIsReg(modrm)) {
13930          assign(t1, getIReg(sz, eregOfRM(modrm)));
13931          assign(t2, getIReg(sz, gregOfRM(modrm)));
13932          putIReg(sz, gregOfRM(modrm), mkexpr(t1));
13933          putIReg(sz, eregOfRM(modrm), mkexpr(t2));
13934          delta++;
13935          DIP("xchg%c %s, %s\n", 
13936              nameISize(sz), nameIReg(sz,gregOfRM(modrm)), 
13937                             nameIReg(sz,eregOfRM(modrm)));
13938       } else {
13939          *expect_CAS = True;
13940          addr = disAMode ( &alen, sorb, delta, dis_buf );
13941          assign( t1, loadLE(ty,mkexpr(addr)) );
13942          assign( t2, getIReg(sz,gregOfRM(modrm)) );
13943          casLE( mkexpr(addr),
13944                 mkexpr(t1), mkexpr(t2), guest_EIP_curr_instr );
13945          putIReg( sz, gregOfRM(modrm), mkexpr(t1) );
13946          delta += alen;
13947          DIP("xchg%c %s, %s\n", nameISize(sz), 
13948                                 nameIReg(sz,gregOfRM(modrm)), dis_buf);
13949       }
13950       break;
13951
13952    case 0x90: /* XCHG eAX,eAX */
13953       DIP("nop\n");
13954       break;
13955    case 0x91: /* XCHG eAX,eCX */
13956    case 0x92: /* XCHG eAX,eDX */
13957    case 0x93: /* XCHG eAX,eBX */
13958    case 0x94: /* XCHG eAX,eSP */
13959    case 0x95: /* XCHG eAX,eBP */
13960    case 0x96: /* XCHG eAX,eSI */
13961    case 0x97: /* XCHG eAX,eDI */
13962       codegen_xchg_eAX_Reg ( sz, opc - 0x90 );
13963       break;
13964
13965    /* ------------------------ XLAT ----------------------- */
13966
13967    case 0xD7: /* XLAT */
13968       if (sz != 4) goto decode_failure; /* sz == 2 is also allowed (0x66) */
13969       putIReg( 
13970          1, 
13971          R_EAX/*AL*/,
13972          loadLE(Ity_I8, 
13973                 handleSegOverride( 
13974                    sorb, 
13975                    binop(Iop_Add32, 
13976                          getIReg(4, R_EBX), 
13977                          unop(Iop_8Uto32, getIReg(1, R_EAX/*AL*/))))));
13978
13979       DIP("xlat%c [ebx]\n", nameISize(sz));
13980       break;
13981
13982    /* ------------------------ IN / OUT ----------------------- */
13983
13984    case 0xE4: /* IN imm8, AL */
13985       sz = 1; 
13986       t1 = newTemp(Ity_I32);
13987       abyte = getIByte(delta); delta++;
13988       assign(t1, mkU32( abyte & 0xFF ));
13989       DIP("in%c $%d,%s\n", nameISize(sz), (Int)abyte, nameIReg(sz,R_EAX));
13990       goto do_IN;
13991    case 0xE5: /* IN imm8, eAX */
13992       vassert(sz == 2 || sz == 4);
13993       t1 = newTemp(Ity_I32);
13994       abyte = getIByte(delta); delta++;
13995       assign(t1, mkU32( abyte & 0xFF ));
13996       DIP("in%c $%d,%s\n", nameISize(sz), (Int)abyte, nameIReg(sz,R_EAX));
13997       goto do_IN;
13998    case 0xEC: /* IN %DX, AL */
13999       sz = 1; 
14000       t1 = newTemp(Ity_I32);
14001       assign(t1, unop(Iop_16Uto32, getIReg(2, R_EDX)));
14002       DIP("in%c %s,%s\n", nameISize(sz), nameIReg(2,R_EDX), 
14003                                          nameIReg(sz,R_EAX));
14004       goto do_IN;
14005    case 0xED: /* IN %DX, eAX */
14006       vassert(sz == 2 || sz == 4);
14007       t1 = newTemp(Ity_I32);
14008       assign(t1, unop(Iop_16Uto32, getIReg(2, R_EDX)));
14009       DIP("in%c %s,%s\n", nameISize(sz), nameIReg(2,R_EDX), 
14010                                          nameIReg(sz,R_EAX));
14011       goto do_IN;
14012    do_IN: {
14013       /* At this point, sz indicates the width, and t1 is a 32-bit
14014          value giving port number. */
14015       IRDirty* d;
14016       vassert(sz == 1 || sz == 2 || sz == 4);
14017       ty = szToITy(sz);
14018       t2 = newTemp(Ity_I32);
14019       d = unsafeIRDirty_1_N( 
14020              t2,
14021              0/*regparms*/, 
14022              "x86g_dirtyhelper_IN", 
14023              &x86g_dirtyhelper_IN,
14024              mkIRExprVec_2( mkexpr(t1), mkU32(sz) )
14025           );
14026       /* do the call, dumping the result in t2. */
14027       stmt( IRStmt_Dirty(d) );
14028       putIReg(sz, R_EAX, narrowTo( ty, mkexpr(t2) ) );
14029       break;
14030    }
14031
14032    case 0xE6: /* OUT AL, imm8 */
14033       sz = 1;
14034       t1 = newTemp(Ity_I32);
14035       abyte = getIByte(delta); delta++;
14036       assign( t1, mkU32( abyte & 0xFF ) );
14037       DIP("out%c %s,$%d\n", nameISize(sz), nameIReg(sz,R_EAX), (Int)abyte);
14038       goto do_OUT;
14039    case 0xE7: /* OUT eAX, imm8 */
14040       vassert(sz == 2 || sz == 4);
14041       t1 = newTemp(Ity_I32);
14042       abyte = getIByte(delta); delta++;
14043       assign( t1, mkU32( abyte & 0xFF ) );
14044       DIP("out%c %s,$%d\n", nameISize(sz), nameIReg(sz,R_EAX), (Int)abyte);
14045       goto do_OUT;
14046    case 0xEE: /* OUT AL, %DX */
14047       sz = 1;
14048       t1 = newTemp(Ity_I32);
14049       assign( t1, unop(Iop_16Uto32, getIReg(2, R_EDX)) );
14050       DIP("out%c %s,%s\n", nameISize(sz), nameIReg(sz,R_EAX),
14051                                           nameIReg(2,R_EDX));
14052       goto do_OUT;
14053    case 0xEF: /* OUT eAX, %DX */
14054       vassert(sz == 2 || sz == 4);
14055       t1 = newTemp(Ity_I32);
14056       assign( t1, unop(Iop_16Uto32, getIReg(2, R_EDX)) );
14057       DIP("out%c %s,%s\n", nameISize(sz), nameIReg(sz,R_EAX),
14058                                           nameIReg(2,R_EDX));
14059       goto do_OUT;
14060    do_OUT: {
14061       /* At this point, sz indicates the width, and t1 is a 32-bit
14062          value giving port number. */
14063       IRDirty* d;
14064       vassert(sz == 1 || sz == 2 || sz == 4);
14065       ty = szToITy(sz);
14066       d = unsafeIRDirty_0_N( 
14067              0/*regparms*/, 
14068              "x86g_dirtyhelper_OUT", 
14069              &x86g_dirtyhelper_OUT,
14070              mkIRExprVec_3( mkexpr(t1),
14071                             widenUto32( getIReg(sz, R_EAX) ), 
14072                             mkU32(sz) )
14073           );
14074       stmt( IRStmt_Dirty(d) );
14075       break;
14076    }
14077
14078    /* ------------------------ (Grp1 extensions) ---------- */
14079
14080    case 0x82: /* Grp1 Ib,Eb too.  Apparently this is the same as 
14081                  case 0x80, but only in 32-bit mode. */
14082       /* fallthru */
14083    case 0x80: /* Grp1 Ib,Eb */
14084       modrm = getIByte(delta);
14085       am_sz = lengthAMode(delta);
14086       sz    = 1;
14087       d_sz  = 1;
14088       d32   = getUChar(delta + am_sz);
14089       delta = dis_Grp1 ( sorb, pfx_lock, delta, modrm, am_sz, d_sz, sz, d32 );
14090       break;
14091
14092    case 0x81: /* Grp1 Iv,Ev */
14093       modrm = getIByte(delta);
14094       am_sz = lengthAMode(delta);
14095       d_sz  = sz;
14096       d32   = getUDisp(d_sz, delta + am_sz);
14097       delta = dis_Grp1 ( sorb, pfx_lock, delta, modrm, am_sz, d_sz, sz, d32 );
14098       break;
14099
14100    case 0x83: /* Grp1 Ib,Ev */
14101       modrm = getIByte(delta);
14102       am_sz = lengthAMode(delta);
14103       d_sz  = 1;
14104       d32   = getSDisp8(delta + am_sz);
14105       delta = dis_Grp1 ( sorb, pfx_lock, delta, modrm, am_sz, d_sz, sz, d32 );
14106       break;
14107
14108    /* ------------------------ (Grp2 extensions) ---------- */
14109
14110    case 0xC0: { /* Grp2 Ib,Eb */
14111       Bool decode_OK = True;
14112       modrm = getIByte(delta);
14113       am_sz = lengthAMode(delta);
14114       d_sz  = 1;
14115       d32   = getUChar(delta + am_sz);
14116       sz    = 1;
14117       delta = dis_Grp2 ( sorb, delta, modrm, am_sz, d_sz, sz, 
14118                          mkU8(d32 & 0xFF), NULL, &decode_OK );
14119       if (!decode_OK)
14120          goto decode_failure;
14121       break;
14122    }
14123    case 0xC1: { /* Grp2 Ib,Ev */
14124       Bool decode_OK = True;
14125       modrm = getIByte(delta);
14126       am_sz = lengthAMode(delta);
14127       d_sz  = 1;
14128       d32   = getUChar(delta + am_sz);
14129       delta = dis_Grp2 ( sorb, delta, modrm, am_sz, d_sz, sz, 
14130                          mkU8(d32 & 0xFF), NULL, &decode_OK );
14131       if (!decode_OK)
14132          goto decode_failure;
14133       break;
14134    }
14135    case 0xD0: { /* Grp2 1,Eb */
14136       Bool decode_OK = True;
14137       modrm = getIByte(delta);
14138       am_sz = lengthAMode(delta);
14139       d_sz  = 0;
14140       d32   = 1;
14141       sz    = 1;
14142       delta = dis_Grp2 ( sorb, delta, modrm, am_sz, d_sz, sz, 
14143                          mkU8(d32), NULL, &decode_OK );
14144       if (!decode_OK)
14145          goto decode_failure;
14146       break;
14147    }
14148    case 0xD1: { /* Grp2 1,Ev */
14149       Bool decode_OK = True;
14150       modrm = getUChar(delta);
14151       am_sz = lengthAMode(delta);
14152       d_sz  = 0;
14153       d32   = 1;
14154       delta = dis_Grp2 ( sorb, delta, modrm, am_sz, d_sz, sz, 
14155                          mkU8(d32), NULL, &decode_OK );
14156       if (!decode_OK)
14157          goto decode_failure;
14158       break;
14159    }
14160    case 0xD2: { /* Grp2 CL,Eb */
14161       Bool decode_OK = True;
14162       modrm = getUChar(delta);
14163       am_sz = lengthAMode(delta);
14164       d_sz  = 0;
14165       sz    = 1;
14166       delta = dis_Grp2 ( sorb, delta, modrm, am_sz, d_sz, sz, 
14167                          getIReg(1,R_ECX), "%cl", &decode_OK );
14168       if (!decode_OK)
14169          goto decode_failure;
14170       break;
14171    }
14172    case 0xD3: { /* Grp2 CL,Ev */
14173       Bool decode_OK = True;
14174       modrm = getIByte(delta);
14175       am_sz = lengthAMode(delta);
14176       d_sz  = 0;
14177       delta = dis_Grp2 ( sorb, delta, modrm, am_sz, d_sz, sz, 
14178                          getIReg(1,R_ECX), "%cl", &decode_OK );
14179       if (!decode_OK)
14180          goto decode_failure;
14181       break;
14182    }
14183
14184    /* ------------------------ (Grp3 extensions) ---------- */
14185
14186    case 0xF6: { /* Grp3 Eb */
14187       Bool decode_OK = True;
14188       delta = dis_Grp3 ( sorb, pfx_lock, 1, delta, &decode_OK );
14189       if (!decode_OK)
14190          goto decode_failure;
14191       break;
14192    }
14193    case 0xF7: { /* Grp3 Ev */
14194       Bool decode_OK = True;
14195       delta = dis_Grp3 ( sorb, pfx_lock, sz, delta, &decode_OK );
14196       if (!decode_OK)
14197          goto decode_failure;
14198       break;
14199    }
14200
14201    /* ------------------------ (Grp4 extensions) ---------- */
14202
14203    case 0xFE: { /* Grp4 Eb */
14204       Bool decode_OK = True;
14205       delta = dis_Grp4 ( sorb, pfx_lock, delta, &decode_OK );
14206       if (!decode_OK)
14207          goto decode_failure;
14208       break;
14209    }
14210
14211    /* ------------------------ (Grp5 extensions) ---------- */
14212
14213    case 0xFF: { /* Grp5 Ev */
14214       Bool decode_OK = True;
14215       delta = dis_Grp5 ( sorb, pfx_lock, sz, delta, &dres, &decode_OK );
14216       if (!decode_OK)
14217          goto decode_failure;
14218       break;
14219    }
14220
14221    /* ------------------------ Escapes to 2-byte opcodes -- */
14222
14223    case 0x0F: {
14224       opc = getIByte(delta); delta++;
14225       switch (opc) {
14226
14227       /* =-=-=-=-=-=-=-=-=- Grp8 =-=-=-=-=-=-=-=-=-=-=-= */
14228
14229       case 0xBA: { /* Grp8 Ib,Ev */
14230          Bool decode_OK = False;
14231          modrm = getUChar(delta);
14232          am_sz = lengthAMode(delta);
14233          d32   = getSDisp8(delta + am_sz);
14234          delta = dis_Grp8_Imm ( sorb, pfx_lock, delta, modrm, 
14235                                 am_sz, sz, d32, &decode_OK );
14236          if (!decode_OK)
14237             goto decode_failure;
14238          break;
14239       }
14240
14241       /* =-=-=-=-=-=-=-=-=- BSF/BSR -=-=-=-=-=-=-=-=-=-= */
14242
14243       case 0xBC: /* BSF Gv,Ev */
14244          delta = dis_bs_E_G ( sorb, sz, delta, True );
14245          break;
14246       case 0xBD: /* BSR Gv,Ev */
14247          delta = dis_bs_E_G ( sorb, sz, delta, False );
14248          break;
14249
14250       /* =-=-=-=-=-=-=-=-=- BSWAP -=-=-=-=-=-=-=-=-=-=-= */
14251
14252       case 0xC8: /* BSWAP %eax */
14253       case 0xC9:
14254       case 0xCA:
14255       case 0xCB:
14256       case 0xCC:
14257       case 0xCD:
14258       case 0xCE:
14259       case 0xCF: /* BSWAP %edi */
14260          /* AFAICS from the Intel docs, this only exists at size 4. */
14261          vassert(sz == 4);
14262          t1 = newTemp(Ity_I32);
14263          t2 = newTemp(Ity_I32);
14264          assign( t1, getIReg(4, opc-0xC8) );
14265
14266          assign( t2,
14267             binop(Iop_Or32,
14268                binop(Iop_Shl32, mkexpr(t1), mkU8(24)),
14269             binop(Iop_Or32,
14270                binop(Iop_And32, binop(Iop_Shl32, mkexpr(t1), mkU8(8)), 
14271                                 mkU32(0x00FF0000)),
14272             binop(Iop_Or32,
14273                binop(Iop_And32, binop(Iop_Shr32, mkexpr(t1), mkU8(8)),
14274                                 mkU32(0x0000FF00)),
14275                binop(Iop_And32, binop(Iop_Shr32, mkexpr(t1), mkU8(24)),
14276                                 mkU32(0x000000FF) )
14277             )))
14278          );
14279
14280          putIReg(4, opc-0xC8, mkexpr(t2));
14281          DIP("bswapl %s\n", nameIReg(4, opc-0xC8));
14282          break;
14283
14284       /* =-=-=-=-=-=-=-=-=- BT/BTS/BTR/BTC =-=-=-=-=-=-= */
14285
14286       case 0xA3: /* BT Gv,Ev */
14287          delta = dis_bt_G_E ( sorb, pfx_lock, sz, delta, BtOpNone );
14288          break;
14289       case 0xB3: /* BTR Gv,Ev */
14290          delta = dis_bt_G_E ( sorb, pfx_lock, sz, delta, BtOpReset );
14291          break;
14292       case 0xAB: /* BTS Gv,Ev */
14293          delta = dis_bt_G_E ( sorb, pfx_lock, sz, delta, BtOpSet );
14294          break;
14295       case 0xBB: /* BTC Gv,Ev */
14296          delta = dis_bt_G_E ( sorb, pfx_lock, sz, delta, BtOpComp );
14297          break;
14298
14299       /* =-=-=-=-=-=-=-=-=- CMOV =-=-=-=-=-=-=-=-=-=-=-= */
14300  
14301       case 0x40:
14302       case 0x41:
14303       case 0x42: /* CMOVBb/CMOVNAEb (cmov below) */
14304       case 0x43: /* CMOVNBb/CMOVAEb (cmov not below) */
14305       case 0x44: /* CMOVZb/CMOVEb (cmov zero) */
14306       case 0x45: /* CMOVNZb/CMOVNEb (cmov not zero) */
14307       case 0x46: /* CMOVBEb/CMOVNAb (cmov below or equal) */
14308       case 0x47: /* CMOVNBEb/CMOVAb (cmov not below or equal) */
14309       case 0x48: /* CMOVSb (cmov negative) */
14310       case 0x49: /* CMOVSb (cmov not negative) */
14311       case 0x4A: /* CMOVP (cmov parity even) */
14312       case 0x4B: /* CMOVNP (cmov parity odd) */
14313       case 0x4C: /* CMOVLb/CMOVNGEb (cmov less) */
14314       case 0x4D: /* CMOVGEb/CMOVNLb (cmov greater or equal) */
14315       case 0x4E: /* CMOVLEb/CMOVNGb (cmov less or equal) */
14316       case 0x4F: /* CMOVGb/CMOVNLEb (cmov greater) */
14317          delta = dis_cmov_E_G(sorb, sz, (X86Condcode)(opc - 0x40), delta);
14318          break;
14319
14320       /* =-=-=-=-=-=-=-=-=- CMPXCHG -=-=-=-=-=-=-=-=-=-= */
14321
14322       case 0xB0: /* CMPXCHG Gb,Eb */
14323          delta = dis_cmpxchg_G_E ( sorb, pfx_lock, 1, delta );
14324          break;
14325       case 0xB1: /* CMPXCHG Gv,Ev */
14326          delta = dis_cmpxchg_G_E ( sorb, pfx_lock, sz, delta );
14327          break;
14328
14329       case 0xC7: { /* CMPXCHG8B Gv (0F C7 /1) */
14330          IRTemp expdHi    = newTemp(Ity_I32);
14331          IRTemp expdLo    = newTemp(Ity_I32);
14332          IRTemp dataHi    = newTemp(Ity_I32);
14333          IRTemp dataLo    = newTemp(Ity_I32);
14334          IRTemp oldHi     = newTemp(Ity_I32);
14335          IRTemp oldLo     = newTemp(Ity_I32);
14336          IRTemp flags_old = newTemp(Ity_I32);
14337          IRTemp flags_new = newTemp(Ity_I32);
14338          IRTemp success   = newTemp(Ity_I1);
14339
14340          /* Translate this using a DCAS, even if there is no LOCK
14341             prefix.  Life is too short to bother with generating two
14342             different translations for the with/without-LOCK-prefix
14343             cases. */
14344          *expect_CAS = True;
14345
14346          /* Decode, and generate address. */
14347          if (sz != 4) goto decode_failure;
14348          modrm = getIByte(delta);
14349          if (epartIsReg(modrm)) goto decode_failure;
14350          if (gregOfRM(modrm) != 1) goto decode_failure;
14351          addr = disAMode ( &alen, sorb, delta, dis_buf );
14352          delta += alen;
14353
14354          /* Get the expected and new values. */
14355          assign( expdHi, getIReg(4,R_EDX) );
14356          assign( expdLo, getIReg(4,R_EAX) );
14357          assign( dataHi, getIReg(4,R_ECX) );
14358          assign( dataLo, getIReg(4,R_EBX) );
14359
14360          /* Do the DCAS */
14361          stmt( IRStmt_CAS(
14362                   mkIRCAS( oldHi, oldLo, 
14363                            Iend_LE, mkexpr(addr), 
14364                            mkexpr(expdHi), mkexpr(expdLo),
14365                            mkexpr(dataHi), mkexpr(dataLo)
14366                )));
14367
14368          /* success when oldHi:oldLo == expdHi:expdLo */
14369          assign( success,
14370                  binop(Iop_CasCmpEQ32,
14371                        binop(Iop_Or32,
14372                              binop(Iop_Xor32, mkexpr(oldHi), mkexpr(expdHi)),
14373                              binop(Iop_Xor32, mkexpr(oldLo), mkexpr(expdLo))
14374                        ),
14375                        mkU32(0)
14376                  ));
14377
14378          /* If the DCAS is successful, that is to say oldHi:oldLo ==
14379             expdHi:expdLo, then put expdHi:expdLo back in EDX:EAX,
14380             which is where they came from originally.  Both the actual
14381             contents of these two regs, and any shadow values, are
14382             unchanged.  If the DCAS fails then we're putting into
14383             EDX:EAX the value seen in memory. */
14384          putIReg(4, R_EDX,
14385                     IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(success)),
14386                                   mkexpr(oldHi),
14387                                   mkexpr(expdHi)
14388                 ));
14389          putIReg(4, R_EAX,
14390                     IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(success)),
14391                                   mkexpr(oldLo),
14392                                   mkexpr(expdLo)
14393                 ));
14394
14395          /* Copy the success bit into the Z flag and leave the others
14396             unchanged */
14397          assign( flags_old, widenUto32(mk_x86g_calculate_eflags_all()));
14398          assign( 
14399             flags_new,
14400             binop(Iop_Or32,
14401                   binop(Iop_And32, mkexpr(flags_old), 
14402                                    mkU32(~X86G_CC_MASK_Z)),
14403                   binop(Iop_Shl32, 
14404                         binop(Iop_And32, 
14405                               unop(Iop_1Uto32, mkexpr(success)), mkU32(1)), 
14406                         mkU8(X86G_CC_SHIFT_Z)) ));
14407
14408          stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(X86G_CC_OP_COPY) ));
14409          stmt( IRStmt_Put( OFFB_CC_DEP1, mkexpr(flags_new) ));
14410          stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0) ));
14411          /* Set NDEP even though it isn't used.  This makes
14412             redundant-PUT elimination of previous stores to this field
14413             work better. */
14414          stmt( IRStmt_Put( OFFB_CC_NDEP, mkU32(0) ));
14415
14416          /* Sheesh.  Aren't you glad it was me and not you that had to
14417             write and validate all this grunge? */
14418
14419          DIP("cmpxchg8b %s\n", dis_buf);
14420          break;
14421       }
14422
14423       /* =-=-=-=-=-=-=-=-=- CPUID -=-=-=-=-=-=-=-=-=-=-= */
14424
14425       case 0xA2: { /* CPUID */
14426          /* Uses dirty helper: 
14427                void dirtyhelper_CPUID_sse[012] ( VexGuestX86State* )
14428             declared to mod eax, wr ebx, ecx, edx
14429          */
14430          IRDirty* d     = NULL;
14431          HChar*   fName = NULL;
14432          void*    fAddr = NULL;
14433          if (archinfo->hwcaps & VEX_HWCAPS_X86_SSE2) {
14434             fName = "x86g_dirtyhelper_CPUID_sse2";
14435             fAddr = &x86g_dirtyhelper_CPUID_sse2; 
14436          } 
14437          else
14438          if (archinfo->hwcaps & VEX_HWCAPS_X86_SSE1) {
14439             fName = "x86g_dirtyhelper_CPUID_sse1";
14440             fAddr = &x86g_dirtyhelper_CPUID_sse1; 
14441          } 
14442          else
14443          if (archinfo->hwcaps == 0/*no SSE*/) {
14444             fName = "x86g_dirtyhelper_CPUID_sse0";
14445             fAddr = &x86g_dirtyhelper_CPUID_sse0; 
14446          } else
14447             vpanic("disInstr(x86)(cpuid)");
14448
14449          vassert(fName); vassert(fAddr);
14450          d = unsafeIRDirty_0_N ( 0/*regparms*/, 
14451                                  fName, fAddr, mkIRExprVec_0() );
14452          /* declare guest state effects */
14453          d->needsBBP = True;
14454          d->nFxState = 4;
14455          d->fxState[0].fx     = Ifx_Modify;
14456          d->fxState[0].offset = OFFB_EAX;
14457          d->fxState[0].size   = 4;
14458          d->fxState[1].fx     = Ifx_Write;
14459          d->fxState[1].offset = OFFB_EBX;
14460          d->fxState[1].size   = 4;
14461          d->fxState[2].fx     = Ifx_Modify;
14462          d->fxState[2].offset = OFFB_ECX;
14463          d->fxState[2].size   = 4;
14464          d->fxState[3].fx     = Ifx_Write;
14465          d->fxState[3].offset = OFFB_EDX;
14466          d->fxState[3].size   = 4;
14467          /* execute the dirty call, side-effecting guest state */
14468          stmt( IRStmt_Dirty(d) );
14469          /* CPUID is a serialising insn.  So, just in case someone is
14470             using it as a memory fence ... */
14471          stmt( IRStmt_MBE(Imbe_Fence) );
14472          DIP("cpuid\n");
14473          break;
14474       }
14475
14476 //--          if (!VG_(cpu_has_feature)(VG_X86_FEAT_CPUID))
14477 //--             goto decode_failure;
14478 //-- 
14479 //--          t1 = newTemp(cb);
14480 //--          t2 = newTemp(cb);
14481 //--          t3 = newTemp(cb);
14482 //--          t4 = newTemp(cb);
14483 //--          uInstr0(cb, CALLM_S, 0);
14484 //-- 
14485 //--          uInstr2(cb, GET,   4, ArchReg, R_EAX, TempReg, t1);
14486 //--          uInstr1(cb, PUSH,  4, TempReg, t1);
14487 //-- 
14488 //--          uInstr2(cb, MOV,   4, Literal, 0, TempReg, t2);
14489 //--          uLiteral(cb, 0);
14490 //--          uInstr1(cb, PUSH,  4, TempReg, t2);
14491 //-- 
14492 //--          uInstr2(cb, MOV,   4, Literal, 0, TempReg, t3);
14493 //--          uLiteral(cb, 0);
14494 //--          uInstr1(cb, PUSH,  4, TempReg, t3);
14495 //-- 
14496 //--          uInstr2(cb, MOV,   4, Literal, 0, TempReg, t4);
14497 //--          uLiteral(cb, 0);
14498 //--          uInstr1(cb, PUSH,  4, TempReg, t4);
14499 //-- 
14500 //--          uInstr1(cb, CALLM, 0, Lit16,   VGOFF_(helper_CPUID));
14501 //--          uFlagsRWU(cb, FlagsEmpty, FlagsEmpty, FlagsEmpty);
14502 //-- 
14503 //--          uInstr1(cb, POP,   4, TempReg, t4);
14504 //--          uInstr2(cb, PUT,   4, TempReg, t4, ArchReg, R_EDX);
14505 //-- 
14506 //--          uInstr1(cb, POP,   4, TempReg, t3);
14507 //--          uInstr2(cb, PUT,   4, TempReg, t3, ArchReg, R_ECX);
14508 //-- 
14509 //--          uInstr1(cb, POP,   4, TempReg, t2);
14510 //--          uInstr2(cb, PUT,   4, TempReg, t2, ArchReg, R_EBX);
14511 //-- 
14512 //--          uInstr1(cb, POP,   4, TempReg, t1);
14513 //--          uInstr2(cb, PUT,   4, TempReg, t1, ArchReg, R_EAX);
14514 //-- 
14515 //--          uInstr0(cb, CALLM_E, 0);
14516 //--          DIP("cpuid\n");
14517 //--          break;
14518 //-- 
14519       /* =-=-=-=-=-=-=-=-=- MOVZX, MOVSX =-=-=-=-=-=-=-= */
14520
14521       case 0xB6: /* MOVZXb Eb,Gv */
14522          if (sz != 2 && sz != 4)
14523             goto decode_failure;
14524          delta = dis_movx_E_G ( sorb, delta, 1, sz, False );
14525          break;
14526
14527       case 0xB7: /* MOVZXw Ew,Gv */
14528          if (sz != 4)
14529             goto decode_failure;
14530          delta = dis_movx_E_G ( sorb, delta, 2, 4, False );
14531          break;
14532
14533       case 0xBE: /* MOVSXb Eb,Gv */
14534          if (sz != 2 && sz != 4)
14535             goto decode_failure;
14536          delta = dis_movx_E_G ( sorb, delta, 1, sz, True );
14537          break;
14538
14539       case 0xBF: /* MOVSXw Ew,Gv */
14540          if (sz != 4)
14541             goto decode_failure;
14542          delta = dis_movx_E_G ( sorb, delta, 2, 4, True );
14543          break;
14544
14545 //--       /* =-=-=-=-=-=-=-=-=-=-= MOVNTI -=-=-=-=-=-=-=-=-= */
14546 //-- 
14547 //--       case 0xC3: /* MOVNTI Gv,Ev */
14548 //--          vg_assert(sz == 4);
14549 //--          modrm = getUChar(eip);
14550 //--          vg_assert(!epartIsReg(modrm));
14551 //--          t1 = newTemp(cb);
14552 //--          uInstr2(cb, GET, 4, ArchReg, gregOfRM(modrm), TempReg, t1);
14553 //--          pair = disAMode ( cb, sorb, eip, dis_buf );
14554 //--          t2 = LOW24(pair);
14555 //--          eip += HI8(pair);
14556 //--          uInstr2(cb, STORE, 4, TempReg, t1, TempReg, t2);
14557 //--          DIP("movnti %s,%s\n", nameIReg(4,gregOfRM(modrm)), dis_buf);
14558 //--          break;
14559
14560       /* =-=-=-=-=-=-=-=-=- MUL/IMUL =-=-=-=-=-=-=-=-=-= */
14561
14562       case 0xAF: /* IMUL Ev, Gv */
14563          delta = dis_mul_E_G ( sorb, sz, delta );
14564          break;
14565
14566       /* =-=-=-=-=-=-=-=-=- NOPs =-=-=-=-=-=-=-=-=-=-=-= */
14567
14568       case 0x1F:
14569          modrm = getUChar(delta);
14570          if (epartIsReg(modrm)) goto decode_failure;
14571          addr = disAMode ( &alen, sorb, delta, dis_buf );
14572          delta += alen;
14573          DIP("nop%c %s\n", nameISize(sz), dis_buf);
14574          break;
14575
14576       /* =-=-=-=-=-=-=-=-=- Jcond d32 -=-=-=-=-=-=-=-=-= */
14577       case 0x80:
14578       case 0x81:
14579       case 0x82: /* JBb/JNAEb (jump below) */
14580       case 0x83: /* JNBb/JAEb (jump not below) */
14581       case 0x84: /* JZb/JEb (jump zero) */
14582       case 0x85: /* JNZb/JNEb (jump not zero) */
14583       case 0x86: /* JBEb/JNAb (jump below or equal) */
14584       case 0x87: /* JNBEb/JAb (jump not below or equal) */
14585       case 0x88: /* JSb (jump negative) */
14586       case 0x89: /* JSb (jump not negative) */
14587       case 0x8A: /* JP (jump parity even) */
14588       case 0x8B: /* JNP/JPO (jump parity odd) */
14589       case 0x8C: /* JLb/JNGEb (jump less) */
14590       case 0x8D: /* JGEb/JNLb (jump greater or equal) */
14591       case 0x8E: /* JLEb/JNGb (jump less or equal) */
14592       case 0x8F: /* JGb/JNLEb (jump greater) */
14593        { Int    jmpDelta;
14594          HChar* comment  = "";
14595          jmpDelta = (Int)getUDisp32(delta);
14596          d32 = (((Addr32)guest_EIP_bbstart)+delta+4) + jmpDelta;
14597          delta += 4;
14598          if (resteerCisOk
14599              && vex_control.guest_chase_cond
14600              && (Addr32)d32 != (Addr32)guest_EIP_bbstart
14601              && jmpDelta < 0
14602              && resteerOkFn( callback_opaque, (Addr64)(Addr32)d32) ) {
14603             /* Speculation: assume this backward branch is taken.  So
14604                we need to emit a side-exit to the insn following this
14605                one, on the negation of the condition, and continue at
14606                the branch target address (d32).  If we wind up back at
14607                the first instruction of the trace, just stop; it's
14608                better to let the IR loop unroller handle that case.*/
14609             stmt( IRStmt_Exit( 
14610                      mk_x86g_calculate_condition((X86Condcode)
14611                                                  (1 ^ (opc - 0x80))),
14612                      Ijk_Boring,
14613                      IRConst_U32(guest_EIP_bbstart+delta) ) );
14614             dres.whatNext   = Dis_ResteerC;
14615             dres.continueAt = (Addr64)(Addr32)d32;
14616             comment = "(assumed taken)";
14617          }
14618          else
14619          if (resteerCisOk
14620              && vex_control.guest_chase_cond
14621              && (Addr32)d32 != (Addr32)guest_EIP_bbstart
14622              && jmpDelta >= 0
14623              && resteerOkFn( callback_opaque, 
14624                              (Addr64)(Addr32)(guest_EIP_bbstart+delta)) ) {
14625             /* Speculation: assume this forward branch is not taken.
14626                So we need to emit a side-exit to d32 (the dest) and
14627                continue disassembling at the insn immediately
14628                following this one. */
14629             stmt( IRStmt_Exit( 
14630                      mk_x86g_calculate_condition((X86Condcode)(opc - 0x80)),
14631                      Ijk_Boring,
14632                      IRConst_U32(d32) ) );
14633             dres.whatNext   = Dis_ResteerC;
14634             dres.continueAt = (Addr64)(Addr32)(guest_EIP_bbstart+delta);
14635             comment = "(assumed not taken)";
14636          }
14637          else {
14638             /* Conservative default translation - end the block at
14639                this point. */
14640          jcc_01( (X86Condcode)(opc - 0x80), 
14641                     (Addr32)(guest_EIP_bbstart+delta), d32);
14642          dres.whatNext = Dis_StopHere;
14643          }
14644          DIP("j%s-32 0x%x %s\n", name_X86Condcode(opc - 0x80), d32, comment);
14645          break;
14646        }
14647
14648       /* =-=-=-=-=-=-=-=-=- RDTSC -=-=-=-=-=-=-=-=-=-=-= */
14649       case 0x31: { /* RDTSC */
14650          IRTemp   val  = newTemp(Ity_I64);
14651          IRExpr** args = mkIRExprVec_0();
14652          IRDirty* d    = unsafeIRDirty_1_N ( 
14653                             val, 
14654                             0/*regparms*/, 
14655                             "x86g_dirtyhelper_RDTSC", 
14656                             &x86g_dirtyhelper_RDTSC, 
14657                             args 
14658                          );
14659          /* execute the dirty call, dumping the result in val. */
14660          stmt( IRStmt_Dirty(d) );
14661          putIReg(4, R_EDX, unop(Iop_64HIto32, mkexpr(val)));
14662          putIReg(4, R_EAX, unop(Iop_64to32, mkexpr(val)));
14663          DIP("rdtsc\n");
14664          break;
14665       }
14666
14667       /* =-=-=-=-=-=-=-=-=- PUSH/POP Sreg =-=-=-=-=-=-=-=-=-= */
14668
14669       case 0xA1: /* POP %FS */
14670          dis_pop_segreg( R_FS, sz ); break;
14671       case 0xA9: /* POP %GS */
14672          dis_pop_segreg( R_GS, sz ); break;
14673
14674       case 0xA0: /* PUSH %FS */
14675          dis_push_segreg( R_FS, sz ); break;
14676       case 0xA8: /* PUSH %GS */
14677          dis_push_segreg( R_GS, sz ); break;
14678
14679       /* =-=-=-=-=-=-=-=-=- SETcc Eb =-=-=-=-=-=-=-=-=-= */
14680       case 0x90:
14681       case 0x91:
14682       case 0x92: /* set-Bb/set-NAEb (jump below) */
14683       case 0x93: /* set-NBb/set-AEb (jump not below) */
14684       case 0x94: /* set-Zb/set-Eb (jump zero) */
14685       case 0x95: /* set-NZb/set-NEb (jump not zero) */
14686       case 0x96: /* set-BEb/set-NAb (jump below or equal) */
14687       case 0x97: /* set-NBEb/set-Ab (jump not below or equal) */
14688       case 0x98: /* set-Sb (jump negative) */
14689       case 0x99: /* set-Sb (jump not negative) */
14690       case 0x9A: /* set-P (jump parity even) */
14691       case 0x9B: /* set-NP (jump parity odd) */
14692       case 0x9C: /* set-Lb/set-NGEb (jump less) */
14693       case 0x9D: /* set-GEb/set-NLb (jump greater or equal) */
14694       case 0x9E: /* set-LEb/set-NGb (jump less or equal) */
14695       case 0x9F: /* set-Gb/set-NLEb (jump greater) */
14696          t1 = newTemp(Ity_I8);
14697          assign( t1, unop(Iop_1Uto8,mk_x86g_calculate_condition(opc-0x90)) );
14698          modrm = getIByte(delta);
14699          if (epartIsReg(modrm)) {
14700             delta++;
14701             putIReg(1, eregOfRM(modrm), mkexpr(t1));
14702             DIP("set%s %s\n", name_X86Condcode(opc-0x90), 
14703                               nameIReg(1,eregOfRM(modrm)));
14704          } else {
14705            addr = disAMode ( &alen, sorb, delta, dis_buf );
14706            delta += alen;
14707            storeLE( mkexpr(addr), mkexpr(t1) );
14708            DIP("set%s %s\n", name_X86Condcode(opc-0x90), dis_buf);
14709          }
14710          break;
14711
14712       /* =-=-=-=-=-=-=-=-=- SHLD/SHRD -=-=-=-=-=-=-=-=-= */
14713
14714       case 0xA4: /* SHLDv imm8,Gv,Ev */
14715          modrm = getIByte(delta);
14716          d32   = delta + lengthAMode(delta);
14717          vex_sprintf(dis_buf, "$%d", getIByte(d32));
14718          delta = dis_SHLRD_Gv_Ev ( 
14719                   sorb, delta, modrm, sz, 
14720                   mkU8(getIByte(d32)), True, /* literal */
14721                   dis_buf, True );
14722          break;
14723       case 0xA5: /* SHLDv %cl,Gv,Ev */
14724          modrm = getIByte(delta);
14725          delta = dis_SHLRD_Gv_Ev ( 
14726                     sorb, delta, modrm, sz,
14727                     getIReg(1,R_ECX), False, /* not literal */
14728                     "%cl", True );
14729          break;
14730
14731       case 0xAC: /* SHRDv imm8,Gv,Ev */
14732          modrm = getIByte(delta);
14733          d32   = delta + lengthAMode(delta);
14734          vex_sprintf(dis_buf, "$%d", getIByte(d32));
14735          delta = dis_SHLRD_Gv_Ev ( 
14736                     sorb, delta, modrm, sz, 
14737                     mkU8(getIByte(d32)), True, /* literal */
14738                     dis_buf, False );
14739          break;
14740       case 0xAD: /* SHRDv %cl,Gv,Ev */
14741          modrm = getIByte(delta);
14742          delta = dis_SHLRD_Gv_Ev ( 
14743                     sorb, delta, modrm, sz, 
14744                     getIReg(1,R_ECX), False, /* not literal */
14745                     "%cl", False );
14746          break;
14747
14748       /* =-=-=-=-=-=-=-=-=- SYSENTER -=-=-=-=-=-=-=-=-=-= */
14749
14750       case 0x34:
14751          /* Simple implementation needing a long explaination.
14752
14753             sysenter is a kind of syscall entry.  The key thing here
14754             is that the return address is not known -- that is
14755             something that is beyond Vex's knowledge.  So this IR
14756             forces a return to the scheduler, which can do what it
14757             likes to simulate the systenter, but it MUST set this
14758             thread's guest_EIP field with the continuation address
14759             before resuming execution.  If that doesn't happen, the
14760             thread will jump to address zero, which is probably
14761             fatal. 
14762          */
14763
14764          /* Note where we are, so we can back up the guest to this
14765             point if the syscall needs to be restarted. */
14766          stmt( IRStmt_Put( OFFB_IP_AT_SYSCALL,
14767                            mkU32(guest_EIP_curr_instr) ) );
14768          jmp_lit(Ijk_Sys_sysenter, 0/*bogus next EIP value*/);
14769          dres.whatNext = Dis_StopHere;
14770          DIP("sysenter");
14771          break;
14772
14773       /* =-=-=-=-=-=-=-=-=- XADD -=-=-=-=-=-=-=-=-=-= */
14774
14775       case 0xC0: { /* XADD Gb,Eb */
14776          Bool decodeOK;
14777          delta = dis_xadd_G_E ( sorb, pfx_lock, 1, delta, &decodeOK );
14778          if (!decodeOK) goto decode_failure;
14779          break;
14780       }
14781       case 0xC1: { /* XADD Gv,Ev */
14782          Bool decodeOK;
14783          delta = dis_xadd_G_E ( sorb, pfx_lock, sz, delta, &decodeOK );
14784          if (!decodeOK) goto decode_failure;
14785          break;
14786       }
14787
14788       /* =-=-=-=-=-=-=-=-=- MMXery =-=-=-=-=-=-=-=-=-=-= */
14789
14790       case 0x71: 
14791       case 0x72: 
14792       case 0x73: /* PSLLgg/PSRAgg/PSRLgg mmxreg by imm8 */
14793
14794       case 0x6E: /* MOVD (src)ireg-or-mem, (dst)mmxreg */
14795       case 0x7E: /* MOVD (src)mmxreg, (dst)ireg-or-mem */
14796       case 0x7F: /* MOVQ (src)mmxreg, (dst)mmxreg-or-mem */
14797       case 0x6F: /* MOVQ (src)mmxreg-or-mem, (dst)mmxreg */
14798
14799       case 0xFC: 
14800       case 0xFD: 
14801       case 0xFE: /* PADDgg (src)mmxreg-or-mem, (dst)mmxreg */
14802
14803       case 0xEC: 
14804       case 0xED: /* PADDSgg (src)mmxreg-or-mem, (dst)mmxreg */
14805
14806       case 0xDC:
14807       case 0xDD: /* PADDUSgg (src)mmxreg-or-mem, (dst)mmxreg */
14808
14809       case 0xF8: 
14810       case 0xF9: 
14811       case 0xFA: /* PSUBgg (src)mmxreg-or-mem, (dst)mmxreg */
14812
14813       case 0xE8: 
14814       case 0xE9: /* PSUBSgg (src)mmxreg-or-mem, (dst)mmxreg */
14815
14816       case 0xD8: 
14817       case 0xD9: /* PSUBUSgg (src)mmxreg-or-mem, (dst)mmxreg */
14818
14819       case 0xE5: /* PMULHW (src)mmxreg-or-mem, (dst)mmxreg */
14820       case 0xD5: /* PMULLW (src)mmxreg-or-mem, (dst)mmxreg */
14821
14822       case 0xF5: /* PMADDWD (src)mmxreg-or-mem, (dst)mmxreg */
14823
14824       case 0x74: 
14825       case 0x75: 
14826       case 0x76: /* PCMPEQgg (src)mmxreg-or-mem, (dst)mmxreg */
14827
14828       case 0x64: 
14829       case 0x65: 
14830       case 0x66: /* PCMPGTgg (src)mmxreg-or-mem, (dst)mmxreg */
14831
14832       case 0x6B: /* PACKSSDW (src)mmxreg-or-mem, (dst)mmxreg */
14833       case 0x63: /* PACKSSWB (src)mmxreg-or-mem, (dst)mmxreg */
14834       case 0x67: /* PACKUSWB (src)mmxreg-or-mem, (dst)mmxreg */
14835
14836       case 0x68: 
14837       case 0x69: 
14838       case 0x6A: /* PUNPCKHgg (src)mmxreg-or-mem, (dst)mmxreg */
14839
14840       case 0x60: 
14841       case 0x61: 
14842       case 0x62: /* PUNPCKLgg (src)mmxreg-or-mem, (dst)mmxreg */
14843
14844       case 0xDB: /* PAND (src)mmxreg-or-mem, (dst)mmxreg */
14845       case 0xDF: /* PANDN (src)mmxreg-or-mem, (dst)mmxreg */
14846       case 0xEB: /* POR (src)mmxreg-or-mem, (dst)mmxreg */
14847       case 0xEF: /* PXOR (src)mmxreg-or-mem, (dst)mmxreg */
14848
14849       case 0xF1: /* PSLLgg (src)mmxreg-or-mem, (dst)mmxreg */
14850       case 0xF2: 
14851       case 0xF3: 
14852
14853       case 0xD1: /* PSRLgg (src)mmxreg-or-mem, (dst)mmxreg */
14854       case 0xD2: 
14855       case 0xD3: 
14856
14857       case 0xE1: /* PSRAgg (src)mmxreg-or-mem, (dst)mmxreg */
14858       case 0xE2: 
14859       {
14860          Int  delta0    = delta-1;
14861          Bool decode_OK = False;
14862
14863          /* If sz==2 this is SSE, and we assume sse idec has
14864             already spotted those cases by now. */
14865          if (sz != 4)
14866             goto decode_failure;
14867
14868          delta = dis_MMX ( &decode_OK, sorb, sz, delta-1 );
14869          if (!decode_OK) {
14870             delta = delta0;
14871             goto decode_failure;
14872          }
14873          break;
14874       }
14875
14876       case 0x77: /* EMMS */
14877          if (sz != 4)
14878             goto decode_failure;
14879          do_EMMS_preamble();
14880          DIP("emms\n");
14881          break;
14882
14883       /* =-=-=-=-=-=-=-=-=- unimp2 =-=-=-=-=-=-=-=-=-=-= */
14884
14885       default:
14886          goto decode_failure;
14887    } /* switch (opc) for the 2-byte opcodes */
14888    goto decode_success;
14889    } /* case 0x0F: of primary opcode */
14890
14891    /* ------------------------ ??? ------------------------ */
14892   
14893   default:
14894   decode_failure:
14895    /* All decode failures end up here. */
14896    vex_printf("vex x86->IR: unhandled instruction bytes: "
14897               "0x%x 0x%x 0x%x 0x%x\n",
14898               (Int)getIByte(delta_start+0),
14899               (Int)getIByte(delta_start+1),
14900               (Int)getIByte(delta_start+2),
14901               (Int)getIByte(delta_start+3) );
14902
14903    /* Tell the dispatcher that this insn cannot be decoded, and so has
14904       not been executed, and (is currently) the next to be executed.
14905       EIP should be up-to-date since it made so at the start of each
14906       insn, but nevertheless be paranoid and update it again right
14907       now. */
14908    stmt( IRStmt_Put( OFFB_EIP, mkU32(guest_EIP_curr_instr) ) );
14909    jmp_lit(Ijk_NoDecode, guest_EIP_curr_instr);
14910    dres.whatNext = Dis_StopHere;
14911    dres.len = 0;
14912    /* We also need to say that a CAS is not expected now, regardless
14913       of what it might have been set to at the start of the function,
14914       since the IR that we've emitted just above (to synthesis a
14915       SIGILL) does not involve any CAS, and presumably no other IR has
14916       been emitted for this (non-decoded) insn. */
14917    *expect_CAS = False;
14918    return dres;
14919
14920    } /* switch (opc) for the main (primary) opcode switch. */
14921
14922   decode_success:
14923    /* All decode successes end up here. */
14924    DIP("\n");
14925    dres.len = delta - delta_start;
14926    return dres;
14927 }
14928
14929 #undef DIP
14930 #undef DIS
14931
14932
14933 /*------------------------------------------------------------*/
14934 /*--- Top-level fn                                         ---*/
14935 /*------------------------------------------------------------*/
14936
14937 /* Disassemble a single instruction into IR.  The instruction
14938    is located in host memory at &guest_code[delta]. */
14939
14940 DisResult disInstr_X86 ( IRSB*        irsb_IN,
14941                          Bool         put_IP,
14942                          Bool         (*resteerOkFn) ( void*, Addr64 ),
14943                          Bool         resteerCisOk,
14944                          void*        callback_opaque,
14945                          UChar*       guest_code_IN,
14946                          Long         delta,
14947                          Addr64       guest_IP,
14948                          VexArch      guest_arch,
14949                          VexArchInfo* archinfo,
14950                          VexAbiInfo*  abiinfo,
14951                          Bool         host_bigendian_IN )
14952 {
14953    Int       i, x1, x2;
14954    Bool      expect_CAS, has_CAS;
14955    DisResult dres;
14956
14957    /* Set globals (see top of this file) */
14958    vassert(guest_arch == VexArchX86);
14959    guest_code           = guest_code_IN;
14960    irsb                 = irsb_IN;
14961    host_is_bigendian    = host_bigendian_IN;
14962    guest_EIP_curr_instr = (Addr32)guest_IP;
14963    guest_EIP_bbstart    = (Addr32)toUInt(guest_IP - delta);
14964
14965    x1 = irsb_IN->stmts_used;
14966    expect_CAS = False;
14967    dres = disInstr_X86_WRK ( &expect_CAS, put_IP, resteerOkFn,
14968                              resteerCisOk,
14969                              callback_opaque, delta, archinfo );
14970    x2 = irsb_IN->stmts_used;
14971    vassert(x2 >= x1);
14972
14973    /* See comment at the top of disInstr_X86_WRK for meaning of
14974       expect_CAS.  Here, we (sanity-)check for the presence/absence of
14975       IRCAS as directed by the returned expect_CAS value. */
14976    has_CAS = False;
14977    for (i = x1; i < x2; i++) {
14978       if (irsb_IN->stmts[i]->tag == Ist_CAS)
14979          has_CAS = True;
14980    }
14981
14982    if (expect_CAS != has_CAS) {
14983       /* inconsistency detected.  re-disassemble the instruction so as
14984          to generate a useful error message; then assert. */
14985       vex_traceflags |= VEX_TRACE_FE;
14986       dres = disInstr_X86_WRK ( &expect_CAS, put_IP, resteerOkFn,
14987                                 resteerCisOk,
14988                                 callback_opaque, delta, archinfo );
14989       for (i = x1; i < x2; i++) {
14990          vex_printf("\t\t");
14991          ppIRStmt(irsb_IN->stmts[i]);
14992          vex_printf("\n");
14993       }
14994       /* Failure of this assertion is serious and denotes a bug in
14995          disInstr. */
14996       vpanic("disInstr_X86: inconsistency in LOCK prefix handling");
14997    }
14998
14999    return dres;
15000 }
15001
15002
15003 /*--------------------------------------------------------------------*/
15004 /*--- end                                         guest_x86_toIR.c ---*/
15005 /*--------------------------------------------------------------------*/