1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- begin                                     guest_amd64_toIR.c ---*/
4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This file is part of Valgrind, a dynamic binary instrumentation
8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   framework.
9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Copyright (C) 2004-2012 OpenWorks LLP
11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      info@open-works.net
12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is free software; you can redistribute it and/or
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   modify it under the terms of the GNU General Public License as
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   published by the Free Software Foundation; either version 2 of the
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   License, or (at your option) any later version.
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is distributed in the hope that it will be useful, but
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   WITHOUT ANY WARRANTY; without even the implied warranty of
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   General Public License for more details.
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   You should have received a copy of the GNU General Public License
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   along with this program; if not, write to the Free Software
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   02110-1301, USA.
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The GNU General Public License is contained in the file COPYING.
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Neither the names of the U.S. Department of Energy nor the
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   University of California nor the names of its contributors may be
32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   used to endorse or promote products derived from this software
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   without prior written permission.
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Translates AMD64 code to IR. */
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* TODO:
39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   All Puts to CC_OP/CC_DEP1/CC_DEP2/CC_NDEP should really be checked
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   to ensure a 64-bit value is being written.
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   x87 FP Limitations:
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * all arithmetic done at 64 bits
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * no FP exceptions, except for handling stack over/underflow
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * FP rounding mode observed only for float->int conversions and
50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     int->float conversions which could lose accuracy, and for
51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     float-to-float rounding.  For all other operations,
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     round-to-nearest is used, regardless.
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * FP sin/cos/tan/sincos: C2 flag is always cleared.  IOW the
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     simulation claims the argument is in-range (-2^63 <= arg <= 2^63)
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     even when it isn't.
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * some of the FCOM cases could do with testing -- not convinced
59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     that the args are the right way round.
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * FSAVE does not re-initialise the FPU; it should do
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * FINIT not only initialises the FPU environment, it also zeroes
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     all the FP registers.  It should leave the registers unchanged.
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    RDTSC returns zero, always.
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    SAHF should cause eflags[1] == 1, and in fact it produces 0.  As
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    per Intel docs this bit has no meaning anyway.  Since PUSHF is the
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    only way to observe eflags[1], a proper fix would be to make that
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    bit be set by PUSHF.
72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    This module uses global variables and so is not MT-safe (if that
74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    should ever become relevant).
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Notes re address size overrides (0x67).
78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   According to the AMD documentation (24594 Rev 3.09, Sept 2003,
80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   "AMD64 Architecture Programmer's Manual Volume 3: General-Purpose
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and System Instructions"), Section 1.2.3 ("Address-Size Override
82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Prefix"):
83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   0x67 applies to all explicit memory references, causing the top
85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   32 bits of the effective address to become zero.
86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   0x67 has no effect on stack references (push/pop); these always
88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   use a 64-bit address.
89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   0x67 changes the interpretation of instructions which implicitly
91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   reference RCX/RSI/RDI, so that in fact ECX/ESI/EDI are used
92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   instead.  These are:
93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cmp{s,sb,sw,sd,sq}
95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      in{s,sb,sw,sd}
96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      jcxz, jecxz, jrcxz
97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      lod{s,sb,sw,sd,sq}
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      loop{,e,bz,be,z}
99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      mov{s,sb,sw,sd,sq}
100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      out{s,sb,sw,sd}
101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      rep{,e,ne,nz}
102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      sca{s,sb,sw,sd,sq}
103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      sto{s,sb,sw,sd,sq}
104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xlat{,b} */
105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* "Special" instructions.
107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This instruction decoder can decode three special instructions
109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   which mean nothing natively (are no-ops as far as regs/mem are
110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   concerned) but have meaning for supporting Valgrind.  A special
111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   instruction is flagged by the 16-byte preamble 48C1C703 48C1C70D
112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   48C1C73D 48C1C733 (in the standard interpretation, that means: rolq
113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   $3, %rdi; rolq $13, %rdi; rolq $61, %rdi; rolq $51, %rdi).
114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Following that, one of the following 3 are allowed (standard
115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   interpretation in parentheses):
116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      4887DB (xchgq %rbx,%rbx)   %RDX = client_request ( %RAX )
118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      4887C9 (xchgq %rcx,%rcx)   %RAX = guest_NRADDR
119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      4887D2 (xchgq %rdx,%rdx)   call-noredir *%RAX
120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Any other bytes following the 16-byte preamble are illegal and
122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   constitute a failure in instruction decoding.  This all assumes
123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   that the preamble will never occur except in specific code
124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   fragments designed for Valgrind to catch.
125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   No prefixes may precede a "Special" instruction.
127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* casLE (implementation of lock-prefixed insns) and rep-prefixed
130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   insns: the side-exit back to the start of the insn is done with
131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Ijk_Boring.  This is quite wrong, it should be done with
132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Ijk_NoRedir, since otherwise the side exit, which is intended to
133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   restart the instruction for whatever reason, could go somewhere
134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   entirely else.  Doing it right (with Ijk_NoRedir jumps) would make
135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   no-redir jumps performance critical, at least for rep-prefixed
136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   instructions, since all iterations thereof would involve such a
137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   jump.  It's not such a big deal with casLE since the side exit is
138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   only taken if the CAS fails, that is, the location is contended,
139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   which is relatively unlikely.
140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Note also, the test for CAS success vs failure is done using
142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Iop_CasCmp{EQ,NE}{8,16,32,64} rather than the ordinary
143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Iop_Cmp{EQ,NE} equivalents.  This is so as to tell Memcheck that it
144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   shouldn't definedness-check these comparisons.  See
145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   COMMENT_ON_CasCmpEQ in memcheck/mc_translate.c for
146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   background/rationale.
147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* LOCK prefixed instructions.  These are translated using IR-level
150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CAS statements (IRCAS) and are believed to preserve atomicity, even
151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   from the point of view of some other process racing against a
152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   simulated one (presumably they communicate via a shared memory
153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   segment).
154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Handlers which are aware of LOCK prefixes are:
156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dis_op2_G_E      (add, or, adc, sbb, and, sub, xor)
157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dis_cmpxchg_G_E  (cmpxchg)
158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dis_Grp1         (add, or, adc, sbb, and, sub, xor)
159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dis_Grp3         (not, neg)
160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dis_Grp4         (inc, dec)
161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dis_Grp5         (inc, dec)
162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dis_Grp8_Imm     (bts, btc, btr)
163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dis_bt_G_E       (bts, btc, btr)
164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dis_xadd_G_E     (xadd)
165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex_basictypes.h"
169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex_ir.h"
170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex.h"
171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex_guest_amd64.h"
172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "main_util.h"
174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "main_globals.h"
175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "guest_generic_bb_to_IR.h"
176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "guest_generic_x87.h"
177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "guest_amd64_defs.h"
178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Globals                                              ---*/
182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* These are set at the start of the translation of an insn, right
185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   down in disInstr_AMD64, so that we don't have to pass them around
186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   endlessly.  They are all constant during the translation of any
187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   given insn. */
188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* These are set at the start of the translation of a BB, so
190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   that we don't have to pass them around endlessly. */
191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* We need to know this to do sub-register accesses correctly. */
193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool host_is_bigendian;
194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Pointer to the guest code area (points to start of BB, not to the
196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   insn being processed). */
197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UChar* guest_code;
198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The guest address corresponding to guest_code[0]. */
200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Addr64 guest_RIP_bbstart;
201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The guest address for the instruction currently being
203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   translated. */
204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Addr64 guest_RIP_curr_instr;
205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The IRSB* into which we're generating code. */
207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRSB* irsb;
208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* For ensuring that %rip-relative addressing is done right.  A read
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   of %rip generates the address of the next instruction.  It may be
211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   that we don't conveniently know that inside disAMode().  For sanity
212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   checking, if the next insn %rip is needed, we make a guess at what
213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   it is, record that guess here, and set the accompanying Bool to
214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   indicate that -- after this insn's decode is finished -- that guess
215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   needs to be checked.  */
216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* At the start of each insn decode, is set to (0, False).
218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   After the decode, if _mustcheck is now True, _assumed is
219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   checked. */
220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Addr64 guest_RIP_next_assumed;
222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool   guest_RIP_next_mustcheck;
223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Helpers for constructing IR.                         ---*/
227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate a new temporary of the given type. */
230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRTemp newTemp ( IRType ty )
231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(isPlausibleIRType(ty));
233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return newIRTemp( irsb->tyenv, ty );
234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Add a statement to the list held by "irsb". */
237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void stmt ( IRStmt* st )
238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addStmtToIRSB( irsb, st );
240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate a statement "dst := e". */
243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void assign ( IRTemp dst, IRExpr* e )
244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_WrTmp(dst, e) );
246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* unop ( IROp op, IRExpr* a )
249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Unop(op, a);
251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* binop ( IROp op, IRExpr* a1, IRExpr* a2 )
254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Binop(op, a1, a2);
256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* triop ( IROp op, IRExpr* a1, IRExpr* a2, IRExpr* a3 )
259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Triop(op, a1, a2, a3);
261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mkexpr ( IRTemp tmp )
264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_RdTmp(tmp);
266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mkU8 ( ULong i )
269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(i < 256);
271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Const(IRConst_U8( (UChar)i ));
272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mkU16 ( ULong i )
275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(i < 0x10000ULL);
277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Const(IRConst_U16( (UShort)i ));
278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mkU32 ( ULong i )
281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(i < 0x100000000ULL);
283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Const(IRConst_U32( (UInt)i ));
284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mkU64 ( ULong i )
287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Const(IRConst_U64(i));
289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mkU ( IRType ty, ULong i )
292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (ty) {
294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I8:  return mkU8(i);
295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I16: return mkU16(i);
296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I32: return mkU32(i);
297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I64: return mkU64(i);
298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vpanic("mkU(amd64)");
299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void storeLE ( IRExpr* addr, IRExpr* data )
303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Store(Iend_LE, addr, data) );
305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* loadLE ( IRType ty, IRExpr* addr )
308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Load(Iend_LE, ty, addr);
310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IROp mkSizedOp ( IRType ty, IROp op8 )
313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(op8 == Iop_Add8 || op8 == Iop_Sub8
315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || op8 == Iop_Mul8
316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || op8 == Iop_Or8 || op8 == Iop_And8 || op8 == Iop_Xor8
317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || op8 == Iop_Shl8 || op8 == Iop_Shr8 || op8 == Iop_Sar8
318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || op8 == Iop_CmpEQ8 || op8 == Iop_CmpNE8
319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || op8 == Iop_CasCmpNE8
320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || op8 == Iop_Not8 );
321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (ty) {
322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I8:  return 0 +op8;
323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I16: return 1 +op8;
324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I32: return 2 +op8;
325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I64: return 3 +op8;
326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vpanic("mkSizedOp(amd64)");
327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRExpr* doScalarWidening ( Int szSmall, Int szBig, Bool signd, IRExpr* src )
332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (szSmall == 1 && szBig == 4) {
334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return unop(signd ? Iop_8Sto32 : Iop_8Uto32, src);
335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (szSmall == 1 && szBig == 2) {
337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return unop(signd ? Iop_8Sto16 : Iop_8Uto16, src);
338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (szSmall == 2 && szBig == 4) {
340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return unop(signd ? Iop_16Sto32 : Iop_16Uto32, src);
341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (szSmall == 1 && szBig == 8 && !signd) {
343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return unop(Iop_8Uto64, src);
344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (szSmall == 1 && szBig == 8 && signd) {
346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return unop(Iop_8Sto64, src);
347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (szSmall == 2 && szBig == 8 && !signd) {
349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return unop(Iop_16Uto64, src);
350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (szSmall == 2 && szBig == 8 && signd) {
352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return unop(Iop_16Sto64, src);
353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vpanic("doScalarWidening(amd64)");
355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Debugging output                                     ---*/
361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Bomb out if we can't handle something. */
364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__ ((noreturn))
365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void unimplemented ( HChar* str )
366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("amd64toIR: unimplemented feature\n");
368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vpanic(str);
369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DIP(format, args...)           \
372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vex_traceflags & VEX_TRACE_FE)  \
373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf(format, ## args)
374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DIS(buf, format, args...)      \
376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vex_traceflags & VEX_TRACE_FE)  \
377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_sprintf(buf, format, ## args)
378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Offsets of various parts of the amd64 guest state.   ---*/
382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_RAX       offsetof(VexGuestAMD64State,guest_RAX)
385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_RBX       offsetof(VexGuestAMD64State,guest_RBX)
386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_RCX       offsetof(VexGuestAMD64State,guest_RCX)
387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_RDX       offsetof(VexGuestAMD64State,guest_RDX)
388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_RSP       offsetof(VexGuestAMD64State,guest_RSP)
389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_RBP       offsetof(VexGuestAMD64State,guest_RBP)
390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_RSI       offsetof(VexGuestAMD64State,guest_RSI)
391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_RDI       offsetof(VexGuestAMD64State,guest_RDI)
392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_R8        offsetof(VexGuestAMD64State,guest_R8)
393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_R9        offsetof(VexGuestAMD64State,guest_R9)
394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_R10       offsetof(VexGuestAMD64State,guest_R10)
395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_R11       offsetof(VexGuestAMD64State,guest_R11)
396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_R12       offsetof(VexGuestAMD64State,guest_R12)
397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_R13       offsetof(VexGuestAMD64State,guest_R13)
398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_R14       offsetof(VexGuestAMD64State,guest_R14)
399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_R15       offsetof(VexGuestAMD64State,guest_R15)
400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_RIP       offsetof(VexGuestAMD64State,guest_RIP)
402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_FS_ZERO   offsetof(VexGuestAMD64State,guest_FS_ZERO)
404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_GS_0x60   offsetof(VexGuestAMD64State,guest_GS_0x60)
405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_CC_OP     offsetof(VexGuestAMD64State,guest_CC_OP)
407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_CC_DEP1   offsetof(VexGuestAMD64State,guest_CC_DEP1)
408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_CC_DEP2   offsetof(VexGuestAMD64State,guest_CC_DEP2)
409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_CC_NDEP   offsetof(VexGuestAMD64State,guest_CC_NDEP)
410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_FPREGS    offsetof(VexGuestAMD64State,guest_FPREG[0])
412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_FPTAGS    offsetof(VexGuestAMD64State,guest_FPTAG[0])
413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_DFLAG     offsetof(VexGuestAMD64State,guest_DFLAG)
414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_ACFLAG    offsetof(VexGuestAMD64State,guest_ACFLAG)
415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_IDFLAG    offsetof(VexGuestAMD64State,guest_IDFLAG)
416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_FTOP      offsetof(VexGuestAMD64State,guest_FTOP)
417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_FC3210    offsetof(VexGuestAMD64State,guest_FC3210)
418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_FPROUND   offsetof(VexGuestAMD64State,guest_FPROUND)
419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_SSEROUND  offsetof(VexGuestAMD64State,guest_SSEROUND)
421663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define OFFB_YMM0      offsetof(VexGuestAMD64State,guest_YMM0)
422663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define OFFB_YMM1      offsetof(VexGuestAMD64State,guest_YMM1)
423663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define OFFB_YMM2      offsetof(VexGuestAMD64State,guest_YMM2)
424663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define OFFB_YMM3      offsetof(VexGuestAMD64State,guest_YMM3)
425663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define OFFB_YMM4      offsetof(VexGuestAMD64State,guest_YMM4)
426663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define OFFB_YMM5      offsetof(VexGuestAMD64State,guest_YMM5)
427663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define OFFB_YMM6      offsetof(VexGuestAMD64State,guest_YMM6)
428663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define OFFB_YMM7      offsetof(VexGuestAMD64State,guest_YMM7)
429663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define OFFB_YMM8      offsetof(VexGuestAMD64State,guest_YMM8)
430663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define OFFB_YMM9      offsetof(VexGuestAMD64State,guest_YMM9)
431663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define OFFB_YMM10     offsetof(VexGuestAMD64State,guest_YMM10)
432663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define OFFB_YMM11     offsetof(VexGuestAMD64State,guest_YMM11)
433663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define OFFB_YMM12     offsetof(VexGuestAMD64State,guest_YMM12)
434663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define OFFB_YMM13     offsetof(VexGuestAMD64State,guest_YMM13)
435663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define OFFB_YMM14     offsetof(VexGuestAMD64State,guest_YMM14)
436663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define OFFB_YMM15     offsetof(VexGuestAMD64State,guest_YMM15)
437663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define OFFB_YMM16     offsetof(VexGuestAMD64State,guest_YMM16)
438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_EMWARN    offsetof(VexGuestAMD64State,guest_EMWARN)
440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_TISTART   offsetof(VexGuestAMD64State,guest_TISTART)
441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_TILEN     offsetof(VexGuestAMD64State,guest_TILEN)
442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_NRADDR    offsetof(VexGuestAMD64State,guest_NRADDR)
444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Helper bits and pieces for deconstructing the        ---*/
448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- amd64 insn stream.                                   ---*/
449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This is the AMD64 register encoding -- integer regs. */
452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_RAX 0
453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_RCX 1
454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_RDX 2
455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_RBX 3
456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_RSP 4
457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_RBP 5
458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_RSI 6
459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_RDI 7
460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_R8  8
461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_R9  9
462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_R10 10
463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_R11 11
464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_R12 12
465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_R13 13
466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_R14 14
467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_R15 15
468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This is the Intel register encoding -- segment regs. */
470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ES 0
471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_CS 1
472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SS 2
473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_DS 3
474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_FS 4
475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_GS 5
476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Various simple conversions */
479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong extend_s_8to64 ( UChar x )
481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (ULong)((((Long)x) << 56) >> 56);
483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong extend_s_16to64 ( UShort x )
486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (ULong)((((Long)x) << 48) >> 48);
488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong extend_s_32to64 ( UInt x )
491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (ULong)((((Long)x) << 32) >> 32);
493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Figure out whether the mod and rm parts of a modRM byte refer to a
496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   register or memory.  If so, the byte will have the form 11XXXYYY,
497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   where YYY is the register number. */
498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browninline
499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool epartIsReg ( UChar mod_reg_rm )
500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toBool(0xC0 == (mod_reg_rm & 0xC0));
502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Extract the 'g' field from a modRM byte.  This only produces 3
505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bits, which is not a complete register number.  You should avoid
506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   this function if at all possible. */
507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browninline
508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int gregLO3ofRM ( UChar mod_reg_rm )
509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (Int)( (mod_reg_rm >> 3) & 7 );
511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Ditto the 'e' field of a modRM byte. */
514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browninline
515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int eregLO3ofRM ( UChar mod_reg_rm )
516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (Int)(mod_reg_rm & 0x7);
518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Get a 8/16/32-bit unsigned value out of the insn stream. */
521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
522663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic inline UChar getUChar ( Long delta )
523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar v = guest_code[delta+0];
525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return v;
526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt getUDisp16 ( Long delta )
529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt v = guest_code[delta+1]; v <<= 8;
531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   v |= guest_code[delta+0];
532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return v & 0xFFFF;
533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//.. static UInt getUDisp ( Int size, Long delta )
536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//.. {
537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..    switch (size) {
538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..       case 4: return getUDisp32(delta);
539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..       case 2: return getUDisp16(delta);
540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..       case 1: return getUChar(delta);
541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..       default: vpanic("getUDisp(x86)");
542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..    }
543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..    return 0; /*notreached*/
544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//.. }
545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Get a byte value out of the insn stream and sign-extend to 64
548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bits. */
549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Long getSDisp8 ( Long delta )
550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return extend_s_8to64( guest_code[delta] );
552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Get a 16-bit value out of the insn stream and sign-extend to 64
555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bits. */
556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Long getSDisp16 ( Long delta )
557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt v = guest_code[delta+1]; v <<= 8;
559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   v |= guest_code[delta+0];
560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return extend_s_16to64( (UShort)v );
561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Get a 32-bit value out of the insn stream and sign-extend to 64
564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bits. */
565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Long getSDisp32 ( Long delta )
566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt v = guest_code[delta+3]; v <<= 8;
568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   v |= guest_code[delta+2]; v <<= 8;
569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   v |= guest_code[delta+1]; v <<= 8;
570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   v |= guest_code[delta+0];
571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return extend_s_32to64( v );
572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Get a 64-bit value out of the insn stream. */
575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Long getDisp64 ( Long delta )
576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong v = 0;
578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   v |= guest_code[delta+7]; v <<= 8;
579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   v |= guest_code[delta+6]; v <<= 8;
580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   v |= guest_code[delta+5]; v <<= 8;
581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   v |= guest_code[delta+4]; v <<= 8;
582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   v |= guest_code[delta+3]; v <<= 8;
583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   v |= guest_code[delta+2]; v <<= 8;
584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   v |= guest_code[delta+1]; v <<= 8;
585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   v |= guest_code[delta+0];
586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return v;
587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Note: because AMD64 doesn't allow 64-bit literals, it is an error
590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if this is called with size==8.  Should not happen. */
591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Long getSDisp ( Int size, Long delta )
592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (size) {
594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 4: return getSDisp32(delta);
595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2: return getSDisp16(delta);
596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 1: return getSDisp8(delta);
597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vpanic("getSDisp(amd64)");
598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong mkSizeMask ( Int sz )
602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (sz) {
604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 1: return 0x00000000000000FFULL;
605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2: return 0x000000000000FFFFULL;
606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 4: return 0x00000000FFFFFFFFULL;
607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 8: return 0xFFFFFFFFFFFFFFFFULL;
608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vpanic("mkSzMask(amd64)");
609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int imin ( Int a, Int b )
613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (a < b) ? a : b;
615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRType szToITy ( Int n )
618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (n) {
620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 1: return Ity_I8;
621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2: return Ity_I16;
622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 4: return Ity_I32;
623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 8: return Ity_I64;
624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vex_printf("\nszToITy(%d)\n", n);
625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vpanic("szToITy(amd64)");
626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- For dealing with prefixes.                           ---*/
632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The idea is to pass around an int holding a bitmask summarising
635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   info from the prefixes seen on the current instruction, including
636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   info from the REX byte.  This info is used in various places, but
637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   most especially when making sense of register fields in
638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   instructions.
639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
640663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   The top 8 bits of the prefix are 0x55, just as a hacky way to
641663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   ensure it really is a valid prefix.
642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Things you can safely assume about a well-formed prefix:
644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * at most one segment-override bit (CS,DS,ES,FS,GS,SS) is set.
645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * if REX is not present then REXW,REXR,REXX,REXB will read
646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     as zero.
647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * F2 and F3 will not both be 1.
648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef UInt  Prefix;
651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
652663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define PFX_ASO    (1<<0)    /* address-size override present (0x67) */
653663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define PFX_66     (1<<1)    /* operand-size override-to-16 present (0x66) */
654663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define PFX_REX    (1<<2)    /* REX byte present (0x40 to 0x4F) */
655663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define PFX_REXW   (1<<3)    /* REX W bit, if REX present, else 0 */
656663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define PFX_REXR   (1<<4)    /* REX R bit, if REX present, else 0 */
657663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define PFX_REXX   (1<<5)    /* REX X bit, if REX present, else 0 */
658663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define PFX_REXB   (1<<6)    /* REX B bit, if REX present, else 0 */
659663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define PFX_LOCK   (1<<7)    /* bus LOCK prefix present (0xF0) */
660663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define PFX_F2     (1<<8)    /* REP/REPE/REPZ prefix present (0xF2) */
661663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define PFX_F3     (1<<9)    /* REPNE/REPNZ prefix present (0xF3) */
662663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define PFX_CS     (1<<10)   /* CS segment prefix present (0x2E) */
663663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define PFX_DS     (1<<11)   /* DS segment prefix present (0x3E) */
664663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define PFX_ES     (1<<12)   /* ES segment prefix present (0x26) */
665663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define PFX_FS     (1<<13)   /* FS segment prefix present (0x64) */
666663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define PFX_GS     (1<<14)   /* GS segment prefix present (0x65) */
667663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define PFX_SS     (1<<15)   /* SS segment prefix present (0x36) */
668663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define PFX_VEX    (1<<16)   /* VEX prefix present (0xC4 or 0xC5) */
669663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define PFX_VEXL   (1<<17)   /* VEX L bit, if VEX present, else 0 */
670663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* The extra register field VEX.vvvv is encoded (after not-ing it) as
671663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   PFX_VEXnV3 .. PFX_VEXnV0, so these must occupy adjacent bit
672663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   positions. */
673663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define PFX_VEXnV0 (1<<18)   /* ~VEX vvvv[0], if VEX present, else 0 */
674663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define PFX_VEXnV1 (1<<19)   /* ~VEX vvvv[1], if VEX present, else 0 */
675663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define PFX_VEXnV2 (1<<20)   /* ~VEX vvvv[2], if VEX present, else 0 */
676663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define PFX_VEXnV3 (1<<21)   /* ~VEX vvvv[3], if VEX present, else 0 */
677663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
678663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
679663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define PFX_EMPTY 0x55000000
680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool IS_VALID_PFX ( Prefix pfx ) {
682663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return toBool((pfx & 0xFF000000) == PFX_EMPTY);
683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool haveREX ( Prefix pfx ) {
686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toBool(pfx & PFX_REX);
687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int getRexW ( Prefix pfx ) {
690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (pfx & PFX_REXW) ? 1 : 0;
691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int getRexR ( Prefix pfx ) {
693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (pfx & PFX_REXR) ? 1 : 0;
694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int getRexX ( Prefix pfx ) {
696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (pfx & PFX_REXX) ? 1 : 0;
697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int getRexB ( Prefix pfx ) {
699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (pfx & PFX_REXB) ? 1 : 0;
700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Check a prefix doesn't have F2 or F3 set in it, since usually that
703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   completely changes what instruction it really is. */
704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool haveF2orF3 ( Prefix pfx ) {
705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toBool((pfx & (PFX_F2|PFX_F3)) > 0);
706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool haveF2 ( Prefix pfx ) {
708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toBool((pfx & PFX_F2) > 0);
709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool haveF3 ( Prefix pfx ) {
711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toBool((pfx & PFX_F3) > 0);
712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool have66 ( Prefix pfx ) {
715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toBool((pfx & PFX_66) > 0);
716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool haveASO ( Prefix pfx ) {
718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toBool((pfx & PFX_ASO) > 0);
719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Return True iff pfx has 66 set and F2 and F3 clear */
722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool have66noF2noF3 ( Prefix pfx )
723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return
725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     toBool((pfx & (PFX_66|PFX_F2|PFX_F3)) == PFX_66);
726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Return True iff pfx has F2 set and 66 and F3 clear */
729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool haveF2no66noF3 ( Prefix pfx )
730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return
732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     toBool((pfx & (PFX_66|PFX_F2|PFX_F3)) == PFX_F2);
733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Return True iff pfx has F3 set and 66 and F2 clear */
736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool haveF3no66noF2 ( Prefix pfx )
737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return
739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     toBool((pfx & (PFX_66|PFX_F2|PFX_F3)) == PFX_F3);
740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Return True iff pfx has F3 set and F2 clear */
743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool haveF3noF2 ( Prefix pfx )
744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return
746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     toBool((pfx & (PFX_F2|PFX_F3)) == PFX_F3);
747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
749f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root/* Return True iff pfx has F2 set and F3 clear */
750f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Rootstatic Bool haveF2noF3 ( Prefix pfx )
751f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root{
752f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root  return
753f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root     toBool((pfx & (PFX_F2|PFX_F3)) == PFX_F2);
754f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root}
755f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Return True iff pfx has 66, F2 and F3 clear */
757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool haveNo66noF2noF3 ( Prefix pfx )
758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return
760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     toBool((pfx & (PFX_66|PFX_F2|PFX_F3)) == 0);
761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Return True iff pfx has any of 66, F2 and F3 set */
764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool have66orF2orF3 ( Prefix pfx )
765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return toBool( ! haveNo66noF2noF3(pfx) );
767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Return True iff pfx has 66 or F2 set */
770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool have66orF2 ( Prefix pfx )
771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toBool((pfx & (PFX_66|PFX_F2)) > 0);
773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Clear all the segment-override bits in a prefix. */
776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Prefix clearSegBits ( Prefix p )
777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return
779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p & ~(PFX_CS | PFX_DS | PFX_ES | PFX_FS | PFX_GS | PFX_SS);
780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
782663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Get the (inverted, hence back to "normal") VEX.vvvv field. */
783663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic UInt getVexNvvvv ( Prefix pfx ) {
784663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt r = (UInt)pfx;
785663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   r /= (UInt)PFX_VEXnV0; /* pray this turns into a shift */
786663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return r & 0xF;
787663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
788663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
789663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Bool haveVEX ( Prefix pfx ) {
790663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return toBool(pfx & PFX_VEX);
791663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
792663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
793663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Int getVexL ( Prefix pfx ) {
794663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return (pfx & PFX_VEXL) ? 1 : 0;
795663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
796663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
797663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
798663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*------------------------------------------------------------*/
799663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*--- For dealing with escapes                             ---*/
800663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*------------------------------------------------------------*/
801663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
802663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
803663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Escapes come after the prefixes, but before the primary opcode
804663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   byte.  They escape the primary opcode byte into a bigger space.
805663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   The 0xF0000000 isn't significant, except so as to make it not
806663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   overlap valid Prefix values, for sanity checking.
807663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng*/
808663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
809663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengtypedef
810663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   enum {
811663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ESC_NONE=0xF0000000, // none
812663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ESC_0F,              // 0F
813663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ESC_0F38,            // 0F 38
814663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ESC_0F3A             // 0F 3A
815663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
816663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Escape;
817663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- For dealing with integer registers                   ---*/
821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This is somewhat complex.  The rules are:
824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   For 64, 32 and 16 bit register references, the e or g fields in the
826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   modrm bytes supply the low 3 bits of the register number.  The
827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   fourth (most-significant) bit of the register number is supplied by
828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the REX byte, if it is present; else that bit is taken to be zero.
829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The REX.R bit supplies the high bit corresponding to the g register
831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   field, and the REX.B bit supplies the high bit corresponding to the
832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   e register field (when the mod part of modrm indicates that modrm's
833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   e component refers to a register and not to memory).
834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The REX.X bit supplies a high register bit for certain registers
836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   in SIB address modes, and is generally rarely used.
837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   For 8 bit register references, the presence of the REX byte itself
839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   has significance.  If there is no REX present, then the 3-bit
840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   number extracted from the modrm e or g field is treated as an index
841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   into the sequence %al %cl %dl %bl %ah %ch %dh %bh -- that is, the
842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   old x86 encoding scheme.
843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   But if there is a REX present, the register reference is
845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   interpreted in the same way as for 64/32/16-bit references: a high
846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bit is extracted from REX, giving a 4-bit number, and the denoted
847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   register is the lowest 8 bits of the 16 integer registers denoted
848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   by the number.  In particular, values 3 through 7 of this sequence
849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   do not refer to %ah %ch %dh %bh but instead to the lowest 8 bits of
850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   %rsp %rbp %rsi %rdi.
851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The REX.W bit has no bearing at all on register numbers.  Instead
853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   its presence indicates that the operand size is to be overridden
854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   from its default value (32 bits) to 64 bits instead.  This is in
855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the same fashion that an 0x66 prefix indicates the operand size is
856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   to be overridden from 32 bits down to 16 bits.  When both REX.W and
857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   0x66 are present there is a conflict, and REX.W takes precedence.
858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Rather than try to handle this complexity using a single huge
860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   function, several smaller ones are provided.  The aim is to make it
861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   as difficult as possible to screw up register decoding in a subtle
862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and hard-to-track-down way.
863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Because these routines fish around in the host's memory (that is,
865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   in the guest state area) for sub-parts of guest registers, their
866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   correctness depends on the host's endianness.  So far these
867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   routines only work for little-endian hosts.  Those for which
868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   endianness is important have assertions to ensure sanity.
869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* About the simplest question you can ask: where do the 64-bit
873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   integer registers live (in the guest state) ? */
874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int integerGuestReg64Offset ( UInt reg )
876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (reg) {
878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case R_RAX: return OFFB_RAX;
879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case R_RCX: return OFFB_RCX;
880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case R_RDX: return OFFB_RDX;
881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case R_RBX: return OFFB_RBX;
882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case R_RSP: return OFFB_RSP;
883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case R_RBP: return OFFB_RBP;
884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case R_RSI: return OFFB_RSI;
885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case R_RDI: return OFFB_RDI;
886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case R_R8:  return OFFB_R8;
887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case R_R9:  return OFFB_R9;
888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case R_R10: return OFFB_R10;
889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case R_R11: return OFFB_R11;
890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case R_R12: return OFFB_R12;
891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case R_R13: return OFFB_R13;
892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case R_R14: return OFFB_R14;
893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case R_R15: return OFFB_R15;
894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vpanic("integerGuestReg64Offset(amd64)");
895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Produce the name of an integer register, for printing purposes.
900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   reg is a number in the range 0 .. 15 that has been generated from a
901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   3-bit reg-field number and a REX extension bit.  irregular denotes
902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the case where sz==1 and no REX byte is present. */
903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHChar* nameIReg ( Int sz, UInt reg, Bool irregular )
906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   static HChar* ireg64_names[16]
908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     = { "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi",
909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         "%r8",  "%r9",  "%r10", "%r11", "%r12", "%r13", "%r14", "%r15" };
910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   static HChar* ireg32_names[16]
911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     = { "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi",
912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         "%r8d", "%r9d", "%r10d","%r11d","%r12d","%r13d","%r14d","%r15d" };
913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   static HChar* ireg16_names[16]
914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     = { "%ax",  "%cx",  "%dx",  "%bx",  "%sp",  "%bp",  "%si",  "%di",
915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         "%r8w", "%r9w", "%r10w","%r11w","%r12w","%r13w","%r14w","%r15w" };
916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   static HChar* ireg8_names[16]
917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     = { "%al",  "%cl",  "%dl",  "%bl",  "%spl", "%bpl", "%sil", "%dil",
918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         "%r8b", "%r9b", "%r10b","%r11b","%r12b","%r13b","%r14b","%r15b" };
919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   static HChar* ireg8_irregular[8]
920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     = { "%al", "%cl", "%dl", "%bl", "%ah", "%ch", "%dh", "%bh" };
921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(reg < 16);
923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (sz == 1) {
924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (irregular)
925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(reg < 8);
926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(irregular == False);
928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (sz) {
931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 8: return ireg64_names[reg];
932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 4: return ireg32_names[reg];
933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2: return ireg16_names[reg];
934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 1: if (irregular) {
935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 return ireg8_irregular[reg];
936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              } else {
937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 return ireg8_names[reg];
938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              }
939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vpanic("nameIReg(amd64)");
940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Using the same argument conventions as nameIReg, produce the
944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   guest state offset of an integer register. */
945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt offsetIReg ( Int sz, UInt reg, Bool irregular )
948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(reg < 16);
950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (sz == 1) {
951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (irregular)
952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(reg < 8);
953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(irregular == False);
955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Deal with irregular case -- sz==1 and no REX present */
958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (sz == 1 && irregular) {
959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (reg) {
960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case R_RSP: return 1+ OFFB_RAX;
961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case R_RBP: return 1+ OFFB_RCX;
962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case R_RSI: return 1+ OFFB_RDX;
963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case R_RDI: return 1+ OFFB_RBX;
964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:    break; /* use the normal case */
965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Normal case */
969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return integerGuestReg64Offset(reg);
970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Read the %CL register :: Ity_I8, for shift/rotate operations. */
974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* getIRegCL ( void )
976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(!host_is_bigendian);
978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Get( OFFB_RCX, Ity_I8 );
979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Write to the %AH register. */
983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void putIRegAH ( IRExpr* e )
985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(!host_is_bigendian);
987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_RAX+1, e ) );
989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Read/write various widths of %RAX, as it has various
993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   special-purpose uses. */
994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HChar* nameIRegRAX ( Int sz )
996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (sz) {
998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 1: return "%al";
999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2: return "%ax";
1000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 4: return "%eax";
1001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 8: return "%rax";
1002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vpanic("nameIRegRAX(amd64)");
1003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* getIRegRAX ( Int sz )
1007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(!host_is_bigendian);
1009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (sz) {
1010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 1: return IRExpr_Get( OFFB_RAX, Ity_I8 );
1011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2: return IRExpr_Get( OFFB_RAX, Ity_I16 );
1012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 4: return unop(Iop_64to32, IRExpr_Get( OFFB_RAX, Ity_I64 ));
1013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 8: return IRExpr_Get( OFFB_RAX, Ity_I64 );
1014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vpanic("getIRegRAX(amd64)");
1015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void putIRegRAX ( Int sz, IRExpr* e )
1019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = typeOfIRExpr(irsb->tyenv, e);
1021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(!host_is_bigendian);
1022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (sz) {
1023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 8: vassert(ty == Ity_I64);
1024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              stmt( IRStmt_Put( OFFB_RAX, e ));
1025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              break;
1026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 4: vassert(ty == Ity_I32);
1027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              stmt( IRStmt_Put( OFFB_RAX, unop(Iop_32Uto64,e) ));
1028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              break;
1029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2: vassert(ty == Ity_I16);
1030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              stmt( IRStmt_Put( OFFB_RAX, e ));
1031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              break;
1032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 1: vassert(ty == Ity_I8);
1033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              stmt( IRStmt_Put( OFFB_RAX, e ));
1034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              break;
1035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vpanic("putIRegRAX(amd64)");
1036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Read/write various widths of %RDX, as it has various
1041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   special-purpose uses. */
1042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HChar* nameIRegRDX ( Int sz )
1044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (sz) {
1046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 1: return "%dl";
1047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2: return "%dx";
1048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 4: return "%edx";
1049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 8: return "%rdx";
1050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vpanic("nameIRegRDX(amd64)");
1051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* getIRegRDX ( Int sz )
1055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(!host_is_bigendian);
1057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (sz) {
1058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 1: return IRExpr_Get( OFFB_RDX, Ity_I8 );
1059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2: return IRExpr_Get( OFFB_RDX, Ity_I16 );
1060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 4: return unop(Iop_64to32, IRExpr_Get( OFFB_RDX, Ity_I64 ));
1061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 8: return IRExpr_Get( OFFB_RDX, Ity_I64 );
1062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vpanic("getIRegRDX(amd64)");
1063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void putIRegRDX ( Int sz, IRExpr* e )
1067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(!host_is_bigendian);
1069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv, e) == szToITy(sz));
1070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (sz) {
1071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 8: stmt( IRStmt_Put( OFFB_RDX, e ));
1072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              break;
1073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 4: stmt( IRStmt_Put( OFFB_RDX, unop(Iop_32Uto64,e) ));
1074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              break;
1075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2: stmt( IRStmt_Put( OFFB_RDX, e ));
1076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              break;
1077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 1: stmt( IRStmt_Put( OFFB_RDX, e ));
1078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              break;
1079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vpanic("putIRegRDX(amd64)");
1080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Simplistic functions to deal with the integer registers as a
1085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   straightforward bank of 16 64-bit regs. */
1086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* getIReg64 ( UInt regno )
1088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Get( integerGuestReg64Offset(regno),
1090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      Ity_I64 );
1091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void putIReg64 ( UInt regno, IRExpr* e )
1094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv,e) == Ity_I64);
1096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( integerGuestReg64Offset(regno), e ) );
1097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HChar* nameIReg64 ( UInt regno )
1100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return nameIReg( 8, regno, False );
1102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Simplistic functions to deal with the lower halves of integer
1106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   registers as a straightforward bank of 16 32-bit regs. */
1107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* getIReg32 ( UInt regno )
1109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(!host_is_bigendian);
1111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return unop(Iop_64to32,
1112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRExpr_Get( integerGuestReg64Offset(regno),
1113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           Ity_I64 ));
1114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void putIReg32 ( UInt regno, IRExpr* e )
1117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv,e) == Ity_I32);
1119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( integerGuestReg64Offset(regno),
1120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     unop(Iop_32Uto64,e) ) );
1121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HChar* nameIReg32 ( UInt regno )
1124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return nameIReg( 4, regno, False );
1126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Simplistic functions to deal with the lower quarters of integer
1130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   registers as a straightforward bank of 16 16-bit regs. */
1131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* getIReg16 ( UInt regno )
1133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(!host_is_bigendian);
1135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Get( integerGuestReg64Offset(regno),
1136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      Ity_I16 );
1137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1139b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic void putIReg16 ( UInt regno, IRExpr* e )
1140b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
1141b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   vassert(typeOfIRExpr(irsb->tyenv,e) == Ity_I16);
1142b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   stmt( IRStmt_Put( integerGuestReg64Offset(regno),
1143b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     unop(Iop_16Uto64,e) ) );
1144b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
1145b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HChar* nameIReg16 ( UInt regno )
1147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return nameIReg( 2, regno, False );
1149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Sometimes what we know is a 3-bit register number, a REX byte, and
1153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   which field of the REX byte is to be used to extend to a 4-bit
1154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   number.  These functions cater for that situation.
1155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* getIReg64rexX ( Prefix pfx, UInt lo3bits )
1157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(lo3bits < 8);
1159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(IS_VALID_PFX(pfx));
1160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return getIReg64( lo3bits | (getRexX(pfx) << 3) );
1161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HChar* nameIReg64rexX ( Prefix pfx, UInt lo3bits )
1164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(lo3bits < 8);
1166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(IS_VALID_PFX(pfx));
1167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return nameIReg( 8, lo3bits | (getRexX(pfx) << 3), False );
1168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HChar* nameIRegRexB ( Int sz, Prefix pfx, UInt lo3bits )
1171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(lo3bits < 8);
1173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(IS_VALID_PFX(pfx));
1174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(sz == 8 || sz == 4 || sz == 2 || sz == 1);
1175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return nameIReg( sz, lo3bits | (getRexB(pfx) << 3),
1176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        toBool(sz==1 && !haveREX(pfx)) );
1177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* getIRegRexB ( Int sz, Prefix pfx, UInt lo3bits )
1180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(lo3bits < 8);
1182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(IS_VALID_PFX(pfx));
1183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(sz == 8 || sz == 4 || sz == 2 || sz == 1);
1184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (sz == 4) {
1185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      sz = 8;
1186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return unop(Iop_64to32,
1187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  IRExpr_Get(
1188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     offsetIReg( sz, lo3bits | (getRexB(pfx) << 3),
1189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     toBool(sz==1 && !haveREX(pfx)) ),
1190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     szToITy(sz)
1191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 )
1192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             );
1193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return IRExpr_Get(
1195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                offsetIReg( sz, lo3bits | (getRexB(pfx) << 3),
1196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                toBool(sz==1 && !haveREX(pfx)) ),
1197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                szToITy(sz)
1198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             );
1199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void putIRegRexB ( Int sz, Prefix pfx, UInt lo3bits, IRExpr* e )
1203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(lo3bits < 8);
1205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(IS_VALID_PFX(pfx));
1206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(sz == 8 || sz == 4 || sz == 2 || sz == 1);
1207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv, e) == szToITy(sz));
1208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put(
1209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            offsetIReg( sz, lo3bits | (getRexB(pfx) << 3),
1210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            toBool(sz==1 && !haveREX(pfx)) ),
1211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sz==4 ? unop(Iop_32Uto64,e) : e
1212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ));
1213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Functions for getting register numbers from modrm bytes and REX
1217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   when we don't have to consider the complexities of integer subreg
1218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   accesses.
1219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Extract the g reg field from a modRM byte, and augment it using the
1221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   REX.R bit from the supplied REX byte.  The R bit usually is
1222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   associated with the g register field.
1223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt gregOfRexRM ( Prefix pfx, UChar mod_reg_rm )
1225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int reg = (Int)( (mod_reg_rm >> 3) & 7 );
1227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   reg += (pfx & PFX_REXR) ? 8 : 0;
1228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return reg;
1229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Extract the e reg field from a modRM byte, and augment it using the
1232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   REX.B bit from the supplied REX byte.  The B bit usually is
1233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   associated with the e register field (when modrm indicates e is a
1234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   register, that is).
1235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt eregOfRexRM ( Prefix pfx, UChar mod_reg_rm )
1237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int rm;
1239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(epartIsReg(mod_reg_rm));
1240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   rm = (Int)(mod_reg_rm & 0x7);
1241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   rm += (pfx & PFX_REXB) ? 8 : 0;
1242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return rm;
1243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* General functions for dealing with integer register access. */
1247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Produce the guest state offset for a reference to the 'g' register
1249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   field in a modrm byte, taking into account REX (or its absence),
1250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and the size of the access.
1251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt offsetIRegG ( Int sz, Prefix pfx, UChar mod_reg_rm )
1253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt reg;
1255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(!host_is_bigendian);
1256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(IS_VALID_PFX(pfx));
1257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(sz == 8 || sz == 4 || sz == 2 || sz == 1);
1258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   reg = gregOfRexRM( pfx, mod_reg_rm );
1259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return offsetIReg( sz, reg, toBool(sz == 1 && !haveREX(pfx)) );
1260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRExpr* getIRegG ( Int sz, Prefix pfx, UChar mod_reg_rm )
1264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (sz == 4) {
1266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      sz = 8;
1267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return unop(Iop_64to32,
1268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  IRExpr_Get( offsetIRegG( sz, pfx, mod_reg_rm ),
1269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              szToITy(sz) ));
1270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return IRExpr_Get( offsetIRegG( sz, pfx, mod_reg_rm ),
1272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         szToITy(sz) );
1273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid putIRegG ( Int sz, Prefix pfx, UChar mod_reg_rm, IRExpr* e )
1278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv,e) == szToITy(sz));
1280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (sz == 4) {
1281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      e = unop(Iop_32Uto64,e);
1282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( offsetIRegG( sz, pfx, mod_reg_rm ), e ) );
1284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHChar* nameIRegG ( Int sz, Prefix pfx, UChar mod_reg_rm )
1288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return nameIReg( sz, gregOfRexRM(pfx,mod_reg_rm),
1290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        toBool(sz==1 && !haveREX(pfx)) );
1291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Produce the guest state offset for a reference to the 'e' register
1295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   field in a modrm byte, taking into account REX (or its absence),
1296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and the size of the access.  eregOfRexRM will assert if mod_reg_rm
1297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   denotes a memory access rather than a register access.
1298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt offsetIRegE ( Int sz, Prefix pfx, UChar mod_reg_rm )
1300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt reg;
1302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(!host_is_bigendian);
1303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(IS_VALID_PFX(pfx));
1304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(sz == 8 || sz == 4 || sz == 2 || sz == 1);
1305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   reg = eregOfRexRM( pfx, mod_reg_rm );
1306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return offsetIReg( sz, reg, toBool(sz == 1 && !haveREX(pfx)) );
1307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRExpr* getIRegE ( Int sz, Prefix pfx, UChar mod_reg_rm )
1311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (sz == 4) {
1313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      sz = 8;
1314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return unop(Iop_64to32,
1315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  IRExpr_Get( offsetIRegE( sz, pfx, mod_reg_rm ),
1316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              szToITy(sz) ));
1317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return IRExpr_Get( offsetIRegE( sz, pfx, mod_reg_rm ),
1319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         szToITy(sz) );
1320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid putIRegE ( Int sz, Prefix pfx, UChar mod_reg_rm, IRExpr* e )
1325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv,e) == szToITy(sz));
1327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (sz == 4) {
1328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      e = unop(Iop_32Uto64,e);
1329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( offsetIRegE( sz, pfx, mod_reg_rm ), e ) );
1331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHChar* nameIRegE ( Int sz, Prefix pfx, UChar mod_reg_rm )
1335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return nameIReg( sz, eregOfRexRM(pfx,mod_reg_rm),
1337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        toBool(sz==1 && !haveREX(pfx)) );
1338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- For dealing with XMM registers                       ---*/
1343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1345663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Int ymmGuestRegOffset ( UInt ymmreg )
1346663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
1347663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (ymmreg) {
1348663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0:  return OFFB_YMM0;
1349663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 1:  return OFFB_YMM1;
1350663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 2:  return OFFB_YMM2;
1351663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 3:  return OFFB_YMM3;
1352663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 4:  return OFFB_YMM4;
1353663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 5:  return OFFB_YMM5;
1354663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 6:  return OFFB_YMM6;
1355663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 7:  return OFFB_YMM7;
1356663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 8:  return OFFB_YMM8;
1357663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 9:  return OFFB_YMM9;
1358663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 10: return OFFB_YMM10;
1359663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 11: return OFFB_YMM11;
1360663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 12: return OFFB_YMM12;
1361663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 13: return OFFB_YMM13;
1362663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 14: return OFFB_YMM14;
1363663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 15: return OFFB_YMM15;
1364663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default: vpanic("ymmGuestRegOffset(amd64)");
1365663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
1366663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
1367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int xmmGuestRegOffset ( UInt xmmreg )
1369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1370663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Correct for little-endian host only. */
1371663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(!host_is_bigendian);
1372663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return ymmGuestRegOffset( xmmreg );
1373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Lanes of vector registers are always numbered from zero being the
1376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   least significant lane (rightmost in the register).  */
1377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int xmmGuestRegLane16offset ( UInt xmmreg, Int laneno )
1379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Correct for little-endian host only. */
1381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(!host_is_bigendian);
1382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(laneno >= 0 && laneno < 8);
1383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return xmmGuestRegOffset( xmmreg ) + 2 * laneno;
1384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int xmmGuestRegLane32offset ( UInt xmmreg, Int laneno )
1387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Correct for little-endian host only. */
1389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(!host_is_bigendian);
1390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(laneno >= 0 && laneno < 4);
1391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return xmmGuestRegOffset( xmmreg ) + 4 * laneno;
1392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int xmmGuestRegLane64offset ( UInt xmmreg, Int laneno )
1395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Correct for little-endian host only. */
1397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(!host_is_bigendian);
1398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(laneno >= 0 && laneno < 2);
1399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return xmmGuestRegOffset( xmmreg ) + 8 * laneno;
1400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1402663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Int ymmGuestRegLane128offset ( UInt ymmreg, Int laneno )
1403663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
1404663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Correct for little-endian host only. */
1405663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(!host_is_bigendian);
1406663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(laneno >= 0 && laneno < 2);
1407663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return ymmGuestRegOffset( ymmreg ) + 16 * laneno;
1408663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
1409663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1410663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Int ymmGuestRegLane64offset ( UInt ymmreg, Int laneno )
1411663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
1412663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Correct for little-endian host only. */
1413663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(!host_is_bigendian);
1414663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(laneno >= 0 && laneno < 4);
1415663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return ymmGuestRegOffset( ymmreg ) + 8 * laneno;
1416663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
1417663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1418663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Int ymmGuestRegLane32offset ( UInt ymmreg, Int laneno )
1419663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
1420663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Correct for little-endian host only. */
1421663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(!host_is_bigendian);
1422663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(laneno >= 0 && laneno < 8);
1423663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return ymmGuestRegOffset( ymmreg ) + 4 * laneno;
1424663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
1425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* getXMMReg ( UInt xmmreg )
1427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Get( xmmGuestRegOffset(xmmreg), Ity_V128 );
1429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* getXMMRegLane64 ( UInt xmmreg, Int laneno )
1432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Get( xmmGuestRegLane64offset(xmmreg,laneno), Ity_I64 );
1434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* getXMMRegLane64F ( UInt xmmreg, Int laneno )
1437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Get( xmmGuestRegLane64offset(xmmreg,laneno), Ity_F64 );
1439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* getXMMRegLane32 ( UInt xmmreg, Int laneno )
1442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Get( xmmGuestRegLane32offset(xmmreg,laneno), Ity_I32 );
1444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* getXMMRegLane32F ( UInt xmmreg, Int laneno )
1447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Get( xmmGuestRegLane32offset(xmmreg,laneno), Ity_F32 );
1449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* getXMMRegLane16 ( UInt xmmreg, Int laneno )
1452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return IRExpr_Get( xmmGuestRegLane16offset(xmmreg,laneno), Ity_I16 );
1454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void putXMMReg ( UInt xmmreg, IRExpr* e )
1457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv,e) == Ity_V128);
1459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( xmmGuestRegOffset(xmmreg), e ) );
1460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void putXMMRegLane64 ( UInt xmmreg, Int laneno, IRExpr* e )
1463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv,e) == Ity_I64);
1465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( xmmGuestRegLane64offset(xmmreg,laneno), e ) );
1466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void putXMMRegLane64F ( UInt xmmreg, Int laneno, IRExpr* e )
1469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv,e) == Ity_F64);
1471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( xmmGuestRegLane64offset(xmmreg,laneno), e ) );
1472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void putXMMRegLane32F ( UInt xmmreg, Int laneno, IRExpr* e )
1475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv,e) == Ity_F32);
1477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( xmmGuestRegLane32offset(xmmreg,laneno), e ) );
1478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void putXMMRegLane32 ( UInt xmmreg, Int laneno, IRExpr* e )
1481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv,e) == Ity_I32);
1483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( xmmGuestRegLane32offset(xmmreg,laneno), e ) );
1484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1486663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRExpr* getYMMReg ( UInt xmmreg )
1487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1488663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return IRExpr_Get( ymmGuestRegOffset(xmmreg), Ity_V256 );
1489663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
1490663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1491663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRExpr* getYMMRegLane128 ( UInt ymmreg, Int laneno )
1492663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
1493663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return IRExpr_Get( ymmGuestRegLane128offset(ymmreg,laneno), Ity_V128 );
1494663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
1495663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1496663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRExpr* getYMMRegLane64 ( UInt ymmreg, Int laneno )
1497663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
1498663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return IRExpr_Get( ymmGuestRegLane64offset(ymmreg,laneno), Ity_I64 );
1499663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
1500663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1501663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRExpr* getYMMRegLane32 ( UInt ymmreg, Int laneno )
1502663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
1503663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return IRExpr_Get( ymmGuestRegLane32offset(ymmreg,laneno), Ity_I32 );
1504663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
1505663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1506663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void putYMMReg ( UInt ymmreg, IRExpr* e )
1507663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
1508663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(typeOfIRExpr(irsb->tyenv,e) == Ity_V256);
1509663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   stmt( IRStmt_Put( ymmGuestRegOffset(ymmreg), e ) );
1510663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
1511663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1512663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void putYMMRegLane128 ( UInt ymmreg, Int laneno, IRExpr* e )
1513663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
1514663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(typeOfIRExpr(irsb->tyenv,e) == Ity_V128);
1515663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   stmt( IRStmt_Put( ymmGuestRegLane128offset(ymmreg,laneno), e ) );
1516663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
1517663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1518663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void putYMMRegLane64F ( UInt ymmreg, Int laneno, IRExpr* e )
1519663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
1520663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(typeOfIRExpr(irsb->tyenv,e) == Ity_F64);
1521663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   stmt( IRStmt_Put( ymmGuestRegLane64offset(ymmreg,laneno), e ) );
1522663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
1523663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1524663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void putYMMRegLane64 ( UInt ymmreg, Int laneno, IRExpr* e )
1525663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
1526663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(typeOfIRExpr(irsb->tyenv,e) == Ity_I64);
1527663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   stmt( IRStmt_Put( ymmGuestRegLane64offset(ymmreg,laneno), e ) );
1528663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
1529663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1530663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void putYMMRegLane32F ( UInt ymmreg, Int laneno, IRExpr* e )
1531663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
1532663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(typeOfIRExpr(irsb->tyenv,e) == Ity_F32);
1533663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   stmt( IRStmt_Put( ymmGuestRegLane32offset(ymmreg,laneno), e ) );
1534663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
1535663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1536663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void putYMMRegLane32 ( UInt ymmreg, Int laneno, IRExpr* e )
1537663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
1538663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(typeOfIRExpr(irsb->tyenv,e) == Ity_I32);
1539663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   stmt( IRStmt_Put( ymmGuestRegLane32offset(ymmreg,laneno), e ) );
1540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mkV128 ( UShort mask )
1543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Const(IRConst_V128(mask));
1545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1547663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Write the low half of a YMM reg and zero out the upper half. */
1548663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void putYMMRegLoAndZU ( UInt ymmreg, IRExpr* e )
1549663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
1550663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putYMMRegLane128( ymmreg, 0, e );
1551663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putYMMRegLane128( ymmreg, 1, mkV128(0) );
1552663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
1553663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mkAnd1 ( IRExpr* x, IRExpr* y )
1555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv,x) == Ity_I1);
1557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv,y) == Ity_I1);
1558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return unop(Iop_64to1,
1559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(Iop_And64,
1560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     unop(Iop_1Uto64,x),
1561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     unop(Iop_1Uto64,y)));
1562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate a compare-and-swap operation, operating on memory at
1565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   'addr'.  The expected value is 'expVal' and the new value is
1566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   'newVal'.  If the operation fails, then transfer control (with a
1567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   no-redir jump (XXX no -- see comment at top of this file)) to
1568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   'restart_point', which is presumably the address of the guest
1569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   instruction again -- retrying, essentially. */
1570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void casLE ( IRExpr* addr, IRExpr* expVal, IRExpr* newVal,
1571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    Addr64 restart_point )
1572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRCAS* cas;
1574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType tyE    = typeOfIRExpr(irsb->tyenv, expVal);
1575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType tyN    = typeOfIRExpr(irsb->tyenv, newVal);
1576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp oldTmp = newTemp(tyE);
1577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp expTmp = newTemp(tyE);
1578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(tyE == tyN);
1579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(tyE == Ity_I64 || tyE == Ity_I32
1580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || tyE == Ity_I16 || tyE == Ity_I8);
1581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(expTmp, expVal);
1582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cas = mkIRCAS( IRTemp_INVALID, oldTmp, Iend_LE, addr,
1583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  NULL, mkexpr(expTmp), NULL, newVal );
1584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_CAS(cas) );
1585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Exit(
1586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            binop( mkSizedOp(tyE,Iop_CasCmpNE8),
1587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   mkexpr(oldTmp), mkexpr(expTmp) ),
1588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Ijk_Boring, /*Ijk_NoRedir*/
1589663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            IRConst_U64( restart_point ),
1590663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            OFFB_RIP
1591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ));
1592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Helpers for %rflags.                                 ---*/
1597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* -------------- Evaluating the flags-thunk. -------------- */
1600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Build IR to calculate all the eflags from stored
1602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CC_OP/CC_DEP1/CC_DEP2/CC_NDEP.  Returns an expression ::
1603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Ity_I64. */
1604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mk_amd64g_calculate_rflags_all ( void )
1605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr** args
1607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = mkIRExprVec_4( IRExpr_Get(OFFB_CC_OP,   Ity_I64),
1608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       IRExpr_Get(OFFB_CC_DEP1, Ity_I64),
1609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       IRExpr_Get(OFFB_CC_DEP2, Ity_I64),
1610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       IRExpr_Get(OFFB_CC_NDEP, Ity_I64) );
1611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* call
1612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = mkIRExprCCall(
1613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           Ity_I64,
1614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           0/*regparm*/,
1615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           "amd64g_calculate_rflags_all", &amd64g_calculate_rflags_all,
1616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           args
1617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        );
1618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Exclude OP and NDEP from definedness checking.  We're only
1619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      interested in DEP1 and DEP2. */
1620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   call->Iex.CCall.cee->mcx_mask = (1<<0) | (1<<3);
1621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return call;
1622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Build IR to calculate some particular condition from stored
1625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CC_OP/CC_DEP1/CC_DEP2/CC_NDEP.  Returns an expression ::
1626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Ity_Bit. */
1627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mk_amd64g_calculate_condition ( AMD64Condcode cond )
1628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr** args
1630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = mkIRExprVec_5( mkU64(cond),
1631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       IRExpr_Get(OFFB_CC_OP,   Ity_I64),
1632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       IRExpr_Get(OFFB_CC_DEP1, Ity_I64),
1633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       IRExpr_Get(OFFB_CC_DEP2, Ity_I64),
1634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       IRExpr_Get(OFFB_CC_NDEP, Ity_I64) );
1635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* call
1636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = mkIRExprCCall(
1637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           Ity_I64,
1638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           0/*regparm*/,
1639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           "amd64g_calculate_condition", &amd64g_calculate_condition,
1640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           args
1641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        );
1642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Exclude the requested condition, OP and NDEP from definedness
1643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      checking.  We're only interested in DEP1 and DEP2. */
1644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   call->Iex.CCall.cee->mcx_mask = (1<<0) | (1<<1) | (1<<4);
1645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return unop(Iop_64to1, call);
1646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Build IR to calculate just the carry flag from stored
1649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CC_OP/CC_DEP1/CC_DEP2/CC_NDEP.  Returns an expression :: Ity_I64. */
1650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mk_amd64g_calculate_rflags_c ( void )
1651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr** args
1653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = mkIRExprVec_4( IRExpr_Get(OFFB_CC_OP,   Ity_I64),
1654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       IRExpr_Get(OFFB_CC_DEP1, Ity_I64),
1655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       IRExpr_Get(OFFB_CC_DEP2, Ity_I64),
1656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       IRExpr_Get(OFFB_CC_NDEP, Ity_I64) );
1657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* call
1658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = mkIRExprCCall(
1659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           Ity_I64,
1660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           0/*regparm*/,
1661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           "amd64g_calculate_rflags_c", &amd64g_calculate_rflags_c,
1662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           args
1663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        );
1664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Exclude OP and NDEP from definedness checking.  We're only
1665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      interested in DEP1 and DEP2. */
1666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   call->Iex.CCall.cee->mcx_mask = (1<<0) | (1<<3);
1667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return call;
1668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* -------------- Building the flags-thunk. -------------- */
1672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The machinery in this section builds the flag-thunk following a
1674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   flag-setting operation.  Hence the various setFlags_* functions.
1675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool isAddSub ( IROp op8 )
1678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toBool(op8 == Iop_Add8 || op8 == Iop_Sub8);
1680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool isLogic ( IROp op8 )
1683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toBool(op8 == Iop_And8 || op8 == Iop_Or8 || op8 == Iop_Xor8);
1685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* U-widen 8/16/32/64 bit int expr to 64. */
1688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* widenUto64 ( IRExpr* e )
1689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (typeOfIRExpr(irsb->tyenv,e)) {
1691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I64: return e;
1692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I32: return unop(Iop_32Uto64, e);
1693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I16: return unop(Iop_16Uto64, e);
1694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I8:  return unop(Iop_8Uto64, e);
1695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vpanic("widenUto64");
1696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* S-widen 8/16/32/64 bit int expr to 32. */
1700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* widenSto64 ( IRExpr* e )
1701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (typeOfIRExpr(irsb->tyenv,e)) {
1703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I64: return e;
1704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I32: return unop(Iop_32Sto64, e);
1705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I16: return unop(Iop_16Sto64, e);
1706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I8:  return unop(Iop_8Sto64, e);
1707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vpanic("widenSto64");
1708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Narrow 8/16/32/64 bit int expr to 8/16/32/64.  Clearly only some
1712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   of these combinations make sense. */
1713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* narrowTo ( IRType dst_ty, IRExpr* e )
1714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType src_ty = typeOfIRExpr(irsb->tyenv,e);
1716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (src_ty == dst_ty)
1717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return e;
1718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (src_ty == Ity_I32 && dst_ty == Ity_I16)
1719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return unop(Iop_32to16, e);
1720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (src_ty == Ity_I32 && dst_ty == Ity_I8)
1721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return unop(Iop_32to8, e);
1722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (src_ty == Ity_I64 && dst_ty == Ity_I32)
1723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return unop(Iop_64to32, e);
1724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (src_ty == Ity_I64 && dst_ty == Ity_I16)
1725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return unop(Iop_64to16, e);
1726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (src_ty == Ity_I64 && dst_ty == Ity_I8)
1727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return unop(Iop_64to8, e);
1728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("\nsrc, dst tys are: ");
1730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ppIRType(src_ty);
1731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf(", ");
1732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ppIRType(dst_ty);
1733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("\n");
1734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vpanic("narrowTo(amd64)");
1735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Set the flags thunk OP, DEP1 and DEP2 fields.  The supplied op is
1739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   auto-sized up to the real op. */
1740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid setFlags_DEP1_DEP2 ( IROp op8, IRTemp dep1, IRTemp dep2, IRType ty )
1743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int ccOp = 0;
1745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (ty) {
1746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I8:  ccOp = 0; break;
1747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I16: ccOp = 1; break;
1748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I32: ccOp = 2; break;
1749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I64: ccOp = 3; break;
1750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vassert(0);
1751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op8) {
1753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add8: ccOp += AMD64G_CC_OP_ADDB;   break;
1754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub8: ccOp += AMD64G_CC_OP_SUBB;   break;
1755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:       ppIROp(op8);
1756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vpanic("setFlags_DEP1_DEP2(amd64)");
1757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_CC_OP,   mkU64(ccOp)) );
1759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_CC_DEP1, widenUto64(mkexpr(dep1))) );
1760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_CC_DEP2, widenUto64(mkexpr(dep2))) );
1761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Set the OP and DEP1 fields only, and write zero to DEP2. */
1765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid setFlags_DEP1 ( IROp op8, IRTemp dep1, IRType ty )
1768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int ccOp = 0;
1770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (ty) {
1771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I8:  ccOp = 0; break;
1772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I16: ccOp = 1; break;
1773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I32: ccOp = 2; break;
1774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I64: ccOp = 3; break;
1775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vassert(0);
1776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op8) {
1778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Or8:
1779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_And8:
1780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Xor8: ccOp += AMD64G_CC_OP_LOGICB; break;
1781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:       ppIROp(op8);
1782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vpanic("setFlags_DEP1(amd64)");
1783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_CC_OP,   mkU64(ccOp)) );
1785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_CC_DEP1, widenUto64(mkexpr(dep1))) );
1786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_CC_DEP2, mkU64(0)) );
1787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* For shift operations, we put in the result and the undershifted
1791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   result.  Except if the shift amount is zero, the thunk is left
1792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   unchanged. */
1793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void setFlags_DEP1_DEP2_shift ( IROp    op64,
1795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       IRTemp  res,
1796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       IRTemp  resUS,
1797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       IRType  ty,
1798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       IRTemp  guard )
1799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int ccOp = 0;
1801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (ty) {
1802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I8:  ccOp = 0; break;
1803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I16: ccOp = 1; break;
1804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I32: ccOp = 2; break;
1805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I64: ccOp = 3; break;
1806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vassert(0);
1807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(guard);
1810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Both kinds of right shifts are handled by the same thunk
1812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      operation. */
1813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op64) {
1814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shr64:
1815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sar64: ccOp += AMD64G_CC_OP_SHRB; break;
1816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shl64: ccOp += AMD64G_CC_OP_SHLB; break;
1817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:        ppIROp(op64);
1818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      vpanic("setFlags_DEP1_DEP2_shift(amd64)");
1819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* DEP1 contains the result, DEP2 contains the undershifted value. */
1822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_CC_OP,
1823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     IRExpr_Mux0X( mkexpr(guard),
1824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   IRExpr_Get(OFFB_CC_OP,Ity_I64),
1825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   mkU64(ccOp))) );
1826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_CC_DEP1,
1827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     IRExpr_Mux0X( mkexpr(guard),
1828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   IRExpr_Get(OFFB_CC_DEP1,Ity_I64),
1829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   widenUto64(mkexpr(res)))) );
1830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_CC_DEP2,
1831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     IRExpr_Mux0X( mkexpr(guard),
1832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   IRExpr_Get(OFFB_CC_DEP2,Ity_I64),
1833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   widenUto64(mkexpr(resUS)))) );
1834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* For the inc/dec case, we store in DEP1 the result value and in NDEP
1838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the former value of the carry flag, which unfortunately we have to
1839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   compute. */
1840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void setFlags_INC_DEC ( Bool inc, IRTemp res, IRType ty )
1842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int ccOp = inc ? AMD64G_CC_OP_INCB : AMD64G_CC_OP_DECB;
1844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (ty) {
1846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I8:  ccOp += 0; break;
1847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I16: ccOp += 1; break;
1848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I32: ccOp += 2; break;
1849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I64: ccOp += 3; break;
1850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vassert(0);
1851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* This has to come first, because calculating the C flag
1854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      may require reading all four thunk fields. */
1855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_CC_NDEP, mk_amd64g_calculate_rflags_c()) );
1856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_CC_OP,   mkU64(ccOp)) );
1857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_CC_DEP1, widenUto64(mkexpr(res))) );
1858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_CC_DEP2, mkU64(0)) );
1859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Multiplies are pretty much like add and sub: DEP1 and DEP2 hold the
1863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   two arguments. */
1864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid setFlags_MUL ( IRType ty, IRTemp arg1, IRTemp arg2, ULong base_op )
1867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (ty) {
1869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I8:
1870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         stmt( IRStmt_Put( OFFB_CC_OP, mkU64(base_op+0) ) );
1871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
1872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I16:
1873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         stmt( IRStmt_Put( OFFB_CC_OP, mkU64(base_op+1) ) );
1874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
1875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I32:
1876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         stmt( IRStmt_Put( OFFB_CC_OP, mkU64(base_op+2) ) );
1877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
1878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I64:
1879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         stmt( IRStmt_Put( OFFB_CC_OP, mkU64(base_op+3) ) );
1880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
1881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
1882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("setFlags_MUL(amd64)");
1883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_CC_DEP1, widenUto64(mkexpr(arg1)) ));
1885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_CC_DEP2, widenUto64(mkexpr(arg2)) ));
1886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* -------------- Condition codes. -------------- */
1890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Condition codes, using the AMD encoding.  */
1892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HChar* name_AMD64Condcode ( AMD64Condcode cond )
1894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (cond) {
1896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64CondO:      return "o";
1897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64CondNO:     return "no";
1898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64CondB:      return "b";
1899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64CondNB:     return "ae"; /*"nb";*/
1900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64CondZ:      return "e"; /*"z";*/
1901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64CondNZ:     return "ne"; /*"nz";*/
1902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64CondBE:     return "be";
1903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64CondNBE:    return "a"; /*"nbe";*/
1904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64CondS:      return "s";
1905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64CondNS:     return "ns";
1906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64CondP:      return "p";
1907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64CondNP:     return "np";
1908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64CondL:      return "l";
1909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64CondNL:     return "ge"; /*"nl";*/
1910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64CondLE:     return "le";
1911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64CondNLE:    return "g"; /*"nle";*/
1912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case AMD64CondAlways: return "ALWAYS";
1913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vpanic("name_AMD64Condcode");
1914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64Condcode positiveIse_AMD64Condcode ( AMD64Condcode  cond,
1919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          /*OUT*/Bool*   needInvert )
1920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(cond >= AMD64CondO && cond <= AMD64CondNLE);
1922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (cond & 1) {
1923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *needInvert = True;
1924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return cond-1;
1925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *needInvert = False;
1927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return cond;
1928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* -------------- Helpers for ADD/SUB with carry. -------------- */
1933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Given ta1, ta2 and tres, compute tres = ADC(ta1,ta2) and set flags
1935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   appropriately.
1936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Optionally, generate a store for the 'tres' value.  This can either
1938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   be a normal store, or it can be a cas-with-possible-failure style
1939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   store:
1940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if taddr is IRTemp_INVALID, then no store is generated.
1942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if taddr is not IRTemp_INVALID, then a store (using taddr as
1944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the address) is generated:
1945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if texpVal is IRTemp_INVALID then a normal store is
1947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     generated, and restart_point must be zero (it is irrelevant).
1948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if texpVal is not IRTemp_INVALID then a cas-style store is
1950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     generated.  texpVal is the expected value, restart_point
1951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     is the restart point if the store fails, and texpVal must
1952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     have the same type as tres.
1953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void helper_ADC ( Int sz,
1956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         IRTemp tres, IRTemp ta1, IRTemp ta2,
1957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         /* info about optional store: */
1958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         IRTemp taddr, IRTemp texpVal, Addr32 restart_point )
1959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt    thunkOp;
1961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType  ty    = szToITy(sz);
1962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  oldc  = newTemp(Ity_I64);
1963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  oldcn = newTemp(ty);
1964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IROp    plus  = mkSizedOp(ty, Iop_Add8);
1965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IROp    xor   = mkSizedOp(ty, Iop_Xor8);
1966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRTemp(irsb->tyenv, tres) == ty);
1968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (sz) {
1970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 8:  thunkOp = AMD64G_CC_OP_ADCQ; break;
1971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 4:  thunkOp = AMD64G_CC_OP_ADCL; break;
1972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2:  thunkOp = AMD64G_CC_OP_ADCW; break;
1973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 1:  thunkOp = AMD64G_CC_OP_ADCB; break;
1974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vassert(0);
1975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* oldc = old carry flag, 0 or 1 */
1978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( oldc,  binop(Iop_And64,
1979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mk_amd64g_calculate_rflags_c(),
1980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mkU64(1)) );
1981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( oldcn, narrowTo(ty, mkexpr(oldc)) );
1983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( tres, binop(plus,
1985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop(plus,mkexpr(ta1),mkexpr(ta2)),
1986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       mkexpr(oldcn)) );
1987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Possibly generate a store of 'tres' to 'taddr'.  See comment at
1989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      start of this function. */
1990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (taddr != IRTemp_INVALID) {
1991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (texpVal == IRTemp_INVALID) {
1992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(restart_point == 0);
1993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         storeLE( mkexpr(taddr), mkexpr(tres) );
1994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
1995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(typeOfIRTemp(irsb->tyenv, texpVal) == ty);
1996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* .. and hence 'texpVal' has the same type as 'tres'. */
1997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         casLE( mkexpr(taddr),
1998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                mkexpr(texpVal), mkexpr(tres), restart_point );
1999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_CC_OP,   mkU64(thunkOp) ) );
2003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_CC_DEP1, widenUto64(mkexpr(ta1))  ));
2004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_CC_DEP2, widenUto64(binop(xor, mkexpr(ta2),
2005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                         mkexpr(oldcn)) )) );
2006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_CC_NDEP, mkexpr(oldc) ) );
2007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Given ta1, ta2 and tres, compute tres = SBB(ta1,ta2) and set flags
2011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   appropriately.  As with helper_ADC, possibly generate a store of
2012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the result -- see comments on helper_ADC for details.
2013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
2014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void helper_SBB ( Int sz,
2015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         IRTemp tres, IRTemp ta1, IRTemp ta2,
2016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         /* info about optional store: */
2017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         IRTemp taddr, IRTemp texpVal, Addr32 restart_point )
2018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt    thunkOp;
2020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType  ty    = szToITy(sz);
2021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  oldc  = newTemp(Ity_I64);
2022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  oldcn = newTemp(ty);
2023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IROp    minus = mkSizedOp(ty, Iop_Sub8);
2024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IROp    xor   = mkSizedOp(ty, Iop_Xor8);
2025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRTemp(irsb->tyenv, tres) == ty);
2027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (sz) {
2029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 8:  thunkOp = AMD64G_CC_OP_SBBQ; break;
2030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 4:  thunkOp = AMD64G_CC_OP_SBBL; break;
2031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2:  thunkOp = AMD64G_CC_OP_SBBW; break;
2032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 1:  thunkOp = AMD64G_CC_OP_SBBB; break;
2033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vassert(0);
2034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* oldc = old carry flag, 0 or 1 */
2037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( oldc, binop(Iop_And64,
2038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       mk_amd64g_calculate_rflags_c(),
2039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       mkU64(1)) );
2040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( oldcn, narrowTo(ty, mkexpr(oldc)) );
2042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( tres, binop(minus,
2044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop(minus,mkexpr(ta1),mkexpr(ta2)),
2045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       mkexpr(oldcn)) );
2046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Possibly generate a store of 'tres' to 'taddr'.  See comment at
2048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      start of this function. */
2049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (taddr != IRTemp_INVALID) {
2050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (texpVal == IRTemp_INVALID) {
2051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(restart_point == 0);
2052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         storeLE( mkexpr(taddr), mkexpr(tres) );
2053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
2054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(typeOfIRTemp(irsb->tyenv, texpVal) == ty);
2055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* .. and hence 'texpVal' has the same type as 'tres'. */
2056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         casLE( mkexpr(taddr),
2057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                mkexpr(texpVal), mkexpr(tres), restart_point );
2058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_CC_OP,   mkU64(thunkOp) ) );
2062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_CC_DEP1, widenUto64(mkexpr(ta1) )) );
2063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_CC_DEP2, widenUto64(binop(xor, mkexpr(ta2),
2064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                         mkexpr(oldcn)) )) );
2065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_CC_NDEP, mkexpr(oldc) ) );
2066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* -------------- Helpers for disassembly printing. -------------- */
2070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HChar* nameGrp1 ( Int opc_aux )
2072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   static HChar* grp1_names[8]
2074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     = { "add", "or", "adc", "sbb", "and", "sub", "xor", "cmp" };
2075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (opc_aux < 0 || opc_aux > 7) vpanic("nameGrp1(amd64)");
2076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return grp1_names[opc_aux];
2077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HChar* nameGrp2 ( Int opc_aux )
2080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   static HChar* grp2_names[8]
2082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     = { "rol", "ror", "rcl", "rcr", "shl", "shr", "shl", "sar" };
2083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (opc_aux < 0 || opc_aux > 7) vpanic("nameGrp2(amd64)");
2084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return grp2_names[opc_aux];
2085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HChar* nameGrp4 ( Int opc_aux )
2088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   static HChar* grp4_names[8]
2090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     = { "inc", "dec", "???", "???", "???", "???", "???", "???" };
2091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (opc_aux < 0 || opc_aux > 1) vpanic("nameGrp4(amd64)");
2092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return grp4_names[opc_aux];
2093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HChar* nameGrp5 ( Int opc_aux )
2096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   static HChar* grp5_names[8]
2098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     = { "inc", "dec", "call*", "call*", "jmp*", "jmp*", "push", "???" };
2099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (opc_aux < 0 || opc_aux > 6) vpanic("nameGrp5(amd64)");
2100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return grp5_names[opc_aux];
2101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HChar* nameGrp8 ( Int opc_aux )
2104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   static HChar* grp8_names[8]
2106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = { "???", "???", "???", "???", "bt", "bts", "btr", "btc" };
2107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (opc_aux < 4 || opc_aux > 7) vpanic("nameGrp8(amd64)");
2108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return grp8_names[opc_aux];
2109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//.. static HChar* nameSReg ( UInt sreg )
2112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//.. {
2113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..    switch (sreg) {
2114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..       case R_ES: return "%es";
2115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..       case R_CS: return "%cs";
2116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..       case R_SS: return "%ss";
2117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..       case R_DS: return "%ds";
2118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..       case R_FS: return "%fs";
2119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..       case R_GS: return "%gs";
2120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..       default: vpanic("nameSReg(x86)");
2121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..    }
2122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//.. }
2123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HChar* nameMMXReg ( Int mmxreg )
2125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   static HChar* mmx_names[8]
2127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     = { "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7" };
2128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (mmxreg < 0 || mmxreg > 7) vpanic("nameMMXReg(amd64,guest)");
2129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return mmx_names[mmxreg];
2130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HChar* nameXMMReg ( Int xmmreg )
2133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   static HChar* xmm_names[16]
2135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     = { "%xmm0",  "%xmm1",  "%xmm2",  "%xmm3",
2136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         "%xmm4",  "%xmm5",  "%xmm6",  "%xmm7",
2137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         "%xmm8",  "%xmm9",  "%xmm10", "%xmm11",
2138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         "%xmm12", "%xmm13", "%xmm14", "%xmm15" };
2139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (xmmreg < 0 || xmmreg > 15) vpanic("nameXMMReg(amd64)");
2140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return xmm_names[xmmreg];
2141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HChar* nameMMXGran ( Int gran )
2144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (gran) {
2146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0: return "b";
2147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 1: return "w";
2148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2: return "d";
2149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 3: return "q";
2150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vpanic("nameMMXGran(amd64,guest)");
2151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HChar nameISize ( Int size )
2155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (size) {
2157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 8: return 'q';
2158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 4: return 'l';
2159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2: return 'w';
2160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 1: return 'b';
2161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vpanic("nameISize(amd64)");
2162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2165663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic HChar* nameYMMReg ( Int ymmreg )
2166663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
2167663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   static HChar* ymm_names[16]
2168663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     = { "%ymm0",  "%ymm1",  "%ymm2",  "%ymm3",
2169663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         "%ymm4",  "%ymm5",  "%ymm6",  "%ymm7",
2170663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         "%ymm8",  "%ymm9",  "%ymm10", "%ymm11",
2171663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         "%ymm12", "%ymm13", "%ymm14", "%ymm15" };
2172663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (ymmreg < 0 || ymmreg > 15) vpanic("nameYMMReg(amd64)");
2173663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return ymm_names[ymmreg];
2174663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
2175663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
2178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- JMP helpers                                          ---*/
2179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
2180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2181663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void jmp_lit( /*MOD*/DisResult* dres,
2182663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     IRJumpKind kind, Addr64 d64 )
2183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2184663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(dres->whatNext    == Dis_Continue);
2185663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(dres->len         == 0);
2186663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(dres->continueAt  == 0);
2187663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(dres->jk_StopHere == Ijk_INVALID);
2188663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   dres->whatNext    = Dis_StopHere;
2189663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   dres->jk_StopHere = kind;
2190663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   stmt( IRStmt_Put( OFFB_RIP, mkU64(d64) ) );
2191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2193663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void jmp_treg( /*MOD*/DisResult* dres,
2194663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      IRJumpKind kind, IRTemp t )
2195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2196663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(dres->whatNext    == Dis_Continue);
2197663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(dres->len         == 0);
2198663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(dres->continueAt  == 0);
2199663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(dres->jk_StopHere == Ijk_INVALID);
2200663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   dres->whatNext    = Dis_StopHere;
2201663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   dres->jk_StopHere = kind;
2202663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   stmt( IRStmt_Put( OFFB_RIP, mkexpr(t) ) );
2203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2206663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengvoid jcc_01 ( /*MOD*/DisResult* dres,
2207663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              AMD64Condcode cond, Addr64 d64_false, Addr64 d64_true )
2208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool          invert;
2210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64Condcode condPos;
2211663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(dres->whatNext    == Dis_Continue);
2212663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(dres->len         == 0);
2213663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(dres->continueAt  == 0);
2214663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(dres->jk_StopHere == Ijk_INVALID);
2215663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   dres->whatNext    = Dis_StopHere;
2216663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   dres->jk_StopHere = Ijk_Boring;
2217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   condPos = positiveIse_AMD64Condcode ( cond, &invert );
2218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (invert) {
2219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt( IRStmt_Exit( mk_amd64g_calculate_condition(condPos),
2220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         Ijk_Boring,
2221663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         IRConst_U64(d64_false),
2222663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         OFFB_RIP ) );
2223663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      stmt( IRStmt_Put( OFFB_RIP, mkU64(d64_true) ) );
2224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
2225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt( IRStmt_Exit( mk_amd64g_calculate_condition(condPos),
2226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         Ijk_Boring,
2227663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         IRConst_U64(d64_true),
2228663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         OFFB_RIP ) );
2229663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      stmt( IRStmt_Put( OFFB_RIP, mkU64(d64_false) ) );
2230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Let new_rsp be the %rsp value after a call/return.  Let nia be the
2234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   guest address of the next instruction to be executed.
2235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This function generates an AbiHint to say that -128(%rsp)
2237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   .. -1(%rsp) should now be regarded as uninitialised.
2238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
2239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid make_redzone_AbiHint ( VexAbiInfo* vbi,
2241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            IRTemp new_rsp, IRTemp nia, HChar* who )
2242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int szB = vbi->guest_stack_redzone_size;
2244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(szB >= 0);
2245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* A bit of a kludge.  Currently the only AbI we've guested AMD64
2247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for is ELF.  So just check it's the expected 128 value
2248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (paranoia). */
2249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(szB == 128);
2250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0) vex_printf("AbiHint: %s\n", who);
2252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRTemp(irsb->tyenv, new_rsp) == Ity_I64);
2253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I64);
2254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (szB > 0)
2255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt( IRStmt_AbiHint(
2256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(Iop_Sub64, mkexpr(new_rsp), mkU64(szB)),
2257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               szB,
2258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               mkexpr(nia)
2259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ));
2260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
2264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Disassembling addressing modes                       ---*/
2265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
2266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHChar* segRegTxt ( Prefix pfx )
2269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (pfx & PFX_CS) return "%cs:";
2271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (pfx & PFX_DS) return "%ds:";
2272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (pfx & PFX_ES) return "%es:";
2273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (pfx & PFX_FS) return "%fs:";
2274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (pfx & PFX_GS) return "%gs:";
2275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (pfx & PFX_SS) return "%ss:";
2276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ""; /* no override */
2277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 'virtual' is an IRExpr* holding a virtual address.  Convert it to a
2281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   linear address by adding any required segment override as indicated
2282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   by sorb, and also dealing with any address size override
2283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   present. */
2284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRExpr* handleAddrOverrides ( VexAbiInfo* vbi,
2286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              Prefix pfx, IRExpr* virtual )
2287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --- segment overrides --- */
2289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (pfx & PFX_FS) {
2290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (vbi->guest_amd64_assume_fs_is_zero) {
2291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Note that this is a linux-kernel specific hack that relies
2292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            on the assumption that %fs is always zero. */
2293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* return virtual + guest_FS_ZERO. */
2294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         virtual = binop(Iop_Add64, virtual,
2295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    IRExpr_Get(OFFB_FS_ZERO, Ity_I64));
2296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
2297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         unimplemented("amd64 %fs segment override");
2298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (pfx & PFX_GS) {
2302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (vbi->guest_amd64_assume_gs_is_0x60) {
2303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Note that this is a darwin-kernel specific hack that relies
2304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            on the assumption that %gs is always 0x60. */
2305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* return virtual + guest_GS_0x60. */
2306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         virtual = binop(Iop_Add64, virtual,
2307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    IRExpr_Get(OFFB_GS_0x60, Ity_I64));
2308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
2309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         unimplemented("amd64 %gs segment override");
2310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* cs, ds, es and ss are simply ignored in 64-bit mode. */
2314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --- address size override --- */
2316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (haveASO(pfx))
2317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      virtual = unop(Iop_32Uto64, unop(Iop_64to32, virtual));
2318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return virtual;
2320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//.. {
2323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..    Int    sreg;
2324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..    IRType hWordTy;
2325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..    IRTemp ldt_ptr, gdt_ptr, seg_selector, r64;
2326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..
2327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..    if (sorb == 0)
2328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..       /* the common case - no override */
2329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..       return virtual;
2330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..
2331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..    switch (sorb) {
2332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..       case 0x3E: sreg = R_DS; break;
2333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..       case 0x26: sreg = R_ES; break;
2334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..       case 0x64: sreg = R_FS; break;
2335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..       case 0x65: sreg = R_GS; break;
2336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..       default: vpanic("handleAddrOverrides(x86,guest)");
2337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..    }
2338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..
2339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..    hWordTy = sizeof(HWord)==4 ? Ity_I32 : Ity_I64;
2340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..
2341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..    seg_selector = newTemp(Ity_I32);
2342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..    ldt_ptr      = newTemp(hWordTy);
2343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..    gdt_ptr      = newTemp(hWordTy);
2344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..    r64          = newTemp(Ity_I64);
2345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..
2346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..    assign( seg_selector, unop(Iop_16Uto32, getSReg(sreg)) );
2347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..    assign( ldt_ptr, IRExpr_Get( OFFB_LDT, hWordTy ));
2348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..    assign( gdt_ptr, IRExpr_Get( OFFB_GDT, hWordTy ));
2349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..
2350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..    /*
2351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..    Call this to do the translation and limit checks:
2352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..    ULong x86g_use_seg_selector ( HWord ldt, HWord gdt,
2353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..                                  UInt seg_selector, UInt virtual_addr )
2354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..    */
2355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..    assign(
2356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..       r64,
2357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..       mkIRExprCCall(
2358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..          Ity_I64,
2359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..          0/*regparms*/,
2360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..          "x86g_use_seg_selector",
2361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..          &x86g_use_seg_selector,
2362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..          mkIRExprVec_4( mkexpr(ldt_ptr), mkexpr(gdt_ptr),
2363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..                         mkexpr(seg_selector), virtual)
2364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..       )
2365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..    );
2366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..
2367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..    /* If the high 32 of the result are non-zero, there was a
2368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..       failure in address translation.  In which case, make a
2369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..       quick exit.
2370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..    */
2371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..    stmt(
2372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..       IRStmt_Exit(
2373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..          binop(Iop_CmpNE32, unop(Iop_64HIto32, mkexpr(r64)), mkU32(0)),
2374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..          Ijk_MapFail,
2375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..          IRConst_U32( guest_eip_curr_instr )
2376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..       )
2377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..    );
2378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..
2379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..    /* otherwise, here's the translated result. */
2380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..    return unop(Iop_64to32, mkexpr(r64));
2381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//.. }
2382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate IR to calculate an address indicated by a ModRM and
2385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   following SIB bytes.  The expression, and the number of bytes in
2386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the address mode, are returned (the latter in *len).  Note that
2387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   this fn should not be called if the R/M part of the address denotes
2388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   a register instead of memory.  If print_codegen is true, text of
2389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the addressing mode is placed in buf.
2390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The computed address is stored in a new tempreg, and the
2392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   identity of the tempreg is returned.
2393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   extra_bytes holds the number of bytes after the amode, as supplied
2395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   by the caller.  This is needed to make sense of %rip-relative
2396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addresses.  Note that the value that *len is set to is only the
2397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   length of the amode itself and does not include the value supplied
2398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   in extra_bytes.
2399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
2400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRTemp disAMode_copy2tmp ( IRExpr* addr64 )
2402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp tmp = newTemp(Ity_I64);
2404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( tmp, addr64 );
2405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return tmp;
2406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRTemp disAMode ( /*OUT*/Int* len,
2410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  VexAbiInfo* vbi, Prefix pfx, Long delta,
2411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  /*OUT*/HChar* buf, Int extra_bytes )
2412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar mod_reg_rm = getUChar(delta);
2414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   delta++;
2415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   buf[0] = (UChar)0;
2417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(extra_bytes >= 0 && extra_bytes < 10);
2418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* squeeze out the reg field from mod_reg_rm, since a 256-entry
2420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      jump table seems a bit excessive.
2421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
2422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mod_reg_rm &= 0xC7;                         /* is now XX000YYY */
2423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mod_reg_rm  = toUChar(mod_reg_rm | (mod_reg_rm >> 3));
2424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                               /* is now XX0XXYYY */
2425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mod_reg_rm &= 0x1F;                         /* is now 000XXYYY */
2426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (mod_reg_rm) {
2427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* REX.B==0: (%rax) .. (%rdi), not including (%rsp) or (%rbp).
2429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         REX.B==1: (%r8)  .. (%r15), not including (%r12) or (%r13).
2430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      */
2431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x00: case 0x01: case 0x02: case 0x03:
2432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ! 04 */ /* ! 05 */ case 0x06: case 0x07:
2433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         { UChar rm = toUChar(mod_reg_rm & 7);
2434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           DIS(buf, "%s(%s)", segRegTxt(pfx), nameIRegRexB(8,pfx,rm));
2435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           *len = 1;
2436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           return disAMode_copy2tmp(
2437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  handleAddrOverrides(vbi, pfx, getIRegRexB(8,pfx,rm)));
2438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* REX.B==0: d8(%rax) ... d8(%rdi), not including d8(%rsp)
2441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         REX.B==1: d8(%r8)  ... d8(%r15), not including d8(%r12)
2442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      */
2443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x08: case 0x09: case 0x0A: case 0x0B:
2444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ! 0C */ case 0x0D: case 0x0E: case 0x0F:
2445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         { UChar rm = toUChar(mod_reg_rm & 7);
2446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           Long d   = getSDisp8(delta);
2447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (d == 0) {
2448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              DIS(buf, "%s(%s)", segRegTxt(pfx), nameIRegRexB(8,pfx,rm));
2449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           } else {
2450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              DIS(buf, "%s%lld(%s)", segRegTxt(pfx), d, nameIRegRexB(8,pfx,rm));
2451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           }
2452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           *len = 2;
2453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           return disAMode_copy2tmp(
2454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  handleAddrOverrides(vbi, pfx,
2455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_Add64,getIRegRexB(8,pfx,rm),mkU64(d))));
2456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* REX.B==0: d32(%rax) ... d32(%rdi), not including d32(%rsp)
2459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         REX.B==1: d32(%r8)  ... d32(%r15), not including d32(%r12)
2460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      */
2461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x10: case 0x11: case 0x12: case 0x13:
2462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ! 14 */ case 0x15: case 0x16: case 0x17:
2463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         { UChar rm = toUChar(mod_reg_rm & 7);
2464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           Long  d  = getSDisp32(delta);
2465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           DIS(buf, "%s%lld(%s)", segRegTxt(pfx), d, nameIRegRexB(8,pfx,rm));
2466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           *len = 5;
2467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           return disAMode_copy2tmp(
2468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  handleAddrOverrides(vbi, pfx,
2469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_Add64,getIRegRexB(8,pfx,rm),mkU64(d))));
2470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* REX.B==0: a register, %rax .. %rdi.  This shouldn't happen. */
2473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* REX.B==1: a register, %r8  .. %r16.  This shouldn't happen. */
2474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x18: case 0x19: case 0x1A: case 0x1B:
2475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x1C: case 0x1D: case 0x1E: case 0x1F:
2476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("disAMode(amd64): not an addr!");
2477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* RIP + disp32.  This assumes that guest_RIP_curr_instr is set
2479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         correctly at the start of handling each instruction. */
2480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x05:
2481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         { Long d = getSDisp32(delta);
2482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           *len = 5;
2483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           DIS(buf, "%s%lld(%%rip)", segRegTxt(pfx), d);
2484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           /* We need to know the next instruction's start address.
2485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              Try and figure out what it is, record the guess, and ask
2486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              the top-level driver logic (bbToIR_AMD64) to check we
2487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              guessed right, after the instruction is completely
2488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              decoded. */
2489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           guest_RIP_next_mustcheck = True;
2490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           guest_RIP_next_assumed = guest_RIP_bbstart
2491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    + delta+4 + extra_bytes;
2492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           return disAMode_copy2tmp(
2493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     handleAddrOverrides(vbi, pfx,
2494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_Add64, mkU64(guest_RIP_next_assumed),
2495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         mkU64(d))));
2496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x04: {
2499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* SIB, with no displacement.  Special cases:
2500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            -- %rsp cannot act as an index value.
2501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               If index_r indicates %rsp, zero is used for the index.
2502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            -- when mod is zero and base indicates RBP or R13, base is
2503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               instead a 32-bit sign-extended literal.
2504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            It's all madness, I tell you.  Extract %index, %base and
2505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            scale from the SIB byte.  The value denoted is then:
2506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               | %index == %RSP && (%base == %RBP || %base == %R13)
2507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               = d32 following SIB byte
2508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               | %index == %RSP && !(%base == %RBP || %base == %R13)
2509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               = %base
2510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               | %index != %RSP && (%base == %RBP || %base == %R13)
2511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               = d32 following SIB byte + (%index << scale)
2512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               | %index != %RSP && !(%base == %RBP || %base == %R13)
2513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               = %base + (%index << scale)
2514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         */
2515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UChar sib     = getUChar(delta);
2516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UChar scale   = toUChar((sib >> 6) & 3);
2517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UChar index_r = toUChar((sib >> 3) & 7);
2518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UChar base_r  = toUChar(sib & 7);
2519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* correct since #(R13) == 8 + #(RBP) */
2520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool  base_is_BPor13 = toBool(base_r == R_RBP);
2521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool  index_is_SP    = toBool(index_r == R_RSP && 0==getRexX(pfx));
2522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         delta++;
2523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if ((!index_is_SP) && (!base_is_BPor13)) {
2525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (scale == 0) {
2526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIS(buf, "%s(%s,%s)", segRegTxt(pfx),
2527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         nameIRegRexB(8,pfx,base_r),
2528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         nameIReg64rexX(pfx,index_r));
2529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
2530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIS(buf, "%s(%s,%s,%d)", segRegTxt(pfx),
2531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         nameIRegRexB(8,pfx,base_r),
2532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         nameIReg64rexX(pfx,index_r), 1<<scale);
2533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
2534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *len = 2;
2535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return
2536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               disAMode_copy2tmp(
2537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               handleAddrOverrides(vbi, pfx,
2538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(Iop_Add64,
2539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        getIRegRexB(8,pfx,base_r),
2540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_Shl64, getIReg64rexX(pfx,index_r),
2541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkU8(scale)))));
2542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if ((!index_is_SP) && base_is_BPor13) {
2545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Long d = getSDisp32(delta);
2546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIS(buf, "%s%lld(,%s,%d)", segRegTxt(pfx), d,
2547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      nameIReg64rexX(pfx,index_r), 1<<scale);
2548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *len = 6;
2549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return
2550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               disAMode_copy2tmp(
2551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               handleAddrOverrides(vbi, pfx,
2552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(Iop_Add64,
2553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_Shl64, getIReg64rexX(pfx,index_r),
2554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         mkU8(scale)),
2555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mkU64(d))));
2556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (index_is_SP && (!base_is_BPor13)) {
2559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIS(buf, "%s(%s)", segRegTxt(pfx), nameIRegRexB(8,pfx,base_r));
2560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *len = 2;
2561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return disAMode_copy2tmp(
2562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   handleAddrOverrides(vbi, pfx, getIRegRexB(8,pfx,base_r)));
2563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (index_is_SP && base_is_BPor13) {
2566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Long d = getSDisp32(delta);
2567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIS(buf, "%s%lld", segRegTxt(pfx), d);
2568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *len = 6;
2569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return disAMode_copy2tmp(
2570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   handleAddrOverrides(vbi, pfx, mkU64(d)));
2571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(0);
2574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* SIB, with 8-bit displacement.  Special cases:
2577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         -- %esp cannot act as an index value.
2578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            If index_r indicates %esp, zero is used for the index.
2579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Denoted value is:
2580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            | %index == %ESP
2581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            = d8 + %base
2582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            | %index != %ESP
2583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            = d8 + %base + (%index << scale)
2584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      */
2585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x0C: {
2586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UChar sib     = getUChar(delta);
2587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UChar scale   = toUChar((sib >> 6) & 3);
2588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UChar index_r = toUChar((sib >> 3) & 7);
2589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UChar base_r  = toUChar(sib & 7);
2590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Long d        = getSDisp8(delta+1);
2591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (index_r == R_RSP && 0==getRexX(pfx)) {
2593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIS(buf, "%s%lld(%s)", segRegTxt(pfx),
2594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   d, nameIRegRexB(8,pfx,base_r));
2595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *len = 3;
2596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return disAMode_copy2tmp(
2597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   handleAddrOverrides(vbi, pfx,
2598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_Add64, getIRegRexB(8,pfx,base_r), mkU64(d)) ));
2599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
2600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (scale == 0) {
2601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIS(buf, "%s%lld(%s,%s)", segRegTxt(pfx), d,
2602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         nameIRegRexB(8,pfx,base_r),
2603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         nameIReg64rexX(pfx,index_r));
2604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
2605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIS(buf, "%s%lld(%s,%s,%d)", segRegTxt(pfx), d,
2606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         nameIRegRexB(8,pfx,base_r),
2607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         nameIReg64rexX(pfx,index_r), 1<<scale);
2608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
2609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *len = 3;
2610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return
2611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                disAMode_copy2tmp(
2612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                handleAddrOverrides(vbi, pfx,
2613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(Iop_Add64,
2614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_Add64,
2615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              getIRegRexB(8,pfx,base_r),
2616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              binop(Iop_Shl64,
2617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    getIReg64rexX(pfx,index_r), mkU8(scale))),
2618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mkU64(d))));
2619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(0); /*NOTREACHED*/
2621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* SIB, with 32-bit displacement.  Special cases:
2624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         -- %rsp cannot act as an index value.
2625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            If index_r indicates %rsp, zero is used for the index.
2626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Denoted value is:
2627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            | %index == %RSP
2628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            = d32 + %base
2629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            | %index != %RSP
2630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            = d32 + %base + (%index << scale)
2631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      */
2632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x14: {
2633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UChar sib     = getUChar(delta);
2634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UChar scale   = toUChar((sib >> 6) & 3);
2635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UChar index_r = toUChar((sib >> 3) & 7);
2636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UChar base_r  = toUChar(sib & 7);
2637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Long d        = getSDisp32(delta+1);
2638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (index_r == R_RSP && 0==getRexX(pfx)) {
2640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIS(buf, "%s%lld(%s)", segRegTxt(pfx),
2641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   d, nameIRegRexB(8,pfx,base_r));
2642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *len = 6;
2643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return disAMode_copy2tmp(
2644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   handleAddrOverrides(vbi, pfx,
2645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_Add64, getIRegRexB(8,pfx,base_r), mkU64(d)) ));
2646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
2647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (scale == 0) {
2648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIS(buf, "%s%lld(%s,%s)", segRegTxt(pfx), d,
2649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         nameIRegRexB(8,pfx,base_r),
2650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         nameIReg64rexX(pfx,index_r));
2651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
2652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIS(buf, "%s%lld(%s,%s,%d)", segRegTxt(pfx), d,
2653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         nameIRegRexB(8,pfx,base_r),
2654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         nameIReg64rexX(pfx,index_r), 1<<scale);
2655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
2656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *len = 6;
2657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return
2658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                disAMode_copy2tmp(
2659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                handleAddrOverrides(vbi, pfx,
2660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(Iop_Add64,
2661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_Add64,
2662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              getIRegRexB(8,pfx,base_r),
2663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              binop(Iop_Shl64,
2664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    getIReg64rexX(pfx,index_r), mkU8(scale))),
2665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mkU64(d))));
2666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(0); /*NOTREACHED*/
2668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
2671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("disAMode(amd64)");
2672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return 0; /*notreached*/
2673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Figure out the number of (insn-stream) bytes constituting the amode
2678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   beginning at delta.  Is useful for getting hold of literals beyond
2679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the end of the amode before it has been disassembled.  */
2680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt lengthAMode ( Prefix pfx, Long delta )
2682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar mod_reg_rm = getUChar(delta);
2684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   delta++;
2685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* squeeze out the reg field from mod_reg_rm, since a 256-entry
2687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      jump table seems a bit excessive.
2688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
2689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mod_reg_rm &= 0xC7;                         /* is now XX000YYY */
2690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mod_reg_rm  = toUChar(mod_reg_rm | (mod_reg_rm >> 3));
2691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                               /* is now XX0XXYYY */
2692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mod_reg_rm &= 0x1F;                         /* is now 000XXYYY */
2693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (mod_reg_rm) {
2694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* REX.B==0: (%rax) .. (%rdi), not including (%rsp) or (%rbp).
2696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         REX.B==1: (%r8)  .. (%r15), not including (%r12) or (%r13).
2697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      */
2698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x00: case 0x01: case 0x02: case 0x03:
2699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ! 04 */ /* ! 05 */ case 0x06: case 0x07:
2700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return 1;
2701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* REX.B==0: d8(%rax) ... d8(%rdi), not including d8(%rsp)
2703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         REX.B==1: d8(%r8)  ... d8(%r15), not including d8(%r12)
2704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      */
2705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x08: case 0x09: case 0x0A: case 0x0B:
2706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ! 0C */ case 0x0D: case 0x0E: case 0x0F:
2707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return 2;
2708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* REX.B==0: d32(%rax) ... d32(%rdi), not including d32(%rsp)
2710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         REX.B==1: d32(%r8)  ... d32(%r15), not including d32(%r12)
2711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      */
2712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x10: case 0x11: case 0x12: case 0x13:
2713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ! 14 */ case 0x15: case 0x16: case 0x17:
2714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return 5;
2715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* REX.B==0: a register, %rax .. %rdi.  This shouldn't happen. */
2717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* REX.B==1: a register, %r8  .. %r16.  This shouldn't happen. */
2718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Not an address, but still handled. */
2719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x18: case 0x19: case 0x1A: case 0x1B:
2720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x1C: case 0x1D: case 0x1E: case 0x1F:
2721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return 1;
2722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* RIP + disp32. */
2724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x05:
2725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return 5;
2726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x04: {
2728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* SIB, with no displacement. */
2729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UChar sib     = getUChar(delta);
2730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UChar base_r  = toUChar(sib & 7);
2731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* correct since #(R13) == 8 + #(RBP) */
2732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool  base_is_BPor13 = toBool(base_r == R_RBP);
2733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (base_is_BPor13) {
2735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return 6;
2736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
2737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return 2;
2738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* SIB, with 8-bit displacement. */
2742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x0C:
2743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return 3;
2744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* SIB, with 32-bit displacement. */
2746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x14:
2747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return 6;
2748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
2750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("lengthAMode(amd64)");
2751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return 0; /*notreached*/
2752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
2757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Disassembling common idioms                          ---*/
2758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
2759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Handle binary integer instructions of the form
2761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      op E, G  meaning
2762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      op reg-or-mem, reg
2763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Is passed the a ptr to the modRM byte, the actual operation, and the
2764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   data size.  Returns the address advanced completely over this
2765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   instruction.
2766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   E(src) is reg-or-mem
2768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   G(dst) is reg.
2769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   If E is reg, -->    GET %G,  tmp
2771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       OP %E,   tmp
2772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       PUT tmp, %G
2773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   If E is mem and OP is not reversible,
2775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                -->    (getAddr E) -> tmpa
2776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       LD (tmpa), tmpa
2777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       GET %G, tmp2
2778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       OP tmpa, tmp2
2779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       PUT tmp2, %G
2780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   If E is mem and OP is reversible
2782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                -->    (getAddr E) -> tmpa
2783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       LD (tmpa), tmpa
2784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       OP %G, tmpa
2785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       PUT tmpa, %G
2786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
2787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong dis_op2_E_G ( VexAbiInfo* vbi,
2789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    Prefix      pfx,
2790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    Bool        addSubCarry,
2791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    IROp        op8,
2792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    Bool        keep,
2793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    Int         size,
2794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    Long        delta0,
2795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    HChar*      t_amd64opc )
2796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar   dis_buf[50];
2798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     len;
2799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType  ty   = szToITy(size);
2800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  dst1 = newTemp(ty);
2801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  src  = newTemp(ty);
2802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  dst0 = newTemp(ty);
2803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar   rm   = getUChar(delta0);
2804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  addr = IRTemp_INVALID;
2805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* addSubCarry == True indicates the intended operation is
2807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      add-with-carry or subtract-with-borrow. */
2808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (addSubCarry) {
2809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(op8 == Iop_Add8 || op8 == Iop_Sub8);
2810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(keep);
2811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (epartIsReg(rm)) {
2814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Specially handle XOR reg,reg, because that doesn't really
2815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         depend on reg, and doing the obvious thing potentially
2816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         generates a spurious value check failure due to the bogus
2817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         dependency. */
2818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ((op8 == Iop_Xor8 || (op8 == Iop_Sub8 && addSubCarry))
2819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && offsetIRegG(size,pfx,rm) == offsetIRegE(size,pfx,rm)) {
2820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (False && op8 == Iop_Sub8)
2821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("vex amd64->IR: sbb %%r,%%r optimisation(1)\n");
2822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 putIRegG(size,pfx,rm, mkU(ty,0));
2823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( dst0, getIRegG(size,pfx,rm) );
2826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( src,  getIRegE(size,pfx,rm) );
2827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (addSubCarry && op8 == Iop_Add8) {
2829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         helper_ADC( size, dst1, dst0, src,
2830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     /*no store*/IRTemp_INVALID, IRTemp_INVALID, 0 );
2831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegG(size, pfx, rm, mkexpr(dst1));
2832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else
2833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (addSubCarry && op8 == Iop_Sub8) {
2834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         helper_SBB( size, dst1, dst0, src,
2835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     /*no store*/IRTemp_INVALID, IRTemp_INVALID, 0 );
2836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegG(size, pfx, rm, mkexpr(dst1));
2837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
2838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)) );
2839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (isAddSub(op8))
2840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            setFlags_DEP1_DEP2(op8, dst0, src, ty);
2841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
2842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            setFlags_DEP1(op8, dst1, ty);
2843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (keep)
2844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putIRegG(size, pfx, rm, mkexpr(dst1));
2845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("%s%c %s,%s\n", t_amd64opc, nameISize(size),
2848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          nameIRegE(size,pfx,rm),
2849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          nameIRegG(size,pfx,rm));
2850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return 1+delta0;
2851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
2852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* E refers to memory */
2853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addr = disAMode ( &len, vbi, pfx, delta0, dis_buf, 0 );
2854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( dst0, getIRegG(size,pfx,rm) );
2855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( src,  loadLE(szToITy(size), mkexpr(addr)) );
2856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (addSubCarry && op8 == Iop_Add8) {
2858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         helper_ADC( size, dst1, dst0, src,
2859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     /*no store*/IRTemp_INVALID, IRTemp_INVALID, 0 );
2860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegG(size, pfx, rm, mkexpr(dst1));
2861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else
2862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (addSubCarry && op8 == Iop_Sub8) {
2863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         helper_SBB( size, dst1, dst0, src,
2864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     /*no store*/IRTemp_INVALID, IRTemp_INVALID, 0 );
2865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegG(size, pfx, rm, mkexpr(dst1));
2866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
2867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)) );
2868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (isAddSub(op8))
2869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            setFlags_DEP1_DEP2(op8, dst0, src, ty);
2870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
2871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            setFlags_DEP1(op8, dst1, ty);
2872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (keep)
2873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putIRegG(size, pfx, rm, mkexpr(dst1));
2874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("%s%c %s,%s\n", t_amd64opc, nameISize(size),
2877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          dis_buf, nameIRegG(size, pfx, rm));
2878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return len+delta0;
2879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Handle binary integer instructions of the form
2885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      op G, E  meaning
2886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      op reg, reg-or-mem
2887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Is passed the a ptr to the modRM byte, the actual operation, and the
2888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   data size.  Returns the address advanced completely over this
2889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   instruction.
2890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   G(src) is reg.
2892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   E(dst) is reg-or-mem
2893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   If E is reg, -->    GET %E,  tmp
2895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       OP %G,   tmp
2896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       PUT tmp, %E
2897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   If E is mem, -->    (getAddr E) -> tmpa
2899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       LD (tmpa), tmpv
2900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       OP %G, tmpv
2901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       ST tmpv, (tmpa)
2902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
2903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong dis_op2_G_E ( VexAbiInfo* vbi,
2905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    Prefix      pfx,
2906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    Bool        addSubCarry,
2907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    IROp        op8,
2908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    Bool        keep,
2909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    Int         size,
2910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    Long        delta0,
2911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    HChar*      t_amd64opc )
2912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar   dis_buf[50];
2914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     len;
2915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType  ty   = szToITy(size);
2916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  dst1 = newTemp(ty);
2917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  src  = newTemp(ty);
2918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  dst0 = newTemp(ty);
2919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar   rm   = getUChar(delta0);
2920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  addr = IRTemp_INVALID;
2921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* addSubCarry == True indicates the intended operation is
2923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      add-with-carry or subtract-with-borrow. */
2924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (addSubCarry) {
2925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(op8 == Iop_Add8 || op8 == Iop_Sub8);
2926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(keep);
2927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (epartIsReg(rm)) {
2930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Specially handle XOR reg,reg, because that doesn't really
2931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         depend on reg, and doing the obvious thing potentially
2932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         generates a spurious value check failure due to the bogus
2933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         dependency.  Ditto SBB reg,reg. */
2934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ((op8 == Iop_Xor8 || (op8 == Iop_Sub8 && addSubCarry))
2935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && offsetIRegG(size,pfx,rm) == offsetIRegE(size,pfx,rm)) {
2936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegE(size,pfx,rm, mkU(ty,0));
2937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(dst0, getIRegE(size,pfx,rm));
2940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(src,  getIRegG(size,pfx,rm));
2941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (addSubCarry && op8 == Iop_Add8) {
2943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         helper_ADC( size, dst1, dst0, src,
2944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     /*no store*/IRTemp_INVALID, IRTemp_INVALID, 0 );
2945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegE(size, pfx, rm, mkexpr(dst1));
2946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else
2947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (addSubCarry && op8 == Iop_Sub8) {
2948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         helper_SBB( size, dst1, dst0, src,
2949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     /*no store*/IRTemp_INVALID, IRTemp_INVALID, 0 );
2950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegE(size, pfx, rm, mkexpr(dst1));
2951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
2952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)));
2953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (isAddSub(op8))
2954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            setFlags_DEP1_DEP2(op8, dst0, src, ty);
2955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
2956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            setFlags_DEP1(op8, dst1, ty);
2957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (keep)
2958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putIRegE(size, pfx, rm, mkexpr(dst1));
2959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("%s%c %s,%s\n", t_amd64opc, nameISize(size),
2962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          nameIRegG(size,pfx,rm),
2963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          nameIRegE(size,pfx,rm));
2964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return 1+delta0;
2965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* E refers to memory */
2968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
2969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addr = disAMode ( &len, vbi, pfx, delta0, dis_buf, 0 );
2970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(dst0, loadLE(ty,mkexpr(addr)));
2971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(src,  getIRegG(size,pfx,rm));
2972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (addSubCarry && op8 == Iop_Add8) {
2974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (pfx & PFX_LOCK) {
2975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* cas-style store */
2976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            helper_ADC( size, dst1, dst0, src,
2977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        /*store*/addr, dst0/*expVal*/, guest_RIP_curr_instr );
2978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
2979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* normal store */
2980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            helper_ADC( size, dst1, dst0, src,
2981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        /*store*/addr, IRTemp_INVALID, 0 );
2982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else
2984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (addSubCarry && op8 == Iop_Sub8) {
2985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (pfx & PFX_LOCK) {
2986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* cas-style store */
2987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            helper_SBB( size, dst1, dst0, src,
2988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        /*store*/addr, dst0/*expVal*/, guest_RIP_curr_instr );
2989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
2990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* normal store */
2991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            helper_SBB( size, dst1, dst0, src,
2992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        /*store*/addr, IRTemp_INVALID, 0 );
2993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
2995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)));
2996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (keep) {
2997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (pfx & PFX_LOCK) {
2998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (0) vex_printf("locked case\n" );
2999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               casLE( mkexpr(addr),
3000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      mkexpr(dst0)/*expval*/,
3001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      mkexpr(dst1)/*newval*/, guest_RIP_curr_instr );
3002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
3003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (0) vex_printf("nonlocked case\n");
3004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               storeLE(mkexpr(addr), mkexpr(dst1));
3005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (isAddSub(op8))
3008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            setFlags_DEP1_DEP2(op8, dst0, src, ty);
3009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
3010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            setFlags_DEP1(op8, dst1, ty);
3011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("%s%c %s,%s\n", t_amd64opc, nameISize(size),
3014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          nameIRegG(size,pfx,rm), dis_buf);
3015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return len+delta0;
3016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Handle move instructions of the form
3021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      mov E, G  meaning
3022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      mov reg-or-mem, reg
3023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Is passed the a ptr to the modRM byte, and the data size.  Returns
3024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the address advanced completely over this instruction.
3025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   E(src) is reg-or-mem
3027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   G(dst) is reg.
3028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   If E is reg, -->    GET %E,  tmpv
3030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       PUT tmpv, %G
3031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   If E is mem  -->    (getAddr E) -> tmpa
3033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       LD (tmpa), tmpb
3034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       PUT tmpb, %G
3035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
3036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
3037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong dis_mov_E_G ( VexAbiInfo* vbi,
3038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    Prefix      pfx,
3039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    Int         size,
3040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    Long        delta0 )
3041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int len;
3043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rm = getUChar(delta0);
3044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar dis_buf[50];
3045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (epartIsReg(rm)) {
3047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIRegG(size, pfx, rm, getIRegE(size, pfx, rm));
3048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("mov%c %s,%s\n", nameISize(size),
3049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           nameIRegE(size,pfx,rm),
3050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           nameIRegG(size,pfx,rm));
3051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return 1+delta0;
3052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* E refers to memory */
3055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
3056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp addr = disAMode ( &len, vbi, pfx, delta0, dis_buf, 0 );
3057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIRegG(size, pfx, rm, loadLE(szToITy(size), mkexpr(addr)));
3058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("mov%c %s,%s\n", nameISize(size),
3059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           dis_buf,
3060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           nameIRegG(size,pfx,rm));
3061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return delta0+len;
3062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Handle move instructions of the form
3067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      mov G, E  meaning
3068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      mov reg, reg-or-mem
3069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Is passed the a ptr to the modRM byte, and the data size.  Returns
3070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the address advanced completely over this instruction.
3071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   G(src) is reg.
3073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   E(dst) is reg-or-mem
3074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   If E is reg, -->    GET %G,  tmp
3076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       PUT tmp, %E
3077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   If E is mem, -->    (getAddr E) -> tmpa
3079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       GET %G, tmpv
3080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       ST tmpv, (tmpa)
3081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
3082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
3083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong dis_mov_G_E ( VexAbiInfo* vbi,
3084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    Prefix      pfx,
3085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    Int         size,
3086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    Long        delta0 )
3087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int len;
3089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rm = getUChar(delta0);
3090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar dis_buf[50];
3091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (epartIsReg(rm)) {
3093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIRegE(size, pfx, rm, getIRegG(size, pfx, rm));
3094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("mov%c %s,%s\n", nameISize(size),
3095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           nameIRegG(size,pfx,rm),
3096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           nameIRegE(size,pfx,rm));
3097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return 1+delta0;
3098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* E refers to memory */
3101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
3102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp addr = disAMode ( &len, vbi, pfx, delta0, dis_buf, 0 );
3103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      storeLE( mkexpr(addr), getIRegG(size, pfx, rm) );
3104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("mov%c %s,%s\n", nameISize(size),
3105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           nameIRegG(size,pfx,rm),
3106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           dis_buf);
3107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return len+delta0;
3108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* op $immediate, AL/AX/EAX/RAX. */
3113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
3114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong dis_op_imm_A ( Int    size,
3115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     Bool   carrying,
3116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     IROp   op8,
3117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     Bool   keep,
3118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     Long   delta,
3119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     HChar* t_amd64opc )
3120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int    size4 = imin(size,4);
3122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty    = szToITy(size);
3123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp dst0  = newTemp(ty);
3124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp src   = newTemp(ty);
3125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp dst1  = newTemp(ty);
3126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Long  lit    = getSDisp(size4,delta);
3127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(dst0, getIRegRAX(size));
3128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(src,  mkU(ty,lit & mkSizeMask(size)));
3129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (isAddSub(op8) && !carrying) {
3131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)) );
3132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      setFlags_DEP1_DEP2(op8, dst0, src, ty);
3133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
3135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (isLogic(op8)) {
3136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(!carrying);
3137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)) );
3138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      setFlags_DEP1(op8, dst1, ty);
3139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
3141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (op8 == Iop_Add8 && carrying) {
3142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      helper_ADC( size, dst1, dst0, src,
3143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  /*no store*/IRTemp_INVALID, IRTemp_INVALID, 0 );
3144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
3146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (op8 == Iop_Sub8 && carrying) {
3147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      helper_SBB( size, dst1, dst0, src,
3148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  /*no store*/IRTemp_INVALID, IRTemp_INVALID, 0 );
3149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
3151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vpanic("dis_op_imm_A(amd64,guest)");
3152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (keep)
3154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIRegRAX(size, mkexpr(dst1));
3155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DIP("%s%c $%lld, %s\n", t_amd64opc, nameISize(size),
3157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           lit, nameIRegRAX(size));
3158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return delta+size4;
3159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Sign- and Zero-extending moves. */
3163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
3164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong dis_movx_E_G ( VexAbiInfo* vbi,
3165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     Prefix pfx,
3166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     Long delta, Int szs, Int szd, Bool sign_extend )
3167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rm = getUChar(delta);
3169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (epartIsReg(rm)) {
3170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIRegG(szd, pfx, rm,
3171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    doScalarWidening(
3172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       szs,szd,sign_extend,
3173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       getIRegE(szs,pfx,rm)));
3174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("mov%c%c%c %s,%s\n", sign_extend ? 's' : 'z',
3175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               nameISize(szs),
3176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               nameISize(szd),
3177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               nameIRegE(szs,pfx,rm),
3178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               nameIRegG(szd,pfx,rm));
3179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return 1+delta;
3180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* E refers to memory */
3183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
3184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int    len;
3185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HChar  dis_buf[50];
3186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp addr = disAMode ( &len, vbi, pfx, delta, dis_buf, 0 );
3187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIRegG(szd, pfx, rm,
3188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    doScalarWidening(
3189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       szs,szd,sign_extend,
3190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       loadLE(szToITy(szs),mkexpr(addr))));
3191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("mov%c%c%c %s,%s\n", sign_extend ? 's' : 'z',
3192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               nameISize(szs),
3193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               nameISize(szd),
3194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               dis_buf,
3195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               nameIRegG(szd,pfx,rm));
3196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return len+delta;
3197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate code to divide ArchRegs RDX:RAX / EDX:EAX / DX:AX / AX by
3202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the 64 / 32 / 16 / 8 bit quantity in the given IRTemp.  */
3203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
3204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid codegen_div ( Int sz, IRTemp t, Bool signed_divide )
3205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* special-case the 64-bit case */
3207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (sz == 8) {
3208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IROp   op     = signed_divide ? Iop_DivModS128to64
3209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    : Iop_DivModU128to64;
3210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp src128 = newTemp(Ity_I128);
3211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp dst128 = newTemp(Ity_I128);
3212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( src128, binop(Iop_64HLto128,
3213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            getIReg64(R_RDX),
3214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            getIReg64(R_RAX)) );
3215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( dst128, binop(op, mkexpr(src128), mkexpr(t)) );
3216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIReg64( R_RAX, unop(Iop_128to64,mkexpr(dst128)) );
3217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIReg64( R_RDX, unop(Iop_128HIto64,mkexpr(dst128)) );
3218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
3219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IROp   op    = signed_divide ? Iop_DivModS64to32
3220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   : Iop_DivModU64to32;
3221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp src64 = newTemp(Ity_I64);
3222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp dst64 = newTemp(Ity_I64);
3223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (sz) {
3224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 4:
3225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( src64,
3226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(Iop_32HLto64, getIRegRDX(4), getIRegRAX(4)) );
3227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( dst64,
3228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(op, mkexpr(src64), mkexpr(t)) );
3229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegRAX( 4, unop(Iop_64to32,mkexpr(dst64)) );
3230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegRDX( 4, unop(Iop_64HIto32,mkexpr(dst64)) );
3231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2: {
3233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IROp widen3264 = signed_divide ? Iop_32Sto64 : Iop_32Uto64;
3234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IROp widen1632 = signed_divide ? Iop_16Sto32 : Iop_16Uto32;
3235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( src64, unop(widen3264,
3236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             binop(Iop_16HLto32,
3237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   getIRegRDX(2),
3238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   getIRegRAX(2))) );
3239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( dst64, binop(op, mkexpr(src64), unop(widen1632,mkexpr(t))) );
3240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegRAX( 2, unop(Iop_32to16,unop(Iop_64to32,mkexpr(dst64))) );
3241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegRDX( 2, unop(Iop_32to16,unop(Iop_64HIto32,mkexpr(dst64))) );
3242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 1: {
3245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IROp widen3264 = signed_divide ? Iop_32Sto64 : Iop_32Uto64;
3246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IROp widen1632 = signed_divide ? Iop_16Sto32 : Iop_16Uto32;
3247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IROp widen816  = signed_divide ? Iop_8Sto16  : Iop_8Uto16;
3248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( src64, unop(widen3264,
3249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        unop(widen1632, getIRegRAX(2))) );
3250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( dst64,
3251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(op, mkexpr(src64),
3252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           unop(widen1632, unop(widen816, mkexpr(t)))) );
3253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegRAX( 1, unop(Iop_16to8,
3254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        unop(Iop_32to16,
3255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        unop(Iop_64to32,mkexpr(dst64)))) );
3256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegAH( unop(Iop_16to8,
3257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    unop(Iop_32to16,
3258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    unop(Iop_64HIto32,mkexpr(dst64)))) );
3259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
3262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("codegen_div(amd64)");
3263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
3268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong dis_Grp1 ( VexAbiInfo* vbi,
3269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 Prefix pfx,
3270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 Long delta, UChar modrm,
3271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 Int am_sz, Int d_sz, Int sz, Long d64 )
3272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     len;
3274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar   dis_buf[50];
3275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType  ty   = szToITy(sz);
3276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  dst1 = newTemp(ty);
3277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  src  = newTemp(ty);
3278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  dst0 = newTemp(ty);
3279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  addr = IRTemp_INVALID;
3280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IROp    op8  = Iop_INVALID;
3281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong   mask = mkSizeMask(sz);
3282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (gregLO3ofRM(modrm)) {
3284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0: op8 = Iop_Add8; break;  case 1: op8 = Iop_Or8;  break;
3285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2: break;  // ADC
3286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 3: break;  // SBB
3287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 4: op8 = Iop_And8; break;  case 5: op8 = Iop_Sub8; break;
3288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 6: op8 = Iop_Xor8; break;  case 7: op8 = Iop_Sub8; break;
3289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*NOTREACHED*/
3290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vpanic("dis_Grp1(amd64): unhandled case");
3291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (epartIsReg(modrm)) {
3294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(am_sz == 1);
3295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(dst0, getIRegE(sz,pfx,modrm));
3297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(src,  mkU(ty,d64 & mask));
3298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (gregLO3ofRM(modrm) == 2 /* ADC */) {
3300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         helper_ADC( sz, dst1, dst0, src,
3301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     /*no store*/IRTemp_INVALID, IRTemp_INVALID, 0 );
3302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else
3303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (gregLO3ofRM(modrm) == 3 /* SBB */) {
3304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         helper_SBB( sz, dst1, dst0, src,
3305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     /*no store*/IRTemp_INVALID, IRTemp_INVALID, 0 );
3306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
3307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)));
3308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (isAddSub(op8))
3309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            setFlags_DEP1_DEP2(op8, dst0, src, ty);
3310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
3311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            setFlags_DEP1(op8, dst1, ty);
3312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (gregLO3ofRM(modrm) < 7)
3315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegE(sz, pfx, modrm, mkexpr(dst1));
3316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delta += (am_sz + d_sz);
3318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("%s%c $%lld, %s\n",
3319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          nameGrp1(gregLO3ofRM(modrm)), nameISize(sz), d64,
3320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          nameIRegE(sz,pfx,modrm));
3321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
3322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addr = disAMode ( &len, vbi, pfx, delta, dis_buf, /*xtra*/d_sz );
3323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(dst0, loadLE(ty,mkexpr(addr)));
3325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(src, mkU(ty,d64 & mask));
3326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (gregLO3ofRM(modrm) == 2 /* ADC */) {
3328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (pfx & PFX_LOCK) {
3329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* cas-style store */
3330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            helper_ADC( sz, dst1, dst0, src,
3331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       /*store*/addr, dst0/*expVal*/, guest_RIP_curr_instr );
3332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
3333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* normal store */
3334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            helper_ADC( sz, dst1, dst0, src,
3335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        /*store*/addr, IRTemp_INVALID, 0 );
3336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else
3338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (gregLO3ofRM(modrm) == 3 /* SBB */) {
3339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (pfx & PFX_LOCK) {
3340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* cas-style store */
3341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            helper_SBB( sz, dst1, dst0, src,
3342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       /*store*/addr, dst0/*expVal*/, guest_RIP_curr_instr );
3343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
3344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* normal store */
3345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            helper_SBB( sz, dst1, dst0, src,
3346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        /*store*/addr, IRTemp_INVALID, 0 );
3347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
3349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)));
3350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (gregLO3ofRM(modrm) < 7) {
3351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (pfx & PFX_LOCK) {
3352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               casLE( mkexpr(addr), mkexpr(dst0)/*expVal*/,
3353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    mkexpr(dst1)/*newVal*/,
3354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    guest_RIP_curr_instr );
3355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
3356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               storeLE(mkexpr(addr), mkexpr(dst1));
3357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (isAddSub(op8))
3360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            setFlags_DEP1_DEP2(op8, dst0, src, ty);
3361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
3362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            setFlags_DEP1(op8, dst1, ty);
3363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delta += (len+d_sz);
3366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("%s%c $%lld, %s\n",
3367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          nameGrp1(gregLO3ofRM(modrm)), nameISize(sz),
3368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          d64, dis_buf);
3369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return delta;
3371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Group 2 extended opcodes.  shift_expr must be an 8-bit typed
3375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   expression. */
3376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
3378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong dis_Grp2 ( VexAbiInfo* vbi,
3379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 Prefix pfx,
3380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 Long delta, UChar modrm,
3381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 Int am_sz, Int d_sz, Int sz, IRExpr* shift_expr,
3382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 HChar* shift_expr_txt, Bool* decode_OK )
3383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* delta on entry points at the modrm byte. */
3385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar  dis_buf[50];
3386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int    len;
3387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool   isShift, isRotate, isRotateC;
3388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty    = szToITy(sz);
3389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp dst0  = newTemp(ty);
3390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp dst1  = newTemp(ty);
3391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp addr  = IRTemp_INVALID;
3392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *decode_OK = True;
3394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(sz == 1 || sz == 2 || sz == 4 || sz == 8);
3396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Put value to shift/rotate in dst0. */
3398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (epartIsReg(modrm)) {
3399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(dst0, getIRegE(sz, pfx, modrm));
3400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delta += (am_sz + d_sz);
3401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
3402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addr = disAMode ( &len, vbi, pfx, delta, dis_buf, /*xtra*/d_sz );
3403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(dst0, loadLE(ty,mkexpr(addr)));
3404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delta += len + d_sz;
3405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   isShift = False;
3408b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   switch (gregLO3ofRM(modrm)) { case 4: case 5: case 6: case 7: isShift = True; }
3409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   isRotate = False;
3411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (gregLO3ofRM(modrm)) { case 0: case 1: isRotate = True; }
3412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   isRotateC = False;
3414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (gregLO3ofRM(modrm)) { case 2: case 3: isRotateC = True; }
3415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!isShift && !isRotate && !isRotateC) {
3417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*NOTREACHED*/
3418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vpanic("dis_Grp2(Reg): unhandled case(amd64)");
3419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (isRotateC) {
3422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Call a helper; this insn is so ridiculous it does not deserve
3423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         better.  One problem is, the helper has to calculate both the
3424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         new value and the new flags.  This is more than 64 bits, and
3425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         there is no way to return more than 64 bits from the helper.
3426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Hence the crude and obvious solution is to call it twice,
3427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         using the sign of the sz field to indicate whether it is the
3428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         value or rflags result we want.
3429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      */
3430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool     left = toBool(gregLO3ofRM(modrm) == 2);
3431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRExpr** argsVALUE;
3432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRExpr** argsRFLAGS;
3433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp new_value  = newTemp(Ity_I64);
3435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp new_rflags = newTemp(Ity_I64);
3436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp old_rflags = newTemp(Ity_I64);
3437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( old_rflags, widenUto64(mk_amd64g_calculate_rflags_all()) );
3439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      argsVALUE
3441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = mkIRExprVec_4( widenUto64(mkexpr(dst0)), /* thing to rotate */
3442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          widenUto64(shift_expr),   /* rotate amount */
3443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          mkexpr(old_rflags),
3444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          mkU64(sz) );
3445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( new_value,
3446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 mkIRExprCCall(
3447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    Ity_I64,
3448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    0/*regparm*/,
3449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    left ? "amd64g_calculate_RCL" : "amd64g_calculate_RCR",
3450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    left ? &amd64g_calculate_RCL  : &amd64g_calculate_RCR,
3451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    argsVALUE
3452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 )
3453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            );
3454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      argsRFLAGS
3456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = mkIRExprVec_4( widenUto64(mkexpr(dst0)), /* thing to rotate */
3457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          widenUto64(shift_expr),   /* rotate amount */
3458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          mkexpr(old_rflags),
3459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          mkU64(-sz) );
3460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( new_rflags,
3461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 mkIRExprCCall(
3462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    Ity_I64,
3463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    0/*regparm*/,
3464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    left ? "amd64g_calculate_RCL" : "amd64g_calculate_RCR",
3465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    left ? &amd64g_calculate_RCL  : &amd64g_calculate_RCR,
3466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    argsRFLAGS
3467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 )
3468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            );
3469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( dst1, narrowTo(ty, mkexpr(new_value)) );
3471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt( IRStmt_Put( OFFB_CC_OP,   mkU64(AMD64G_CC_OP_COPY) ));
3472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt( IRStmt_Put( OFFB_CC_DEP1, mkexpr(new_rflags) ));
3473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt( IRStmt_Put( OFFB_CC_DEP2, mkU64(0) ));
3474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt( IRStmt_Put( OFFB_CC_NDEP, mkU64(0) ));
3475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
3478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (isShift) {
3479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp pre64     = newTemp(Ity_I64);
3481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp res64     = newTemp(Ity_I64);
3482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp res64ss   = newTemp(Ity_I64);
3483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp shift_amt = newTemp(Ity_I8);
3484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar  mask      = toUChar(sz==8 ? 63 : 31);
3485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IROp   op64;
3486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (gregLO3ofRM(modrm)) {
3488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 4: op64 = Iop_Shl64; break;
3489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 5: op64 = Iop_Shr64; break;
3490b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 6: op64 = Iop_Shl64; break;
3491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 7: op64 = Iop_Sar64; break;
3492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /*NOTREACHED*/
3493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default: vpanic("dis_Grp2:shift"); break;
3494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Widen the value to be shifted to 64 bits, do the shift, and
3497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         narrow back down.  This seems surprisingly long-winded, but
3498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         unfortunately the AMD semantics requires that 8/16/32-bit
3499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         shifts give defined results for shift values all the way up
3500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         to 32, and this seems the simplest way to do it.  It has the
3501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         advantage that the only IR level shifts generated are of 64
3502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bit values, and the shift amount is guaranteed to be in the
3503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         range 0 .. 63, thereby observing the IR semantics requiring
3504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         all shift values to be in the range 0 .. 2^word_size-1.
3505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Therefore the shift amount is masked with 63 for 64-bit shifts
3507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         and 31 for all others.
3508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      */
3509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* shift_amt = shift_expr & MASK, regardless of operation size */
3510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( shift_amt, binop(Iop_And8, shift_expr, mkU8(mask)) );
3511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* suitably widen the value to be shifted to 64 bits. */
3513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( pre64, op64==Iop_Sar64 ? widenSto64(mkexpr(dst0))
3514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     : widenUto64(mkexpr(dst0)) );
3515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* res64 = pre64 `shift` shift_amt */
3517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( res64, binop(op64, mkexpr(pre64), mkexpr(shift_amt)) );
3518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* res64ss = pre64 `shift` ((shift_amt - 1) & MASK) */
3520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( res64ss,
3521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              binop(op64,
3522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    mkexpr(pre64),
3523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    binop(Iop_And8,
3524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          binop(Iop_Sub8,
3525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                mkexpr(shift_amt), mkU8(1)),
3526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          mkU8(mask))) );
3527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Build the flags thunk. */
3529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      setFlags_DEP1_DEP2_shift(op64, res64, res64ss, ty, shift_amt);
3530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Narrow the result back down. */
3532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( dst1, narrowTo(ty, mkexpr(res64)) );
3533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* if (isShift) */
3535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
3537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (isRotate) {
3538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int    ccOp      = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1
3539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        : (ty==Ity_I32 ? 2 : 3));
3540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool   left      = toBool(gregLO3ofRM(modrm) == 0);
3541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp rot_amt   = newTemp(Ity_I8);
3542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp rot_amt64 = newTemp(Ity_I8);
3543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp oldFlags  = newTemp(Ity_I64);
3544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar  mask      = toUChar(sz==8 ? 63 : 31);
3545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* rot_amt = shift_expr & mask */
3547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* By masking the rotate amount thusly, the IR-level Shl/Shr
3548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         expressions never shift beyond the word size and thus remain
3549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         well defined. */
3550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(rot_amt64, binop(Iop_And8, shift_expr, mkU8(mask)));
3551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_I64)
3553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(rot_amt, mkexpr(rot_amt64));
3554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
3555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(rot_amt, binop(Iop_And8, mkexpr(rot_amt64), mkU8(8*sz-1)));
3556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (left) {
3558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* dst1 = (dst0 << rot_amt) | (dst0 >>u (wordsize-rot_amt)) */
3560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(dst1,
3561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            binop( mkSizedOp(ty,Iop_Or8),
3562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   binop( mkSizedOp(ty,Iop_Shl8),
3563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          mkexpr(dst0),
3564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          mkexpr(rot_amt)
3565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   ),
3566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   binop( mkSizedOp(ty,Iop_Shr8),
3567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          mkexpr(dst0),
3568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          binop(Iop_Sub8,mkU8(8*sz), mkexpr(rot_amt))
3569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   )
3570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            )
3571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         );
3572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ccOp += AMD64G_CC_OP_ROLB;
3573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else { /* right */
3575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* dst1 = (dst0 >>u rot_amt) | (dst0 << (wordsize-rot_amt)) */
3577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(dst1,
3578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            binop( mkSizedOp(ty,Iop_Or8),
3579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   binop( mkSizedOp(ty,Iop_Shr8),
3580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          mkexpr(dst0),
3581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          mkexpr(rot_amt)
3582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   ),
3583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   binop( mkSizedOp(ty,Iop_Shl8),
3584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          mkexpr(dst0),
3585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          binop(Iop_Sub8,mkU8(8*sz), mkexpr(rot_amt))
3586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   )
3587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            )
3588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         );
3589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ccOp += AMD64G_CC_OP_RORB;
3590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* dst1 now holds the rotated value.  Build flag thunk.  We
3594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         need the resulting value for this, and the previous flags.
3595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Except don't set it if the rotate count is zero. */
3596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(oldFlags, mk_amd64g_calculate_rflags_all());
3598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* CC_DEP1 is the rotated value.  CC_NDEP is flags before. */
3600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt( IRStmt_Put( OFFB_CC_OP,
3601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        IRExpr_Mux0X( mkexpr(rot_amt64),
3602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      IRExpr_Get(OFFB_CC_OP,Ity_I64),
3603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      mkU64(ccOp))) );
3604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt( IRStmt_Put( OFFB_CC_DEP1,
3605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        IRExpr_Mux0X( mkexpr(rot_amt64),
3606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      IRExpr_Get(OFFB_CC_DEP1,Ity_I64),
3607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      widenUto64(mkexpr(dst1)))) );
3608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt( IRStmt_Put( OFFB_CC_DEP2,
3609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        IRExpr_Mux0X( mkexpr(rot_amt64),
3610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      IRExpr_Get(OFFB_CC_DEP2,Ity_I64),
3611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      mkU64(0))) );
3612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt( IRStmt_Put( OFFB_CC_NDEP,
3613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        IRExpr_Mux0X( mkexpr(rot_amt64),
3614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      IRExpr_Get(OFFB_CC_NDEP,Ity_I64),
3615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      mkexpr(oldFlags))) );
3616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* if (isRotate) */
3617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Save result, and finish up. */
3619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (epartIsReg(modrm)) {
3620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIRegE(sz, pfx, modrm, mkexpr(dst1));
3621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (vex_traceflags & VEX_TRACE_FE) {
3622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("%s%c ",
3623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    nameGrp2(gregLO3ofRM(modrm)), nameISize(sz) );
3624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (shift_expr_txt)
3625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("%s", shift_expr_txt);
3626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
3627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppIRExpr(shift_expr);
3628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(", %s\n", nameIRegE(sz,pfx,modrm));
3629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
3631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      storeLE(mkexpr(addr), mkexpr(dst1));
3632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (vex_traceflags & VEX_TRACE_FE) {
3633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("%s%c ",
3634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    nameGrp2(gregLO3ofRM(modrm)), nameISize(sz) );
3635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (shift_expr_txt)
3636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("%s", shift_expr_txt);
3637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
3638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppIRExpr(shift_expr);
3639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(", %s\n", dis_buf);
3640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return delta;
3643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Group 8 extended opcodes (but BT/BTS/BTC/BTR only). */
3647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
3648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong dis_Grp8_Imm ( VexAbiInfo* vbi,
3649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     Prefix pfx,
3650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     Long delta, UChar modrm,
3651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     Int am_sz, Int sz, ULong src_val,
3652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     Bool* decode_OK )
3653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* src_val denotes a d8.
3655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      And delta on entry points at the modrm byte. */
3656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty     = szToITy(sz);
3658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp t2     = newTemp(Ity_I64);
3659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp t2m    = newTemp(Ity_I64);
3660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp t_addr = IRTemp_INVALID;
3661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar  dis_buf[50];
3662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong  mask;
3663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* we're optimists :-) */
3665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *decode_OK = True;
3666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Limit src_val -- the bit offset -- to something within a word.
3668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      The Intel docs say that literal offsets larger than a word are
3669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      masked in this way. */
3670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (sz) {
3671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2:  src_val &= 15; break;
3672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 4:  src_val &= 31; break;
3673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 8:  src_val &= 63; break;
3674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: *decode_OK = False; return delta;
3675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Invent a mask suitable for the operation. */
3678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (gregLO3ofRM(modrm)) {
3679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 4: /* BT */  mask = 0;                  break;
3680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 5: /* BTS */ mask = 1ULL << src_val;    break;
3681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 6: /* BTR */ mask = ~(1ULL << src_val); break;
3682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 7: /* BTC */ mask = 1ULL << src_val;    break;
3683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* If this needs to be extended, probably simplest to make a
3684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            new function to handle the other cases (0 .. 3).  The
3685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Intel docs do however not indicate any use for 0 .. 3, so
3686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            we don't expect this to happen. */
3687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: *decode_OK = False; return delta;
3688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Fetch the value to be tested and modified into t2, which is
3691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      64-bits wide regardless of sz. */
3692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (epartIsReg(modrm)) {
3693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(am_sz == 1);
3694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( t2, widenUto64(getIRegE(sz, pfx, modrm)) );
3695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delta += (am_sz + 1);
3696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("%s%c $0x%llx, %s\n", nameGrp8(gregLO3ofRM(modrm)),
3697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                nameISize(sz),
3698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                src_val, nameIRegE(sz,pfx,modrm));
3699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
3700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int len;
3701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      t_addr = disAMode ( &len, vbi, pfx, delta, dis_buf, 1 );
3702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delta  += (len+1);
3703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( t2, widenUto64(loadLE(ty, mkexpr(t_addr))) );
3704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("%s%c $0x%llx, %s\n", nameGrp8(gregLO3ofRM(modrm)),
3705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                nameISize(sz),
3706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                src_val, dis_buf);
3707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Compute the new value into t2m, if non-BT. */
3710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (gregLO3ofRM(modrm)) {
3711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 4: /* BT */
3712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 5: /* BTS */
3714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( t2m, binop(Iop_Or64, mkU64(mask), mkexpr(t2)) );
3715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 6: /* BTR */
3717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( t2m, binop(Iop_And64, mkU64(mask), mkexpr(t2)) );
3718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 7: /* BTC */
3720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( t2m, binop(Iop_Xor64, mkU64(mask), mkexpr(t2)) );
3721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     default:
3723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /*NOTREACHED*/ /*the previous switch guards this*/
3724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(0);
3725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Write the result back, if non-BT. */
3728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (gregLO3ofRM(modrm) != 4 /* BT */) {
3729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (epartIsReg(modrm)) {
3730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	putIRegE(sz, pfx, modrm, narrowTo(ty, mkexpr(t2m)));
3731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
3732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (pfx & PFX_LOCK) {
3733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            casLE( mkexpr(t_addr),
3734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   narrowTo(ty, mkexpr(t2))/*expd*/,
3735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   narrowTo(ty, mkexpr(t2m))/*new*/,
3736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   guest_RIP_curr_instr );
3737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
3738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            storeLE(mkexpr(t_addr), narrowTo(ty, mkexpr(t2m)));
3739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Copy relevant bit from t2 into the carry flag. */
3744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Flags: C=selected bit, O,S,Z,A,P undefined, so are set to zero. */
3745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_CC_OP,   mkU64(AMD64G_CC_OP_COPY) ));
3746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_CC_DEP2, mkU64(0) ));
3747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put(
3748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            OFFB_CC_DEP1,
3749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            binop(Iop_And64,
3750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(Iop_Shr64, mkexpr(t2), mkU8(src_val)),
3751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  mkU64(1))
3752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       ));
3753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Set NDEP even though it isn't used.  This makes redundant-PUT
3754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      elimination of previous stores to this field work better. */
3755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_CC_NDEP, mkU64(0) ));
3756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return delta;
3758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Signed/unsigned widening multiply.  Generate IR to multiply the
3762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   value in RAX/EAX/AX/AL by the given IRTemp, and park the result in
3763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   RDX:RAX/EDX:EAX/DX:AX/AX.
3764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
3765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void codegen_mulL_A_D ( Int sz, Bool syned,
3766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               IRTemp tmp, HChar* tmp_txt )
3767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = szToITy(sz);
3769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp t1 = newTemp(ty);
3770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( t1, getIRegRAX(sz) );
3772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (ty) {
3774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I64: {
3775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp res128  = newTemp(Ity_I128);
3776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp resHi   = newTemp(Ity_I64);
3777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp resLo   = newTemp(Ity_I64);
3778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IROp   mulOp   = syned ? Iop_MullS64 : Iop_MullU64;
3779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt   tBaseOp = syned ? AMD64G_CC_OP_SMULB : AMD64G_CC_OP_UMULB;
3780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         setFlags_MUL ( Ity_I64, t1, tmp, tBaseOp );
3781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( res128, binop(mulOp, mkexpr(t1), mkexpr(tmp)) );
3782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( resHi, unop(Iop_128HIto64,mkexpr(res128)));
3783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( resLo, unop(Iop_128to64,mkexpr(res128)));
3784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg64(R_RDX, mkexpr(resHi));
3785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg64(R_RAX, mkexpr(resLo));
3786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I32: {
3789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp res64   = newTemp(Ity_I64);
3790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp resHi   = newTemp(Ity_I32);
3791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp resLo   = newTemp(Ity_I32);
3792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IROp   mulOp   = syned ? Iop_MullS32 : Iop_MullU32;
3793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt   tBaseOp = syned ? AMD64G_CC_OP_SMULB : AMD64G_CC_OP_UMULB;
3794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         setFlags_MUL ( Ity_I32, t1, tmp, tBaseOp );
3795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( res64, binop(mulOp, mkexpr(t1), mkexpr(tmp)) );
3796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( resHi, unop(Iop_64HIto32,mkexpr(res64)));
3797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( resLo, unop(Iop_64to32,mkexpr(res64)));
3798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegRDX(4, mkexpr(resHi));
3799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegRAX(4, mkexpr(resLo));
3800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I16: {
3803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp res32   = newTemp(Ity_I32);
3804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp resHi   = newTemp(Ity_I16);
3805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp resLo   = newTemp(Ity_I16);
3806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IROp   mulOp   = syned ? Iop_MullS16 : Iop_MullU16;
3807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt   tBaseOp = syned ? AMD64G_CC_OP_SMULB : AMD64G_CC_OP_UMULB;
3808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         setFlags_MUL ( Ity_I16, t1, tmp, tBaseOp );
3809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( res32, binop(mulOp, mkexpr(t1), mkexpr(tmp)) );
3810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( resHi, unop(Iop_32HIto16,mkexpr(res32)));
3811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( resLo, unop(Iop_32to16,mkexpr(res32)));
3812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegRDX(2, mkexpr(resHi));
3813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegRAX(2, mkexpr(resLo));
3814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I8: {
3817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp res16   = newTemp(Ity_I16);
3818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp resHi   = newTemp(Ity_I8);
3819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp resLo   = newTemp(Ity_I8);
3820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IROp   mulOp   = syned ? Iop_MullS8 : Iop_MullU8;
3821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt   tBaseOp = syned ? AMD64G_CC_OP_SMULB : AMD64G_CC_OP_UMULB;
3822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         setFlags_MUL ( Ity_I8, t1, tmp, tBaseOp );
3823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( res16, binop(mulOp, mkexpr(t1), mkexpr(tmp)) );
3824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( resHi, unop(Iop_16HIto8,mkexpr(res16)));
3825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( resLo, unop(Iop_16to8,mkexpr(res16)));
3826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegRAX(2, mkexpr(res16));
3827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
3830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRType(ty);
3831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("codegen_mulL_A_D(amd64)");
3832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DIP("%s%c %s\n", syned ? "imul" : "mul", nameISize(sz), tmp_txt);
3834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Group 3 extended opcodes. */
3838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
3839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong dis_Grp3 ( VexAbiInfo* vbi,
3840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 Prefix pfx, Int sz, Long delta, Bool* decode_OK )
3841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Long    d64;
3843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar   modrm;
3844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar   dis_buf[50];
3845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     len;
3846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  addr;
3847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType  ty = szToITy(sz);
3848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  t1 = newTemp(ty);
3849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp dst1, src, dst0;
3850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *decode_OK = True;
3851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   modrm = getUChar(delta);
3852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (epartIsReg(modrm)) {
3853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (gregLO3ofRM(modrm)) {
3854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 0: { /* TEST */
3855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            delta++;
3856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            d64 = getSDisp(imin(4,sz), delta);
3857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            delta += imin(4,sz);
3858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dst1 = newTemp(ty);
3859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(dst1, binop(mkSizedOp(ty,Iop_And8),
3860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               getIRegE(sz,pfx,modrm),
3861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               mkU(ty, d64 & mkSizeMask(sz))));
3862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            setFlags_DEP1( Iop_And8, dst1, ty );
3863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("test%c $%lld, %s\n",
3864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                nameISize(sz), d64,
3865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                nameIRegE(sz, pfx, modrm));
3866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
3867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 1:
3869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *decode_OK = False;
3870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return delta;
3871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 2: /* NOT */
3872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            delta++;
3873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putIRegE(sz, pfx, modrm,
3874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              unop(mkSizedOp(ty,Iop_Not8),
3875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   getIRegE(sz, pfx, modrm)));
3876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("not%c %s\n", nameISize(sz),
3877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              nameIRegE(sz, pfx, modrm));
3878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
3879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 3: /* NEG */
3880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            delta++;
3881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dst0 = newTemp(ty);
3882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            src  = newTemp(ty);
3883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dst1 = newTemp(ty);
3884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(dst0, mkU(ty,0));
3885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(src,  getIRegE(sz, pfx, modrm));
3886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(dst1, binop(mkSizedOp(ty,Iop_Sub8), mkexpr(dst0),
3887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                       mkexpr(src)));
3888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            setFlags_DEP1_DEP2(Iop_Sub8, dst0, src, ty);
3889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putIRegE(sz, pfx, modrm, mkexpr(dst1));
3890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("neg%c %s\n", nameISize(sz), nameIRegE(sz, pfx, modrm));
3891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
3892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 4: /* MUL (unsigned widening) */
3893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            delta++;
3894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            src = newTemp(ty);
3895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(src, getIRegE(sz,pfx,modrm));
3896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            codegen_mulL_A_D ( sz, False, src,
3897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               nameIRegE(sz,pfx,modrm) );
3898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
3899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 5: /* IMUL (signed widening) */
3900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            delta++;
3901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            src = newTemp(ty);
3902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(src, getIRegE(sz,pfx,modrm));
3903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            codegen_mulL_A_D ( sz, True, src,
3904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               nameIRegE(sz,pfx,modrm) );
3905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
3906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 6: /* DIV */
3907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            delta++;
3908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( t1, getIRegE(sz, pfx, modrm) );
3909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            codegen_div ( sz, t1, False );
3910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("div%c %s\n", nameISize(sz),
3911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              nameIRegE(sz, pfx, modrm));
3912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
3913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 7: /* IDIV */
3914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            delta++;
3915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( t1, getIRegE(sz, pfx, modrm) );
3916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            codegen_div ( sz, t1, True );
3917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("idiv%c %s\n", nameISize(sz),
3918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               nameIRegE(sz, pfx, modrm));
3919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
3920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
3921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /*NOTREACHED*/
3922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vpanic("Grp3(amd64,R)");
3923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
3925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addr = disAMode ( &len, vbi, pfx, delta, dis_buf,
3926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        /* we have to inform disAMode of any immediate
3927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			   bytes used */
3928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        gregLO3ofRM(modrm)==0/*TEST*/
3929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           ? imin(4,sz)
3930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           : 0
3931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      );
3932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      t1   = newTemp(ty);
3933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delta += len;
3934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(t1, loadLE(ty,mkexpr(addr)));
3935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (gregLO3ofRM(modrm)) {
3936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 0: { /* TEST */
3937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            d64 = getSDisp(imin(4,sz), delta);
3938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            delta += imin(4,sz);
3939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dst1 = newTemp(ty);
3940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(dst1, binop(mkSizedOp(ty,Iop_And8),
3941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               mkexpr(t1),
3942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               mkU(ty, d64 & mkSizeMask(sz))));
3943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            setFlags_DEP1( Iop_And8, dst1, ty );
3944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("test%c $%lld, %s\n", nameISize(sz), d64, dis_buf);
3945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
3946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 1:
3948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *decode_OK = False;
3949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return delta;
3950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 2: /* NOT */
3951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dst1 = newTemp(ty);
3952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(dst1, unop(mkSizedOp(ty,Iop_Not8), mkexpr(t1)));
3953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (pfx & PFX_LOCK) {
3954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               casLE( mkexpr(addr), mkexpr(t1)/*expd*/, mkexpr(dst1)/*new*/,
3955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    guest_RIP_curr_instr );
3956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
3957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               storeLE( mkexpr(addr), mkexpr(dst1) );
3958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("not%c %s\n", nameISize(sz), dis_buf);
3960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
3961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 3: /* NEG */
3962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dst0 = newTemp(ty);
3963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            src  = newTemp(ty);
3964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dst1 = newTemp(ty);
3965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(dst0, mkU(ty,0));
3966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(src,  mkexpr(t1));
3967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(dst1, binop(mkSizedOp(ty,Iop_Sub8), mkexpr(dst0),
3968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                       mkexpr(src)));
3969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (pfx & PFX_LOCK) {
3970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               casLE( mkexpr(addr), mkexpr(t1)/*expd*/, mkexpr(dst1)/*new*/,
3971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    guest_RIP_curr_instr );
3972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
3973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               storeLE( mkexpr(addr), mkexpr(dst1) );
3974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            setFlags_DEP1_DEP2(Iop_Sub8, dst0, src, ty);
3976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("neg%c %s\n", nameISize(sz), dis_buf);
3977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
3978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 4: /* MUL (unsigned widening) */
3979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            codegen_mulL_A_D ( sz, False, t1, dis_buf );
3980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
3981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 5: /* IMUL */
3982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            codegen_mulL_A_D ( sz, True, t1, dis_buf );
3983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
3984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 6: /* DIV */
3985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            codegen_div ( sz, t1, False );
3986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("div%c %s\n", nameISize(sz), dis_buf);
3987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
3988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 7: /* IDIV */
3989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            codegen_div ( sz, t1, True );
3990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("idiv%c %s\n", nameISize(sz), dis_buf);
3991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
3992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
3993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /*NOTREACHED*/
3994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vpanic("Grp3(amd64,M)");
3995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return delta;
3998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Group 4 extended opcodes. */
4002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
4003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong dis_Grp4 ( VexAbiInfo* vbi,
4004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 Prefix pfx, Long delta, Bool* decode_OK )
4005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int   alen;
4007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar modrm;
4008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar dis_buf[50];
4009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = Ity_I8;
4010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp t1 = newTemp(ty);
4011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp t2 = newTemp(ty);
4012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *decode_OK = True;
4014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   modrm = getUChar(delta);
4016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (epartIsReg(modrm)) {
4017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(t1, getIRegE(1, pfx, modrm));
4018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (gregLO3ofRM(modrm)) {
4019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 0: /* INC */
4020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(t2, binop(Iop_Add8, mkexpr(t1), mkU8(1)));
4021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putIRegE(1, pfx, modrm, mkexpr(t2));
4022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            setFlags_INC_DEC( True, t2, ty );
4023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
4024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 1: /* DEC */
4025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(t2, binop(Iop_Sub8, mkexpr(t1), mkU8(1)));
4026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putIRegE(1, pfx, modrm, mkexpr(t2));
4027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            setFlags_INC_DEC( False, t2, ty );
4028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
4029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
4030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *decode_OK = False;
4031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return delta;
4032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delta++;
4034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("%sb %s\n", nameGrp4(gregLO3ofRM(modrm)),
4035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      nameIRegE(1, pfx, modrm));
4036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
4037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
4038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( t1, loadLE(ty, mkexpr(addr)) );
4039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (gregLO3ofRM(modrm)) {
4040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 0: /* INC */
4041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(t2, binop(Iop_Add8, mkexpr(t1), mkU8(1)));
4042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (pfx & PFX_LOCK) {
4043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               casLE( mkexpr(addr), mkexpr(t1)/*expd*/, mkexpr(t2)/*new*/,
4044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      guest_RIP_curr_instr );
4045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
4046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               storeLE( mkexpr(addr), mkexpr(t2) );
4047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
4048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            setFlags_INC_DEC( True, t2, ty );
4049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
4050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 1: /* DEC */
4051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(t2, binop(Iop_Sub8, mkexpr(t1), mkU8(1)));
4052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (pfx & PFX_LOCK) {
4053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               casLE( mkexpr(addr), mkexpr(t1)/*expd*/, mkexpr(t2)/*new*/,
4054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      guest_RIP_curr_instr );
4055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
4056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               storeLE( mkexpr(addr), mkexpr(t2) );
4057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
4058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            setFlags_INC_DEC( False, t2, ty );
4059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
4060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
4061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *decode_OK = False;
4062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return delta;
4063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delta += alen;
4065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("%sb %s\n", nameGrp4(gregLO3ofRM(modrm)), dis_buf);
4066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return delta;
4068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Group 5 extended opcodes. */
4072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
4073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong dis_Grp5 ( VexAbiInfo* vbi,
4074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 Prefix pfx, Int sz, Long delta,
4075663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 /*MOD*/DisResult* dres, /*OUT*/Bool* decode_OK )
4076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     len;
4078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar   modrm;
4079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar   dis_buf[50];
4080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  addr = IRTemp_INVALID;
4081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType  ty = szToITy(sz);
4082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  t1 = newTemp(ty);
4083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  t2 = IRTemp_INVALID;
4084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  t3 = IRTemp_INVALID;
4085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool    showSz = True;
4086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *decode_OK = True;
4088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   modrm = getUChar(delta);
4090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (epartIsReg(modrm)) {
4091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(t1, getIRegE(sz,pfx,modrm));
4092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (gregLO3ofRM(modrm)) {
4093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 0: /* INC */
4094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t2 = newTemp(ty);
4095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(t2, binop(mkSizedOp(ty,Iop_Add8),
4096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             mkexpr(t1), mkU(ty,1)));
4097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            setFlags_INC_DEC( True, t2, ty );
4098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putIRegE(sz,pfx,modrm, mkexpr(t2));
4099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
4100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 1: /* DEC */
4101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t2 = newTemp(ty);
4102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(t2, binop(mkSizedOp(ty,Iop_Sub8),
4103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             mkexpr(t1), mkU(ty,1)));
4104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            setFlags_INC_DEC( False, t2, ty );
4105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putIRegE(sz,pfx,modrm, mkexpr(t2));
4106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
4107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 2: /* call Ev */
4108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Ignore any sz value and operate as if sz==8. */
4109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!(sz == 4 || sz == 8)) goto unhandled;
4110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sz = 8;
4111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t3 = newTemp(Ity_I64);
4112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(t3, getIRegE(sz,pfx,modrm));
4113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t2 = newTemp(Ity_I64);
4114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(t2, binop(Iop_Sub64, getIReg64(R_RSP), mkU64(8)));
4115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putIReg64(R_RSP, mkexpr(t2));
4116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            storeLE( mkexpr(t2), mkU64(guest_RIP_bbstart+delta+1));
4117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            make_redzone_AbiHint(vbi, t2, t3/*nia*/, "call-Ev(reg)");
4118663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            jmp_treg(dres, Ijk_Call, t3);
4119663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            vassert(dres->whatNext == Dis_StopHere);
4120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            showSz = False;
4121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
4122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 4: /* jmp Ev */
4123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Ignore any sz value and operate as if sz==8. */
4124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!(sz == 4 || sz == 8)) goto unhandled;
4125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sz = 8;
4126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t3 = newTemp(Ity_I64);
4127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(t3, getIRegE(sz,pfx,modrm));
4128663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            jmp_treg(dres, Ijk_Boring, t3);
4129663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            vassert(dres->whatNext == Dis_StopHere);
4130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            showSz = False;
4131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
4132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
4133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *decode_OK = False;
4134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return delta;
4135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delta++;
4137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("%s%c %s\n", nameGrp5(gregLO3ofRM(modrm)),
4138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       showSz ? nameISize(sz) : ' ',
4139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       nameIRegE(sz, pfx, modrm));
4140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
4141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addr = disAMode ( &len, vbi, pfx, delta, dis_buf, 0 );
4142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (gregLO3ofRM(modrm) != 2 && gregLO3ofRM(modrm) != 4
4143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  && gregLO3ofRM(modrm) != 6) {
4144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(t1, loadLE(ty,mkexpr(addr)));
4145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (gregLO3ofRM(modrm)) {
4147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 0: /* INC */
4148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t2 = newTemp(ty);
4149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(t2, binop(mkSizedOp(ty,Iop_Add8),
4150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             mkexpr(t1), mkU(ty,1)));
4151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (pfx & PFX_LOCK) {
4152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               casLE( mkexpr(addr),
4153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      mkexpr(t1), mkexpr(t2), guest_RIP_curr_instr );
4154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
4155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               storeLE(mkexpr(addr),mkexpr(t2));
4156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
4157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            setFlags_INC_DEC( True, t2, ty );
4158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
4159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 1: /* DEC */
4160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t2 = newTemp(ty);
4161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(t2, binop(mkSizedOp(ty,Iop_Sub8),
4162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             mkexpr(t1), mkU(ty,1)));
4163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (pfx & PFX_LOCK) {
4164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               casLE( mkexpr(addr),
4165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      mkexpr(t1), mkexpr(t2), guest_RIP_curr_instr );
4166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
4167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               storeLE(mkexpr(addr),mkexpr(t2));
4168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
4169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            setFlags_INC_DEC( False, t2, ty );
4170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
4171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 2: /* call Ev */
4172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Ignore any sz value and operate as if sz==8. */
4173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!(sz == 4 || sz == 8)) goto unhandled;
4174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sz = 8;
4175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t3 = newTemp(Ity_I64);
4176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(t3, loadLE(Ity_I64,mkexpr(addr)));
4177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t2 = newTemp(Ity_I64);
4178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(t2, binop(Iop_Sub64, getIReg64(R_RSP), mkU64(8)));
4179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putIReg64(R_RSP, mkexpr(t2));
4180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            storeLE( mkexpr(t2), mkU64(guest_RIP_bbstart+delta+len));
4181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            make_redzone_AbiHint(vbi, t2, t3/*nia*/, "call-Ev(mem)");
4182663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            jmp_treg(dres, Ijk_Call, t3);
4183663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            vassert(dres->whatNext == Dis_StopHere);
4184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            showSz = False;
4185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
4186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 4: /* JMP Ev */
4187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Ignore any sz value and operate as if sz==8. */
4188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!(sz == 4 || sz == 8)) goto unhandled;
4189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sz = 8;
4190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t3 = newTemp(Ity_I64);
4191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(t3, loadLE(Ity_I64,mkexpr(addr)));
4192663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            jmp_treg(dres, Ijk_Boring, t3);
4193663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            vassert(dres->whatNext == Dis_StopHere);
4194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            showSz = False;
4195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
4196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 6: /* PUSH Ev */
4197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* There is no encoding for 32-bit operand size; hence ... */
4198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (sz == 4) sz = 8;
4199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!(sz == 8 || sz == 2)) goto unhandled;
4200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (sz == 8) {
4201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               t3 = newTemp(Ity_I64);
4202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(t3, loadLE(Ity_I64,mkexpr(addr)));
4203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               t2 = newTemp(Ity_I64);
4204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign( t2, binop(Iop_Sub64,getIReg64(R_RSP),mkU64(sz)) );
4205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putIReg64(R_RSP, mkexpr(t2) );
4206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               storeLE( mkexpr(t2), mkexpr(t3) );
4207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
4208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    } else {
4209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto unhandled; /* awaiting test case */
4210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    }
4211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
4212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         unhandled:
4213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *decode_OK = False;
4214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return delta;
4215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delta += len;
4217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("%s%c %s\n", nameGrp5(gregLO3ofRM(modrm)),
4218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       showSz ? nameISize(sz) : ' ',
4219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       dis_buf);
4220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return delta;
4222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
4226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Disassembling string ops (including REP prefixes)    ---*/
4227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
4228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Code shared by all the string ops */
4230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
4231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid dis_string_op_increment ( Int sz, IRTemp t_inc )
4232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar logSz;
4234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (sz == 8 || sz == 4 || sz == 2) {
4235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      logSz = 1;
4236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (sz == 4) logSz = 2;
4237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (sz == 8) logSz = 3;
4238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( t_inc,
4239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              binop(Iop_Shl64, IRExpr_Get( OFFB_DFLAG, Ity_I64 ),
4240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               mkU8(logSz) ) );
4241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
4242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( t_inc,
4243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              IRExpr_Get( OFFB_DFLAG, Ity_I64 ) );
4244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
4248b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid dis_string_op( void (*dis_OP)( Int, IRTemp, Prefix pfx ),
4249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    Int sz, HChar* name, Prefix pfx )
4250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp t_inc = newTemp(Ity_I64);
4252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Really we ought to inspect the override prefixes, but we don't.
4253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      The following assertion catches any resulting sillyness. */
4254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(pfx == clearSegBits(pfx));
4255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   dis_string_op_increment(sz, t_inc);
4256b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   dis_OP( sz, t_inc, pfx );
4257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DIP("%s%c\n", name, nameISize(sz));
4258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
4261b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid dis_MOVS ( Int sz, IRTemp t_inc, Prefix pfx )
4262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = szToITy(sz);
4264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp td = newTemp(Ity_I64);   /* RDI */
4265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp ts = newTemp(Ity_I64);   /* RSI */
4266b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRExpr *incd, *incs;
4267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4268b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (haveASO(pfx)) {
4269b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      assign( td, unop(Iop_32Uto64, getIReg32(R_RDI)) );
4270b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      assign( ts, unop(Iop_32Uto64, getIReg32(R_RSI)) );
4271b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   } else {
4272b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      assign( td, getIReg64(R_RDI) );
4273b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      assign( ts, getIReg64(R_RSI) );
4274b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
4275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   storeLE( mkexpr(td), loadLE(ty,mkexpr(ts)) );
4277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4278b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   incd = binop(Iop_Add64, mkexpr(td), mkexpr(t_inc));
4279b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   incs = binop(Iop_Add64, mkexpr(ts), mkexpr(t_inc));
4280b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (haveASO(pfx)) {
4281b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      incd = unop(Iop_32Uto64, unop(Iop_64to32, incd));
4282b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      incs = unop(Iop_32Uto64, unop(Iop_64to32, incs));
4283b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
4284b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   putIReg64( R_RDI, incd );
4285b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   putIReg64( R_RSI, incs );
4286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
4289b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid dis_LODS ( Int sz, IRTemp t_inc, Prefix pfx )
4290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = szToITy(sz);
4292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp ts = newTemp(Ity_I64);   /* RSI */
4293b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRExpr *incs;
4294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4295b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (haveASO(pfx))
4296b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      assign( ts, unop(Iop_32Uto64, getIReg32(R_RSI)) );
4297b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   else
4298b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      assign( ts, getIReg64(R_RSI) );
4299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   putIRegRAX ( sz, loadLE(ty, mkexpr(ts)) );
4301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4302b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   incs = binop(Iop_Add64, mkexpr(ts), mkexpr(t_inc));
4303b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (haveASO(pfx))
4304b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      incs = unop(Iop_32Uto64, unop(Iop_64to32, incs));
4305b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   putIReg64( R_RSI, incs );
4306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
4309b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid dis_STOS ( Int sz, IRTemp t_inc, Prefix pfx )
4310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = szToITy(sz);
4312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp ta = newTemp(ty);        /* rAX */
4313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp td = newTemp(Ity_I64);   /* RDI */
4314b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRExpr *incd;
4315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( ta, getIRegRAX(sz) );
4317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4318b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (haveASO(pfx))
4319b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      assign( td, unop(Iop_32Uto64, getIReg32(R_RDI)) );
4320b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   else
4321b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      assign( td, getIReg64(R_RDI) );
4322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   storeLE( mkexpr(td), mkexpr(ta) );
4324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4325b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   incd = binop(Iop_Add64, mkexpr(td), mkexpr(t_inc));
4326b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (haveASO(pfx))
4327b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      incd = unop(Iop_32Uto64, unop(Iop_64to32, incd));
4328b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   putIReg64( R_RDI, incd );
4329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
4332b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid dis_CMPS ( Int sz, IRTemp t_inc, Prefix pfx )
4333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty  = szToITy(sz);
4335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp tdv = newTemp(ty);      /* (RDI) */
4336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp tsv = newTemp(ty);      /* (RSI) */
4337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp td  = newTemp(Ity_I64); /*  RDI  */
4338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp ts  = newTemp(Ity_I64); /*  RSI  */
4339b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRExpr *incd, *incs;
4340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4341b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (haveASO(pfx)) {
4342b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      assign( td, unop(Iop_32Uto64, getIReg32(R_RDI)) );
4343b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      assign( ts, unop(Iop_32Uto64, getIReg32(R_RSI)) );
4344b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   } else {
4345b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      assign( td, getIReg64(R_RDI) );
4346b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      assign( ts, getIReg64(R_RSI) );
4347b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
4348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( tdv, loadLE(ty,mkexpr(td)) );
4350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( tsv, loadLE(ty,mkexpr(ts)) );
4352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   setFlags_DEP1_DEP2 ( Iop_Sub8, tsv, tdv, ty );
4354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4355b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   incd = binop(Iop_Add64, mkexpr(td), mkexpr(t_inc));
4356b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   incs = binop(Iop_Add64, mkexpr(ts), mkexpr(t_inc));
4357b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (haveASO(pfx)) {
4358b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      incd = unop(Iop_32Uto64, unop(Iop_64to32, incd));
4359b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      incs = unop(Iop_32Uto64, unop(Iop_64to32, incs));
4360b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
4361b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   putIReg64( R_RDI, incd );
4362b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   putIReg64( R_RSI, incs );
4363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
4366b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid dis_SCAS ( Int sz, IRTemp t_inc, Prefix pfx )
4367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty  = szToITy(sz);
4369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp ta  = newTemp(ty);       /*  rAX  */
4370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp td  = newTemp(Ity_I64);  /*  RDI  */
4371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp tdv = newTemp(ty);       /* (RDI) */
4372b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRExpr *incd;
4373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( ta, getIRegRAX(sz) );
4375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4376b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (haveASO(pfx))
4377b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      assign( td, unop(Iop_32Uto64, getIReg32(R_RDI)) );
4378b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   else
4379b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      assign( td, getIReg64(R_RDI) );
4380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( tdv, loadLE(ty,mkexpr(td)) );
4382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   setFlags_DEP1_DEP2 ( Iop_Sub8, ta, tdv, ty );
4384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4385b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   incd = binop(Iop_Add64, mkexpr(td), mkexpr(t_inc));
4386b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (haveASO(pfx))
4387b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      incd = unop(Iop_32Uto64, unop(Iop_64to32, incd));
4388b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   putIReg64( R_RDI, incd );
4389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Wrap the appropriate string op inside a REP/REPE/REPNE.  We assume
4393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the insn is the last one in the basic block, and so emit a jump to
4394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the next insn, rather than just falling through. */
4395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
4396663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengvoid dis_REP_op ( /*MOD*/DisResult* dres,
4397663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  AMD64Condcode cond,
4398b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  void (*dis_OP)(Int, IRTemp, Prefix),
4399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  Int sz, Addr64 rip, Addr64 rip_next, HChar* name,
4400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  Prefix pfx )
4401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp t_inc = newTemp(Ity_I64);
4403b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp tc;
4404b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRExpr* cmp;
4405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Really we ought to inspect the override prefixes, but we don't.
4407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      The following assertion catches any resulting sillyness. */
4408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(pfx == clearSegBits(pfx));
4409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4410b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (haveASO(pfx)) {
4411b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      tc = newTemp(Ity_I32);  /*  ECX  */
4412b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      assign( tc, getIReg32(R_RCX) );
4413b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      cmp = binop(Iop_CmpEQ32, mkexpr(tc), mkU32(0));
4414b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   } else {
4415b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      tc = newTemp(Ity_I64);  /*  RCX  */
4416b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      assign( tc, getIReg64(R_RCX) );
4417b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      cmp = binop(Iop_CmpEQ64, mkexpr(tc), mkU64(0));
4418b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
4419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4420663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   stmt( IRStmt_Exit( cmp, Ijk_Boring,
4421663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      IRConst_U64(rip_next), OFFB_RIP ) );
4422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4423b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (haveASO(pfx))
4424b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      putIReg32(R_RCX, binop(Iop_Sub32, mkexpr(tc), mkU32(1)) );
4425b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  else
4426b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      putIReg64(R_RCX, binop(Iop_Sub64, mkexpr(tc), mkU64(1)) );
4427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   dis_string_op_increment(sz, t_inc);
4429b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   dis_OP (sz, t_inc, pfx);
4430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (cond == AMD64CondAlways) {
4432663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      jmp_lit(dres, Ijk_Boring, rip);
4433663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(dres->whatNext == Dis_StopHere);
4434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
4435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt( IRStmt_Exit( mk_amd64g_calculate_condition(cond),
4436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         Ijk_Boring,
4437663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         IRConst_U64(rip),
4438663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         OFFB_RIP ) );
4439663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      jmp_lit(dres, Ijk_Boring, rip_next);
4440663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(dres->whatNext == Dis_StopHere);
4441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DIP("%s%c\n", name, nameISize(sz));
4443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
4447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Arithmetic, etc.                                     ---*/
4448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
4449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* IMUL E, G.  Supplied eip points to the modR/M byte. */
4451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
4452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong dis_mul_E_G ( VexAbiInfo* vbi,
4453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    Prefix      pfx,
4454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    Int         size,
4455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    Long        delta0 )
4456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int    alen;
4458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar  dis_buf[50];
4459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar  rm = getUChar(delta0);
4460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = szToITy(size);
4461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp te = newTemp(ty);
4462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp tg = newTemp(ty);
4463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp resLo = newTemp(ty);
4464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( tg, getIRegG(size, pfx, rm) );
4466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (epartIsReg(rm)) {
4467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( te, getIRegE(size, pfx, rm) );
4468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
4469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp addr = disAMode( &alen, vbi, pfx, delta0, dis_buf, 0 );
4470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( te, loadLE(ty,mkexpr(addr)) );
4471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   setFlags_MUL ( ty, te, tg, AMD64G_CC_OP_SMULB );
4474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( resLo, binop( mkSizedOp(ty, Iop_Mul8), mkexpr(te), mkexpr(tg) ) );
4476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   putIRegG(size, pfx, rm, mkexpr(resLo) );
4478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (epartIsReg(rm)) {
4480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("imul%c %s, %s\n", nameISize(size),
4481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             nameIRegE(size,pfx,rm),
4482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             nameIRegG(size,pfx,rm));
4483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return 1+delta0;
4484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
4485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("imul%c %s, %s\n", nameISize(size),
4486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             dis_buf,
4487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             nameIRegG(size,pfx,rm));
4488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return alen+delta0;
4489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* IMUL I * E -> G.  Supplied rip points to the modR/M byte. */
4494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
4495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong dis_imul_I_E_G ( VexAbiInfo* vbi,
4496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       Prefix      pfx,
4497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       Int         size,
4498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       Long        delta,
4499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       Int         litsize )
4500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Long   d64;
4502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int    alen;
4503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar  dis_buf[50];
4504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar  rm = getUChar(delta);
4505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = szToITy(size);
4506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp te = newTemp(ty);
4507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp tl = newTemp(ty);
4508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp resLo = newTemp(ty);
4509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(/*size == 1 ||*/ size == 2 || size == 4 || size == 8);
4511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (epartIsReg(rm)) {
4513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(te, getIRegE(size, pfx, rm));
4514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delta++;
4515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
4516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp addr = disAMode( &alen, vbi, pfx, delta, dis_buf,
4517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     imin(4,litsize) );
4518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(te, loadLE(ty, mkexpr(addr)));
4519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delta += alen;
4520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   d64 = getSDisp(imin(4,litsize),delta);
4522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   delta += imin(4,litsize);
4523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   d64 &= mkSizeMask(size);
4525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(tl, mkU(ty,d64));
4526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( resLo, binop( mkSizedOp(ty, Iop_Mul8), mkexpr(te), mkexpr(tl) ));
4528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   setFlags_MUL ( ty, te, tl, AMD64G_CC_OP_SMULB );
4530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   putIRegG(size, pfx, rm, mkexpr(resLo));
4532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DIP("imul%c $%lld, %s, %s\n",
4534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       nameISize(size), d64,
4535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       ( epartIsReg(rm) ? nameIRegE(size,pfx,rm) : dis_buf ),
4536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       nameIRegG(size,pfx,rm) );
4537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return delta;
4538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate an IR sequence to do a popcount operation on the supplied
4542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp, and return a new IRTemp holding the result.  'ty' may be
4543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Ity_I16, Ity_I32 or Ity_I64 only. */
4544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRTemp gen_POPCOUNT ( IRType ty, IRTemp src )
4545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i;
4547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ty == Ity_I16) {
4548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp old = IRTemp_INVALID;
4549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp nyu = IRTemp_INVALID;
4550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp mask[4], shift[4];
4551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = 0; i < 4; i++) {
4552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mask[i]  = newTemp(ty);
4553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         shift[i] = 1 << i;
4554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(mask[0], mkU16(0x5555));
4556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(mask[1], mkU16(0x3333));
4557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(mask[2], mkU16(0x0F0F));
4558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(mask[3], mkU16(0x00FF));
4559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      old = src;
4560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = 0; i < 4; i++) {
4561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         nyu = newTemp(ty);
4562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(nyu,
4563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop(Iop_Add16,
4564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_And16,
4565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkexpr(old),
4566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkexpr(mask[i])),
4567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_And16,
4568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(Iop_Shr16, mkexpr(old), mkU8(shift[i])),
4569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkexpr(mask[i]))));
4570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         old = nyu;
4571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return nyu;
4573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ty == Ity_I32) {
4575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp old = IRTemp_INVALID;
4576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp nyu = IRTemp_INVALID;
4577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp mask[5], shift[5];
4578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = 0; i < 5; i++) {
4579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mask[i]  = newTemp(ty);
4580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         shift[i] = 1 << i;
4581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(mask[0], mkU32(0x55555555));
4583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(mask[1], mkU32(0x33333333));
4584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(mask[2], mkU32(0x0F0F0F0F));
4585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(mask[3], mkU32(0x00FF00FF));
4586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(mask[4], mkU32(0x0000FFFF));
4587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      old = src;
4588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = 0; i < 5; i++) {
4589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         nyu = newTemp(ty);
4590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(nyu,
4591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop(Iop_Add32,
4592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_And32,
4593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkexpr(old),
4594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkexpr(mask[i])),
4595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_And32,
4596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])),
4597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkexpr(mask[i]))));
4598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         old = nyu;
4599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return nyu;
4601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ty == Ity_I64) {
4603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp old = IRTemp_INVALID;
4604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp nyu = IRTemp_INVALID;
4605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp mask[6], shift[6];
4606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = 0; i < 6; i++) {
4607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mask[i]  = newTemp(ty);
4608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         shift[i] = 1 << i;
4609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(mask[0], mkU64(0x5555555555555555ULL));
4611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(mask[1], mkU64(0x3333333333333333ULL));
4612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(mask[2], mkU64(0x0F0F0F0F0F0F0F0FULL));
4613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(mask[3], mkU64(0x00FF00FF00FF00FFULL));
4614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(mask[4], mkU64(0x0000FFFF0000FFFFULL));
4615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(mask[5], mkU64(0x00000000FFFFFFFFULL));
4616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      old = src;
4617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = 0; i < 6; i++) {
4618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         nyu = newTemp(ty);
4619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(nyu,
4620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop(Iop_Add64,
4621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_And64,
4622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkexpr(old),
4623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkexpr(mask[i])),
4624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_And64,
4625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(Iop_Shr64, mkexpr(old), mkU8(shift[i])),
4626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkexpr(mask[i]))));
4627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         old = nyu;
4628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return nyu;
4630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /*NOTREACHED*/
4632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(0);
4633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate an IR sequence to do a count-leading-zeroes operation on
4637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the supplied IRTemp, and return a new IRTemp holding the result.
4638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   'ty' may be Ity_I16, Ity_I32 or Ity_I64 only.  In the case where
4639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the argument is zero, return the number of bits in the word (the
4640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   natural semantics). */
4641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRTemp gen_LZCNT ( IRType ty, IRTemp src )
4642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(ty == Ity_I64 || ty == Ity_I32 || ty == Ity_I16);
4644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp src64 = newTemp(Ity_I64);
4646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(src64, widenUto64( mkexpr(src) ));
4647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp src64x = newTemp(Ity_I64);
4649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(src64x,
4650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          binop(Iop_Shl64, mkexpr(src64),
4651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           mkU8(64 - 8 * sizeofIRType(ty))));
4652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Clz64 has undefined semantics when its input is zero, so
4654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // special-case around that.
4655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp res64 = newTemp(Ity_I64);
4656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(res64,
4657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          IRExpr_Mux0X(
4658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             unop(Iop_1Uto8,
4659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(Iop_CmpEQ64, mkexpr(src64x), mkU64(0))),
4660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             unop(Iop_Clz64, mkexpr(src64x)),
4661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             mkU64(8 * sizeofIRType(ty))
4662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ));
4663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp res = newTemp(ty);
4665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(res, narrowTo(ty, mkexpr(res64)));
4666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return res;
4667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
4671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---                                                      ---*/
4672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- x87 FLOATING POINT INSTRUCTIONS                      ---*/
4673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---                                                      ---*/
4674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
4675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --- Helper functions for dealing with the register stack. --- */
4677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --- Set the emulation-warning pseudo-register. --- */
4679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void put_emwarn ( IRExpr* e /* :: Ity_I32 */ )
4681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I32);
4683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_EMWARN, e ) );
4684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --- Produce an IRExpr* denoting a 64-bit QNaN. --- */
4687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mkQNaN64 ( void )
4689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  /* QNaN is 0 2047 1 0(51times)
4691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     == 0b 11111111111b 1 0(51times)
4692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     == 0x7FF8 0000 0000 0000
4693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
4694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Const(IRConst_F64i(0x7FF8000000000000ULL));
4695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------- Get/put the top-of-stack pointer :: Ity_I32 --------- */
4698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* get_ftop ( void )
4700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Get( OFFB_FTOP, Ity_I32 );
4702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void put_ftop ( IRExpr* e )
4705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I32);
4707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_FTOP, e ) );
4708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------- Get/put the C3210 bits. --------- */
4711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr*  /* :: Ity_I64 */ get_C3210 ( void )
4713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Get( OFFB_FC3210, Ity_I64 );
4715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void put_C3210 ( IRExpr* e  /* :: Ity_I64 */ )
4718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I64);
4720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_FC3210, e ) );
4721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------- Get/put the FPU rounding mode. --------- */
4724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* /* :: Ity_I32 */ get_fpround ( void )
4725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return unop(Iop_64to32, IRExpr_Get( OFFB_FPROUND, Ity_I64 ));
4727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void put_fpround ( IRExpr* /* :: Ity_I32 */ e )
4730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I32);
4732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_FPROUND, unop(Iop_32Uto64,e) ) );
4733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------- Synthesise a 2-bit FPU rounding mode. --------- */
4737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Produces a value in 0 .. 3, which is encoded as per the type
4738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRRoundingMode.  Since the guest_FPROUND value is also encoded as
4739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   per IRRoundingMode, we merely need to get it and mask it for
4740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   safety.
4741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
4742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* /* :: Ity_I32 */ get_roundingmode ( void )
4743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return binop( Iop_And32, get_fpround(), mkU32(3) );
4745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* /* :: Ity_I32 */ get_FAKE_roundingmode ( void )
4748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return mkU32(Irrm_NEAREST);
4750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------- Get/set FP register tag bytes. --------- */
4754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Given i, and some expression e, generate 'ST_TAG(i) = e'. */
4756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void put_ST_TAG ( Int i, IRExpr* value )
4758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRRegArray* descr;
4760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv, value) == Ity_I8);
4761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   descr = mkIRRegArray( OFFB_FPTAGS, Ity_I8, 8 );
4762663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   stmt( IRStmt_PutI( mkIRPutI(descr, get_ftop(), i, value) ) );
4763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Given i, generate an expression yielding 'ST_TAG(i)'.  This will be
4766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   zero to indicate "Empty" and nonzero to indicate "NonEmpty".  */
4767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* get_ST_TAG ( Int i )
4769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRRegArray* descr = mkIRRegArray( OFFB_FPTAGS, Ity_I8, 8 );
4771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_GetI( descr, get_ftop(), i );
4772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------- Get/set FP registers. --------- */
4776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Given i, and some expression e, emit 'ST(i) = e' and set the
4778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   register's tag to indicate the register is full.  The previous
4779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   state of the register is not checked. */
4780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void put_ST_UNCHECKED ( Int i, IRExpr* value )
4782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRRegArray* descr;
4784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv, value) == Ity_F64);
4785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   descr = mkIRRegArray( OFFB_FPREGS, Ity_F64, 8 );
4786663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   stmt( IRStmt_PutI( mkIRPutI(descr, get_ftop(), i, value) ) );
4787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Mark the register as in-use. */
4788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   put_ST_TAG(i, mkU8(1));
4789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Given i, and some expression e, emit
4792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ST(i) = is_full(i) ? NaN : e
4793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and set the tag accordingly.
4794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
4795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void put_ST ( Int i, IRExpr* value )
4797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   put_ST_UNCHECKED( i,
4799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     IRExpr_Mux0X( get_ST_TAG(i),
4800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   /* 0 means empty */
4801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   value,
4802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   /* non-0 means full */
4803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   mkQNaN64()
4804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   )
4805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   );
4806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Given i, generate an expression yielding 'ST(i)'. */
4810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* get_ST_UNCHECKED ( Int i )
4812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRRegArray* descr = mkIRRegArray( OFFB_FPREGS, Ity_F64, 8 );
4814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_GetI( descr, get_ftop(), i );
4815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Given i, generate an expression yielding
4819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  is_full(i) ? ST(i) : NaN
4820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
4821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* get_ST ( Int i )
4823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return
4825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRExpr_Mux0X( get_ST_TAG(i),
4826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* 0 means empty */
4827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    mkQNaN64(),
4828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* non-0 means full */
4829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    get_ST_UNCHECKED(i));
4830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Adjust FTOP downwards by one register. */
4834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void fp_push ( void )
4836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   put_ftop( binop(Iop_Sub32, get_ftop(), mkU32(1)) );
4838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Adjust FTOP upwards by one register, and mark the vacated register
4841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   as empty.  */
4842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void fp_pop ( void )
4844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   put_ST_TAG(0, mkU8(0));
4846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   put_ftop( binop(Iop_Add32, get_ftop(), mkU32(1)) );
4847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Clear the C2 bit of the FPU status register, for
4850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sin/cos/tan/sincos. */
4851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void clear_C2 ( void )
4853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   put_C3210( binop(Iop_And64, get_C3210(), mkU64(~AMD64G_FC_MASK_C2)) );
4855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Invent a plausible-looking FPU status word value:
4858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ((ftop & 7) << 11) | (c3210 & 0x4700)
4859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
4860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* get_FPU_sw ( void )
4861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return
4863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      unop(Iop_32to16,
4864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           binop(Iop_Or32,
4865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(Iop_Shl32,
4866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop(Iop_And32, get_ftop(), mkU32(7)),
4867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             mkU8(11)),
4868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop(Iop_And32, unop(Iop_64to32, get_C3210()),
4869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        mkU32(0x4700))
4870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ));
4871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------------------------------------------------------- */
4875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Given all that stack-mangling junk, we can now go ahead
4876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and describe FP instructions.
4877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
4878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ST(0) = ST(0) `op` mem64/32(addr)
4880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Need to check ST(0)'s tag on read, but not on write.
4881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
4882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
4883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid fp_do_op_mem_ST_0 ( IRTemp addr, HChar* op_txt, HChar* dis_buf,
4884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         IROp op, Bool dbl )
4885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DIP("f%s%c %s\n", op_txt, dbl?'l':'s', dis_buf);
4887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (dbl) {
4888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      put_ST_UNCHECKED(0,
4889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         triop( op,
4890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
4891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                get_ST(0),
4892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                loadLE(Ity_F64,mkexpr(addr))
4893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ));
4894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
4895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      put_ST_UNCHECKED(0,
4896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         triop( op,
4897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
4898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                get_ST(0),
4899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                unop(Iop_F32toF64, loadLE(Ity_F32,mkexpr(addr)))
4900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ));
4901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ST(0) = mem64/32(addr) `op` ST(0)
4906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Need to check ST(0)'s tag on read, but not on write.
4907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
4908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
4909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid fp_do_oprev_mem_ST_0 ( IRTemp addr, HChar* op_txt, HChar* dis_buf,
4910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            IROp op, Bool dbl )
4911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DIP("f%s%c %s\n", op_txt, dbl?'l':'s', dis_buf);
4913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (dbl) {
4914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      put_ST_UNCHECKED(0,
4915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         triop( op,
4916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
4917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                loadLE(Ity_F64,mkexpr(addr)),
4918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                get_ST(0)
4919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ));
4920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
4921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      put_ST_UNCHECKED(0,
4922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         triop( op,
4923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
4924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                unop(Iop_F32toF64, loadLE(Ity_F32,mkexpr(addr))),
4925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                get_ST(0)
4926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ));
4927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ST(dst) = ST(dst) `op` ST(src).
4932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Check dst and src tags when reading but not on write.
4933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
4934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
4935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid fp_do_op_ST_ST ( HChar* op_txt, IROp op, UInt st_src, UInt st_dst,
4936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      Bool pop_after )
4937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DIP("f%s%s st(%u), st(%u)\n", op_txt, pop_after?"p":"", st_src, st_dst );
4939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   put_ST_UNCHECKED(
4940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st_dst,
4941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      triop( op,
4942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
4943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             get_ST(st_dst),
4944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             get_ST(st_src) )
4945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   );
4946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (pop_after)
4947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fp_pop();
4948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ST(dst) = ST(src) `op` ST(dst).
4951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Check dst and src tags when reading but not on write.
4952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
4953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
4954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid fp_do_oprev_ST_ST ( HChar* op_txt, IROp op, UInt st_src, UInt st_dst,
4955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         Bool pop_after )
4956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DIP("f%s%s st(%u), st(%u)\n", op_txt, pop_after?"p":"", st_src, st_dst );
4958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   put_ST_UNCHECKED(
4959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st_dst,
4960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      triop( op,
4961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
4962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             get_ST(st_src),
4963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             get_ST(st_dst) )
4964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   );
4965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (pop_after)
4966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fp_pop();
4967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* %rflags(Z,P,C) = UCOMI( st(0), st(i) ) */
4970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void fp_do_ucomi_ST0_STi ( UInt i, Bool pop_after )
4971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DIP("fucomi%s %%st(0),%%st(%u)\n", pop_after ? "p" : "", i);
4973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* This is a bit of a hack (and isn't really right).  It sets
4974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Z,P,C,O correctly, but forces A and S to zero, whereas the Intel
4975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      documentation implies A and S are unchanged.
4976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
4977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* It's also fishy in that it is used both for COMIP and
4978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UCOMIP, and they aren't the same (although similar). */
4979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_CC_OP,   mkU64(AMD64G_CC_OP_COPY) ));
4980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_CC_DEP2, mkU64(0) ));
4981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put(
4982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            OFFB_CC_DEP1,
4983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            binop( Iop_And64,
4984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   unop( Iop_32Uto64,
4985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_CmpF64, get_ST(0), get_ST(i))),
4986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   mkU64(0x45)
4987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        )));
4988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (pop_after)
4989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fp_pop();
4990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* returns
4994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   32to16( if e32 <s -32768 || e32 >s 32767 then -32768 else e32 )
4995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
4996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* x87ishly_qnarrow_32_to_16 ( IRExpr* e32 )
4997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp t32 = newTemp(Ity_I32);
4999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( t32, e32 );
5000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return
5001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRExpr_Mux0X(
5002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         unop(Iop_1Uto8,
5003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              binop(Iop_CmpLT64U,
5004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    unop(Iop_32Uto64,
5005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_Add32, mkexpr(t32), mkU32(32768))),
5006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    mkU64(65536))),
5007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mkU16( 0x8000 ),
5008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         unop(Iop_32to16, mkexpr(t32)));
5009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
5013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong dis_FPU ( /*OUT*/Bool* decode_ok,
5014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                VexAbiInfo* vbi, Prefix pfx, Long delta )
5015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int    len;
5017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt   r_src, r_dst;
5018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar  dis_buf[50];
5019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp t1, t2;
5020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* On entry, delta points at the second byte of the insn (the modrm
5022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      byte).*/
5023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar first_opcode = getUChar(delta-1);
5024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar modrm        = getUChar(delta+0);
5025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xD8 opcodes +-+-+-+-+-+-+-+ */
5027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (first_opcode == 0xD8) {
5029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (modrm < 0xC0) {
5030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* bits 5,4,3 are an opcode extension, and the modRM also
5032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           specifies an address. */
5033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp addr = disAMode( &len, vbi, pfx, delta, dis_buf, 0 );
5034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         delta += len;
5035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (gregLO3ofRM(modrm)) {
5037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0: /* FADD single-real */
5039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_do_op_mem_ST_0 ( addr, "add", dis_buf, Iop_AddF64, False );
5040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 1: /* FMUL single-real */
5043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_do_op_mem_ST_0 ( addr, "mul", dis_buf, Iop_MulF64, False );
5044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5046663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 2: /* FCOM single-real */
5047663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               DIP("fcoms %s\n", dis_buf);
5048663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* This forces C1 to zero, which isn't right. */
5049663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* The AMD documentation suggests that forcing C1 to
5050663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  zero is correct (Eliot Moss) */
5051663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               put_C3210(
5052663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   unop( Iop_32Uto64,
5053663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       binop( Iop_And32,
5054663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              binop(Iop_Shl32,
5055663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    binop(Iop_CmpF64,
5056663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                          get_ST(0),
5057663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                          unop(Iop_F32toF64,
5058663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                               loadLE(Ity_F32,mkexpr(addr)))),
5059663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    mkU8(8)),
5060663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              mkU32(0x4500)
5061663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   )));
5062663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               break;
5063663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
5064663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 3: /* FCOMP single-real */
5065663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* The AMD documentation suggests that forcing C1 to
5066663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  zero is correct (Eliot Moss) */
5067663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               DIP("fcomps %s\n", dis_buf);
5068663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* This forces C1 to zero, which isn't right. */
5069663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               put_C3210(
5070663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   unop( Iop_32Uto64,
5071663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       binop( Iop_And32,
5072663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              binop(Iop_Shl32,
5073663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    binop(Iop_CmpF64,
5074663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                          get_ST(0),
5075663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                          unop(Iop_F32toF64,
5076663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                               loadLE(Ity_F32,mkexpr(addr)))),
5077663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    mkU8(8)),
5078663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              mkU32(0x4500)
5079663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   )));
5080663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               fp_pop();
5081663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               break;
5082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 4: /* FSUB single-real */
5084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_do_op_mem_ST_0 ( addr, "sub", dis_buf, Iop_SubF64, False );
5085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 5: /* FSUBR single-real */
5088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_do_oprev_mem_ST_0 ( addr, "subr", dis_buf, Iop_SubF64, False );
5089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 6: /* FDIV single-real */
5092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_do_op_mem_ST_0 ( addr, "div", dis_buf, Iop_DivF64, False );
5093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 7: /* FDIVR single-real */
5096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_do_oprev_mem_ST_0 ( addr, "divr", dis_buf, Iop_DivF64, False );
5097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
5100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf("unhandled opc_aux = 0x%2x\n", gregLO3ofRM(modrm));
5101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf("first_opcode == 0xD8\n");
5102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto decode_fail;
5103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
5105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         delta++;
5106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (modrm) {
5107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xC0 ... 0xC7: /* FADD %st(?),%st(0) */
5109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_do_op_ST_ST ( "add", Iop_AddF64, modrm - 0xC0, 0, False );
5110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xC8 ... 0xCF: /* FMUL %st(?),%st(0) */
5113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_do_op_ST_ST ( "mul", Iop_MulF64, modrm - 0xC8, 0, False );
5114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Dunno if this is right */
5117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xD0 ... 0xD7: /* FCOM %st(?),%st(0) */
5118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               r_dst = (UInt)modrm - 0xD0;
5119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fcom %%st(0),%%st(%d)\n", r_dst);
5120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* This forces C1 to zero, which isn't right. */
5121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_C3210(
5122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   unop(Iop_32Uto64,
5123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   binop( Iop_And32,
5124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          binop(Iop_Shl32,
5125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                binop(Iop_CmpF64, get_ST(0), get_ST(r_dst)),
5126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                mkU8(8)),
5127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          mkU32(0x4500)
5128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   )));
5129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Dunno if this is right */
5132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xD8 ... 0xDF: /* FCOMP %st(?),%st(0) */
5133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               r_dst = (UInt)modrm - 0xD8;
5134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fcomp %%st(0),%%st(%d)\n", r_dst);
5135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* This forces C1 to zero, which isn't right. */
5136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_C3210(
5137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   unop(Iop_32Uto64,
5138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   binop( Iop_And32,
5139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          binop(Iop_Shl32,
5140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                binop(Iop_CmpF64, get_ST(0), get_ST(r_dst)),
5141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                mkU8(8)),
5142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          mkU32(0x4500)
5143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   )));
5144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_pop();
5145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xE0 ... 0xE7: /* FSUB %st(?),%st(0) */
5148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_do_op_ST_ST ( "sub", Iop_SubF64, modrm - 0xE0, 0, False );
5149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xE8 ... 0xEF: /* FSUBR %st(?),%st(0) */
5152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_do_oprev_ST_ST ( "subr", Iop_SubF64, modrm - 0xE8, 0, False );
5153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xF0 ... 0xF7: /* FDIV %st(?),%st(0) */
5156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_do_op_ST_ST ( "div", Iop_DivF64, modrm - 0xF0, 0, False );
5157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xF8 ... 0xFF: /* FDIVR %st(?),%st(0) */
5160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_do_oprev_ST_ST ( "divr", Iop_DivF64, modrm - 0xF8, 0, False );
5161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
5164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto decode_fail;
5165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xD9 opcodes +-+-+-+-+-+-+-+ */
5170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
5171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (first_opcode == 0xD9) {
5172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (modrm < 0xC0) {
5173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* bits 5,4,3 are an opcode extension, and the modRM also
5175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            specifies an address. */
5176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp addr = disAMode( &len, vbi, pfx, delta, dis_buf, 0 );
5177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         delta += len;
5178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (gregLO3ofRM(modrm)) {
5180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0: /* FLD single-real */
5182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("flds %s\n", dis_buf);
5183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_push();
5184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST(0, unop(Iop_F32toF64,
5185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              loadLE(Ity_F32, mkexpr(addr))));
5186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 2: /* FST single-real */
5189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fsts %s\n", dis_buf);
5190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               storeLE(mkexpr(addr),
5191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop(Iop_F64toF32, get_roundingmode(), get_ST(0)));
5192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 3: /* FSTP single-real */
5195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fstps %s\n", dis_buf);
5196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               storeLE(mkexpr(addr),
5197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop(Iop_F64toF32, get_roundingmode(), get_ST(0)));
5198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_pop();
5199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 4: { /* FLDENV m28 */
5202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* Uses dirty helper:
5203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     VexEmWarn amd64g_do_FLDENV ( VexGuestX86State*, HWord ) */
5204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp    ew = newTemp(Ity_I32);
5205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp   w64 = newTemp(Ity_I64);
5206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRDirty*   d = unsafeIRDirty_0_N (
5207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 0/*regparms*/,
5208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 "amd64g_dirtyhelper_FLDENV",
5209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 &amd64g_dirtyhelper_FLDENV,
5210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 mkIRExprVec_1( mkexpr(addr) )
5211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              );
5212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->needsBBP = True;
5213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->tmp      = w64;
5214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* declare we're reading memory */
5215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->mFx   = Ifx_Read;
5216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->mAddr = mkexpr(addr);
5217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->mSize = 28;
5218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* declare we're writing guest state */
5220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->nFxState = 4;
5221663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               vex_bzero(&d->fxState, sizeof(d->fxState));
5222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->fxState[0].fx     = Ifx_Write;
5224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->fxState[0].offset = OFFB_FTOP;
5225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->fxState[0].size   = sizeof(UInt);
5226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->fxState[1].fx     = Ifx_Write;
5228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->fxState[1].offset = OFFB_FPTAGS;
5229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->fxState[1].size   = 8 * sizeof(UChar);
5230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->fxState[2].fx     = Ifx_Write;
5232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->fxState[2].offset = OFFB_FPROUND;
5233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->fxState[2].size   = sizeof(ULong);
5234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->fxState[3].fx     = Ifx_Write;
5236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->fxState[3].offset = OFFB_FC3210;
5237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->fxState[3].size   = sizeof(ULong);
5238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               stmt( IRStmt_Dirty(d) );
5240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* ew contains any emulation warning we may need to
5242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  issue.  If needed, side-exit to the next insn,
5243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  reporting the warning, so that Valgrind's dispatcher
5244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  sees the warning. */
5245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       assign(ew, unop(Iop_64to32,mkexpr(w64)) );
5246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_emwarn( mkexpr(ew) );
5247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               stmt(
5248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  IRStmt_Exit(
5249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_CmpNE32, mkexpr(ew), mkU32(0)),
5250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     Ijk_EmWarn,
5251663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     IRConst_U64( guest_RIP_bbstart+delta ),
5252663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     OFFB_RIP
5253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  )
5254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               );
5255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fldenv %s\n", dis_buf);
5257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
5259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 5: {/* FLDCW */
5261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* The only thing we observe in the control word is the
5262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  rounding mode.  Therefore, pass the 16-bit value
5263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  (x87 native-format control word) to a clean helper,
5264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  getting back a 64-bit value, the lower half of which
5265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  is the FPROUND value to store, and the upper half of
5266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  which is the emulation-warning token which may be
5267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  generated.
5268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               */
5269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* ULong amd64h_check_fldcw ( ULong ); */
5270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp t64 = newTemp(Ity_I64);
5271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp ew = newTemp(Ity_I32);
5272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fldcw %s\n", dis_buf);
5273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign( t64, mkIRExprCCall(
5274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               Ity_I64, 0/*regparms*/,
5275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               "amd64g_check_fldcw",
5276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               &amd64g_check_fldcw,
5277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               mkIRExprVec_1(
5278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  unop( Iop_16Uto64,
5279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        loadLE(Ity_I16, mkexpr(addr)))
5280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               )
5281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            )
5282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     );
5283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_fpround( unop(Iop_64to32, mkexpr(t64)) );
5285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign( ew, unop(Iop_64HIto32, mkexpr(t64) ) );
5286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_emwarn( mkexpr(ew) );
5287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* Finally, if an emulation warning was reported,
5288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  side-exit to the next insn, reporting the warning,
5289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  so that Valgrind's dispatcher sees the warning. */
5290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               stmt(
5291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  IRStmt_Exit(
5292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_CmpNE32, mkexpr(ew), mkU32(0)),
5293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     Ijk_EmWarn,
5294663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     IRConst_U64( guest_RIP_bbstart+delta ),
5295663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     OFFB_RIP
5296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  )
5297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               );
5298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
5300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 6: { /* FNSTENV m28 */
5302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* Uses dirty helper:
5303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     void amd64g_do_FSTENV ( VexGuestAMD64State*, HWord ) */
5304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRDirty* d = unsafeIRDirty_0_N (
5305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               0/*regparms*/,
5306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               "amd64g_dirtyhelper_FSTENV",
5307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               &amd64g_dirtyhelper_FSTENV,
5308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               mkIRExprVec_1( mkexpr(addr) )
5309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            );
5310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->needsBBP = True;
5311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* declare we're writing memory */
5312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->mFx   = Ifx_Write;
5313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->mAddr = mkexpr(addr);
5314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->mSize = 28;
5315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* declare we're reading guest state */
5317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->nFxState = 4;
5318663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               vex_bzero(&d->fxState, sizeof(d->fxState));
5319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->fxState[0].fx     = Ifx_Read;
5321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->fxState[0].offset = OFFB_FTOP;
5322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->fxState[0].size   = sizeof(UInt);
5323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->fxState[1].fx     = Ifx_Read;
5325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->fxState[1].offset = OFFB_FPTAGS;
5326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->fxState[1].size   = 8 * sizeof(UChar);
5327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->fxState[2].fx     = Ifx_Read;
5329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->fxState[2].offset = OFFB_FPROUND;
5330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->fxState[2].size   = sizeof(ULong);
5331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->fxState[3].fx     = Ifx_Read;
5333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->fxState[3].offset = OFFB_FC3210;
5334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->fxState[3].size   = sizeof(ULong);
5335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               stmt( IRStmt_Dirty(d) );
5337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fnstenv %s\n", dis_buf);
5339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
5341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 7: /* FNSTCW */
5343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* Fake up a native x87 FPU control word.  The only
5344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  thing it depends on is FPROUND[1:0], so call a clean
5345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  helper to cook it up. */
5346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* ULong amd64g_create_fpucw ( ULong fpround ) */
5347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fnstcw %s\n", dis_buf);
5348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               storeLE(
5349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  mkexpr(addr),
5350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  unop( Iop_64to16,
5351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mkIRExprCCall(
5352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           Ity_I64, 0/*regp*/,
5353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           "amd64g_create_fpucw", &amd64g_create_fpucw,
5354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           mkIRExprVec_1( unop(Iop_32Uto64, get_fpround()) )
5355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        )
5356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  )
5357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               );
5358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
5361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf("unhandled opc_aux = 0x%2x\n", gregLO3ofRM(modrm));
5362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf("first_opcode == 0xD9\n");
5363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto decode_fail;
5364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
5367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         delta++;
5368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (modrm) {
5369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xC0 ... 0xC7: /* FLD %st(?) */
5371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               r_src = (UInt)modrm - 0xC0;
5372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fld %%st(%u)\n", r_src);
5373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               t1 = newTemp(Ity_F64);
5374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(t1, get_ST(r_src));
5375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_push();
5376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST(0, mkexpr(t1));
5377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xC8 ... 0xCF: /* FXCH %st(?) */
5380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               r_src = (UInt)modrm - 0xC8;
5381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fxch %%st(%u)\n", r_src);
5382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               t1 = newTemp(Ity_F64);
5383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               t2 = newTemp(Ity_F64);
5384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(t1, get_ST(0));
5385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(t2, get_ST(r_src));
5386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST_UNCHECKED(0, mkexpr(t2));
5387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST_UNCHECKED(r_src, mkexpr(t1));
5388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xE0: /* FCHS */
5391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fchs\n");
5392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST_UNCHECKED(0, unop(Iop_NegF64, get_ST(0)));
5393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xE1: /* FABS */
5396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fabs\n");
5397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST_UNCHECKED(0, unop(Iop_AbsF64, get_ST(0)));
5398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xE5: { /* FXAM */
5401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* This is an interesting one.  It examines %st(0),
5402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  regardless of whether the tag says it's empty or not.
5403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  Here, just pass both the tag (in our format) and the
5404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  value (as a double, actually a ULong) to a helper
5405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  function. */
5406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRExpr** args
5407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  = mkIRExprVec_2( unop(Iop_8Uto64, get_ST_TAG(0)),
5408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   unop(Iop_ReinterpF64asI64,
5409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        get_ST_UNCHECKED(0)) );
5410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_C3210(mkIRExprCCall(
5411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            Ity_I64,
5412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            0/*regparm*/,
5413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            "amd64g_calculate_FXAM", &amd64g_calculate_FXAM,
5414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            args
5415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        ));
5416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fxam\n");
5417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
5419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xE8: /* FLD1 */
5421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fld1\n");
5422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_push();
5423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* put_ST(0, IRExpr_Const(IRConst_F64(1.0))); */
5424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST(0, IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)));
5425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xE9: /* FLDL2T */
5428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fldl2t\n");
5429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_push();
5430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* put_ST(0, IRExpr_Const(IRConst_F64(3.32192809488736234781))); */
5431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST(0, IRExpr_Const(IRConst_F64i(0x400a934f0979a371ULL)));
5432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xEA: /* FLDL2E */
5435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fldl2e\n");
5436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_push();
5437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* put_ST(0, IRExpr_Const(IRConst_F64(1.44269504088896340739))); */
5438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST(0, IRExpr_Const(IRConst_F64i(0x3ff71547652b82feULL)));
5439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xEB: /* FLDPI */
5442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fldpi\n");
5443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_push();
5444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* put_ST(0, IRExpr_Const(IRConst_F64(3.14159265358979323851))); */
5445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST(0, IRExpr_Const(IRConst_F64i(0x400921fb54442d18ULL)));
5446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xEC: /* FLDLG2 */
5449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fldlg2\n");
5450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_push();
5451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* put_ST(0, IRExpr_Const(IRConst_F64(0.301029995663981143))); */
5452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST(0, IRExpr_Const(IRConst_F64i(0x3fd34413509f79ffULL)));
5453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xED: /* FLDLN2 */
5456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fldln2\n");
5457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_push();
5458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* put_ST(0, IRExpr_Const(IRConst_F64(0.69314718055994530942))); */
5459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST(0, IRExpr_Const(IRConst_F64i(0x3fe62e42fefa39efULL)));
5460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xEE: /* FLDZ */
5463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fldz\n");
5464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_push();
5465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* put_ST(0, IRExpr_Const(IRConst_F64(0.0))); */
5466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST(0, IRExpr_Const(IRConst_F64i(0x0000000000000000ULL)));
5467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xF0: /* F2XM1 */
5470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("f2xm1\n");
5471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST_UNCHECKED(0,
5472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(Iop_2xm1F64,
5473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
5474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        get_ST(0)));
5475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xF1: /* FYL2X */
5478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fyl2x\n");
5479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST_UNCHECKED(1,
5480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  triop(Iop_Yl2xF64,
5481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
5482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        get_ST(1),
5483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        get_ST(0)));
5484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_pop();
5485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xF2: /* FPTAN */
5488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("ftan\n");
5489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST_UNCHECKED(0,
5490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(Iop_TanF64,
5491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
5492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        get_ST(0)));
5493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_push();
5494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST(0, IRExpr_Const(IRConst_F64(1.0)));
5495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               clear_C2(); /* HACK */
5496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xF3: /* FPATAN */
5499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fpatan\n");
5500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST_UNCHECKED(1,
5501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  triop(Iop_AtanF64,
5502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
5503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        get_ST(1),
5504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        get_ST(0)));
5505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_pop();
5506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xF4: { /* FXTRACT */
5509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp argF = newTemp(Ity_F64);
5510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp sigF = newTemp(Ity_F64);
5511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp expF = newTemp(Ity_F64);
5512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp argI = newTemp(Ity_I64);
5513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp sigI = newTemp(Ity_I64);
5514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp expI = newTemp(Ity_I64);
5515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fxtract\n");
5516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign( argF, get_ST(0) );
5517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign( argI, unop(Iop_ReinterpF64asI64, mkexpr(argF)));
5518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign( sigI,
5519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       mkIRExprCCall(
5520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          Ity_I64, 0/*regparms*/,
5521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          "x86amd64g_calculate_FXTRACT",
5522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          &x86amd64g_calculate_FXTRACT,
5523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          mkIRExprVec_2( mkexpr(argI),
5524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         mkIRExpr_HWord(0)/*sig*/ ))
5525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               );
5526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign( expI,
5527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       mkIRExprCCall(
5528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          Ity_I64, 0/*regparms*/,
5529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          "x86amd64g_calculate_FXTRACT",
5530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          &x86amd64g_calculate_FXTRACT,
5531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          mkIRExprVec_2( mkexpr(argI),
5532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         mkIRExpr_HWord(1)/*exp*/ ))
5533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               );
5534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign( sigF, unop(Iop_ReinterpI64asF64, mkexpr(sigI)) );
5535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign( expF, unop(Iop_ReinterpI64asF64, mkexpr(expI)) );
5536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* exponent */
5537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST_UNCHECKED(0, mkexpr(expF) );
5538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_push();
5539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* significand */
5540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST(0, mkexpr(sigF) );
5541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
5543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xF5: { /* FPREM1 -- IEEE compliant */
5545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp a1 = newTemp(Ity_F64);
5546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp a2 = newTemp(Ity_F64);
5547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fprem1\n");
5548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* Do FPREM1 twice, once to get the remainder, and once
5549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  to get the C3210 flag values. */
5550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign( a1, get_ST(0) );
5551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign( a2, get_ST(1) );
5552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST_UNCHECKED(0,
5553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  triop(Iop_PRem1F64,
5554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
5555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mkexpr(a1),
5556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mkexpr(a2)));
5557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_C3210(
5558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  unop(Iop_32Uto64,
5559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  triop(Iop_PRem1C3210F64,
5560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
5561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mkexpr(a1),
5562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mkexpr(a2)) ));
5563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
5565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xF7: /* FINCSTP */
5567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fincstp\n");
5568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ftop( binop(Iop_Add32, get_ftop(), mkU32(1)) );
5569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xF8: { /* FPREM -- not IEEE compliant */
5572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp a1 = newTemp(Ity_F64);
5573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp a2 = newTemp(Ity_F64);
5574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fprem\n");
5575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* Do FPREM twice, once to get the remainder, and once
5576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  to get the C3210 flag values. */
5577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign( a1, get_ST(0) );
5578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign( a2, get_ST(1) );
5579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST_UNCHECKED(0,
5580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  triop(Iop_PRemF64,
5581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
5582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mkexpr(a1),
5583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mkexpr(a2)));
5584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_C3210(
5585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  unop(Iop_32Uto64,
5586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  triop(Iop_PRemC3210F64,
5587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
5588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mkexpr(a1),
5589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mkexpr(a2)) ));
5590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
5592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xF9: /* FYL2XP1 */
5594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fyl2xp1\n");
5595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST_UNCHECKED(1,
5596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  triop(Iop_Yl2xp1F64,
5597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
5598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        get_ST(1),
5599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        get_ST(0)));
5600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_pop();
5601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xFA: /* FSQRT */
5604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fsqrt\n");
5605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST_UNCHECKED(0,
5606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(Iop_SqrtF64,
5607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
5608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        get_ST(0)));
5609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xFB: { /* FSINCOS */
5612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp a1 = newTemp(Ity_F64);
5613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign( a1, get_ST(0) );
5614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fsincos\n");
5615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST_UNCHECKED(0,
5616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(Iop_SinF64,
5617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
5618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mkexpr(a1)));
5619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_push();
5620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST(0,
5621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(Iop_CosF64,
5622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
5623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mkexpr(a1)));
5624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               clear_C2(); /* HACK */
5625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
5627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xFC: /* FRNDINT */
5629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("frndint\n");
5630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST_UNCHECKED(0,
5631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(Iop_RoundF64toInt, get_roundingmode(), get_ST(0)) );
5632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xFD: /* FSCALE */
5635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fscale\n");
5636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST_UNCHECKED(0,
5637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  triop(Iop_ScaleF64,
5638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
5639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        get_ST(0),
5640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        get_ST(1)));
5641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xFE: /* FSIN */
5644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fsin\n");
5645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST_UNCHECKED(0,
5646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(Iop_SinF64,
5647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
5648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        get_ST(0)));
5649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               clear_C2(); /* HACK */
5650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xFF: /* FCOS */
5653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fcos\n");
5654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST_UNCHECKED(0,
5655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(Iop_CosF64,
5656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
5657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        get_ST(0)));
5658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               clear_C2(); /* HACK */
5659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
5662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto decode_fail;
5663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDA opcodes +-+-+-+-+-+-+-+ */
5668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
5669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (first_opcode == 0xDA) {
5670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (modrm < 0xC0) {
5672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* bits 5,4,3 are an opcode extension, and the modRM also
5674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            specifies an address. */
5675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IROp   fop;
5676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp addr = disAMode( &len, vbi, pfx, delta, dis_buf, 0 );
5677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         delta += len;
5678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (gregLO3ofRM(modrm)) {
5679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0: /* FIADD m32int */ /* ST(0) += m32int */
5681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fiaddl %s\n", dis_buf);
5682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fop = Iop_AddF64;
5683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto do_fop_m32;
5684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 1: /* FIMUL m32int */ /* ST(0) *= m32int */
5686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fimull %s\n", dis_buf);
5687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fop = Iop_MulF64;
5688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto do_fop_m32;
5689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 4: /* FISUB m32int */ /* ST(0) -= m32int */
5691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fisubl %s\n", dis_buf);
5692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fop = Iop_SubF64;
5693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto do_fop_m32;
5694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 5: /* FISUBR m32int */ /* ST(0) = m32int - ST(0) */
5696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fisubrl %s\n", dis_buf);
5697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fop = Iop_SubF64;
5698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto do_foprev_m32;
5699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 6: /* FIDIV m32int */ /* ST(0) /= m32int */
5701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fisubl %s\n", dis_buf);
5702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fop = Iop_DivF64;
5703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto do_fop_m32;
5704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 7: /* FIDIVR m32int */ /* ST(0) = m32int / ST(0) */
5706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fidivrl %s\n", dis_buf);
5707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fop = Iop_DivF64;
5708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto do_foprev_m32;
5709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            do_fop_m32:
5711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST_UNCHECKED(0,
5712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  triop(fop,
5713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
5714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        get_ST(0),
5715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        unop(Iop_I32StoF64,
5716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             loadLE(Ity_I32, mkexpr(addr)))));
5717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            do_foprev_m32:
5720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST_UNCHECKED(0,
5721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  triop(fop,
5722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
5723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        unop(Iop_I32StoF64,
5724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             loadLE(Ity_I32, mkexpr(addr))),
5725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        get_ST(0)));
5726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
5729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf("unhandled opc_aux = 0x%2x\n", gregLO3ofRM(modrm));
5730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf("first_opcode == 0xDA\n");
5731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto decode_fail;
5732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
5735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         delta++;
5737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (modrm) {
5738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xC0 ... 0xC7: /* FCMOVB ST(i), ST(0) */
5740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               r_src = (UInt)modrm - 0xC0;
5741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fcmovb %%st(%u), %%st(0)\n", r_src);
5742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST_UNCHECKED(0,
5743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                IRExpr_Mux0X(
5744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    unop(Iop_1Uto8,
5745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         mk_amd64g_calculate_condition(AMD64CondB)),
5746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    get_ST(0), get_ST(r_src)) );
5747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xC8 ... 0xCF: /* FCMOVE(Z) ST(i), ST(0) */
5750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               r_src = (UInt)modrm - 0xC8;
5751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fcmovz %%st(%u), %%st(0)\n", r_src);
5752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST_UNCHECKED(0,
5753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                IRExpr_Mux0X(
5754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    unop(Iop_1Uto8,
5755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         mk_amd64g_calculate_condition(AMD64CondZ)),
5756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    get_ST(0), get_ST(r_src)) );
5757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xD0 ... 0xD7: /* FCMOVBE ST(i), ST(0) */
5760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               r_src = (UInt)modrm - 0xD0;
5761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fcmovbe %%st(%u), %%st(0)\n", r_src);
5762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST_UNCHECKED(0,
5763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                IRExpr_Mux0X(
5764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    unop(Iop_1Uto8,
5765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         mk_amd64g_calculate_condition(AMD64CondBE)),
5766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    get_ST(0), get_ST(r_src)) );
5767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xD8 ... 0xDF: /* FCMOVU ST(i), ST(0) */
5770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               r_src = (UInt)modrm - 0xD8;
5771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fcmovu %%st(%u), %%st(0)\n", r_src);
5772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST_UNCHECKED(0,
5773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                IRExpr_Mux0X(
5774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    unop(Iop_1Uto8,
5775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         mk_amd64g_calculate_condition(AMD64CondP)),
5776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    get_ST(0), get_ST(r_src)) );
5777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xE9: /* FUCOMPP %st(0),%st(1) */
5780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fucompp %%st(0),%%st(1)\n");
5781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* This forces C1 to zero, which isn't right. */
5782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_C3210(
5783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   unop(Iop_32Uto64,
5784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   binop( Iop_And32,
5785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          binop(Iop_Shl32,
5786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                binop(Iop_CmpF64, get_ST(0), get_ST(1)),
5787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                mkU8(8)),
5788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          mkU32(0x4500)
5789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   )));
5790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_pop();
5791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_pop();
5792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
5795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto decode_fail;
5796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDB opcodes +-+-+-+-+-+-+-+ */
5802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
5803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (first_opcode == 0xDB) {
5804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (modrm < 0xC0) {
5805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* bits 5,4,3 are an opcode extension, and the modRM also
5807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            specifies an address. */
5808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp addr = disAMode( &len, vbi, pfx, delta, dis_buf, 0 );
5809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         delta += len;
5810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (gregLO3ofRM(modrm)) {
5812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0: /* FILD m32int */
5814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fildl %s\n", dis_buf);
5815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_push();
5816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST(0, unop(Iop_I32StoF64,
5817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              loadLE(Ity_I32, mkexpr(addr))));
5818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 1: /* FISTTPL m32 (SSE3) */
5821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fisttpl %s\n", dis_buf);
5822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               storeLE( mkexpr(addr),
5823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_F64toI32S, mkU32(Irrm_ZERO), get_ST(0)) );
5824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_pop();
5825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 2: /* FIST m32 */
5828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fistl %s\n", dis_buf);
5829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               storeLE( mkexpr(addr),
5830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_F64toI32S, get_roundingmode(), get_ST(0)) );
5831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 3: /* FISTP m32 */
5834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fistpl %s\n", dis_buf);
5835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               storeLE( mkexpr(addr),
5836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_F64toI32S, get_roundingmode(), get_ST(0)) );
5837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_pop();
5838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 5: { /* FLD extended-real */
5841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* Uses dirty helper:
5842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     ULong amd64g_loadF80le ( ULong )
5843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  addr holds the address.  First, do a dirty call to
5844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  get hold of the data. */
5845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp   val  = newTemp(Ity_I64);
5846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRExpr** args = mkIRExprVec_1 ( mkexpr(addr) );
5847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRDirty* d = unsafeIRDirty_1_N (
5849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               val,
5850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               0/*regparms*/,
5851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               "amd64g_dirtyhelper_loadF80le",
5852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               &amd64g_dirtyhelper_loadF80le,
5853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               args
5854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            );
5855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* declare that we're reading memory */
5856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->mFx   = Ifx_Read;
5857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->mAddr = mkexpr(addr);
5858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->mSize = 10;
5859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* execute the dirty call, dumping the result in val. */
5861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               stmt( IRStmt_Dirty(d) );
5862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_push();
5863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST(0, unop(Iop_ReinterpI64asF64, mkexpr(val)));
5864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fldt %s\n", dis_buf);
5866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
5868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 7: { /* FSTP extended-real */
5870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* Uses dirty helper:
5871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     void amd64g_storeF80le ( ULong addr, ULong data )
5872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               */
5873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRExpr** args
5874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  = mkIRExprVec_2( mkexpr(addr),
5875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   unop(Iop_ReinterpF64asI64, get_ST(0)) );
5876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRDirty* d = unsafeIRDirty_0_N (
5878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               0/*regparms*/,
5879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               "amd64g_dirtyhelper_storeF80le",
5880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               &amd64g_dirtyhelper_storeF80le,
5881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               args
5882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            );
5883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* declare we're writing memory */
5884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->mFx   = Ifx_Write;
5885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->mAddr = mkexpr(addr);
5886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->mSize = 10;
5887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* execute the dirty call. */
5889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               stmt( IRStmt_Dirty(d) );
5890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_pop();
5891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fstpt\n %s", dis_buf);
5893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
5895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
5897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf("unhandled opc_aux = 0x%2x\n", gregLO3ofRM(modrm));
5898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf("first_opcode == 0xDB\n");
5899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto decode_fail;
5900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
5903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         delta++;
5905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (modrm) {
5906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xC0 ... 0xC7: /* FCMOVNB ST(i), ST(0) */
5908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               r_src = (UInt)modrm - 0xC0;
5909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fcmovnb %%st(%u), %%st(0)\n", r_src);
5910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST_UNCHECKED(0,
5911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                IRExpr_Mux0X(
5912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    unop(Iop_1Uto8,
5913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         mk_amd64g_calculate_condition(AMD64CondNB)),
5914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    get_ST(0), get_ST(r_src)) );
5915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xC8 ... 0xCF: /* FCMOVNE(NZ) ST(i), ST(0) */
5918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               r_src = (UInt)modrm - 0xC8;
5919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fcmovnz %%st(%u), %%st(0)\n", r_src);
5920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST_UNCHECKED(
5921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  0,
5922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  IRExpr_Mux0X(
5923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     unop(Iop_1Uto8,
5924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          mk_amd64g_calculate_condition(AMD64CondNZ)),
5925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     get_ST(0),
5926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     get_ST(r_src)
5927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  )
5928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               );
5929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xD0 ... 0xD7: /* FCMOVNBE ST(i), ST(0) */
5932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               r_src = (UInt)modrm - 0xD0;
5933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fcmovnbe %%st(%u), %%st(0)\n", r_src);
5934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST_UNCHECKED(
5935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  0,
5936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  IRExpr_Mux0X(
5937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     unop(Iop_1Uto8,
5938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          mk_amd64g_calculate_condition(AMD64CondNBE)),
5939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     get_ST(0),
5940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     get_ST(r_src)
5941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  )
5942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               );
5943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xD8 ... 0xDF: /* FCMOVNU ST(i), ST(0) */
5946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               r_src = (UInt)modrm - 0xD8;
5947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fcmovnu %%st(%u), %%st(0)\n", r_src);
5948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST_UNCHECKED(
5949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  0,
5950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  IRExpr_Mux0X(
5951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     unop(Iop_1Uto8,
5952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          mk_amd64g_calculate_condition(AMD64CondNP)),
5953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     get_ST(0),
5954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     get_ST(r_src)
5955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  )
5956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               );
5957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xE2:
5960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fnclex\n");
5961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xE3: {
5964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* Uses dirty helper:
5965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     void amd64g_do_FINIT ( VexGuestAMD64State* ) */
5966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRDirty* d  = unsafeIRDirty_0_N (
5967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                0/*regparms*/,
5968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                "amd64g_dirtyhelper_FINIT",
5969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                &amd64g_dirtyhelper_FINIT,
5970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                mkIRExprVec_0()
5971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             );
5972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->needsBBP = True;
5973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* declare we're writing guest state */
5975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->nFxState = 5;
5976663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               vex_bzero(&d->fxState, sizeof(d->fxState));
5977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->fxState[0].fx     = Ifx_Write;
5979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->fxState[0].offset = OFFB_FTOP;
5980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->fxState[0].size   = sizeof(UInt);
5981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->fxState[1].fx     = Ifx_Write;
5983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->fxState[1].offset = OFFB_FPREGS;
5984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->fxState[1].size   = 8 * sizeof(ULong);
5985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->fxState[2].fx     = Ifx_Write;
5987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->fxState[2].offset = OFFB_FPTAGS;
5988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->fxState[2].size   = 8 * sizeof(UChar);
5989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->fxState[3].fx     = Ifx_Write;
5991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->fxState[3].offset = OFFB_FPROUND;
5992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->fxState[3].size   = sizeof(ULong);
5993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->fxState[4].fx     = Ifx_Write;
5995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->fxState[4].offset = OFFB_FC3210;
5996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d->fxState[4].size   = sizeof(ULong);
5997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               stmt( IRStmt_Dirty(d) );
5999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fninit\n");
6001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
6003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xE8 ... 0xEF: /* FUCOMI %st(0),%st(?) */
6005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_do_ucomi_ST0_STi( (UInt)modrm - 0xE8, False );
6006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xF0 ... 0xF7: /* FCOMI %st(0),%st(?) */
6009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_do_ucomi_ST0_STi( (UInt)modrm - 0xF0, False );
6010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
6013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto decode_fail;
6014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
6015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDC opcodes +-+-+-+-+-+-+-+ */
6019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
6020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (first_opcode == 0xDC) {
6021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (modrm < 0xC0) {
6022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* bits 5,4,3 are an opcode extension, and the modRM also
6024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            specifies an address. */
6025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp addr = disAMode( &len, vbi, pfx, delta, dis_buf, 0 );
6026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         delta += len;
6027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (gregLO3ofRM(modrm)) {
6029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0: /* FADD double-real */
6031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_do_op_mem_ST_0 ( addr, "add", dis_buf, Iop_AddF64, True );
6032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 1: /* FMUL double-real */
6035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_do_op_mem_ST_0 ( addr, "mul", dis_buf, Iop_MulF64, True );
6036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..             case 2: /* FCOM double-real */
6039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..                DIP("fcoml %s\n", dis_buf);
6040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..                /* This forces C1 to zero, which isn't right. */
6041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..                put_C3210(
6042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..                    binop( Iop_And32,
6043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..                           binop(Iop_Shl32,
6044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..                                 binop(Iop_CmpF64,
6045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..                                       get_ST(0),
6046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..                                       loadLE(Ity_F64,mkexpr(addr))),
6047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..                                 mkU8(8)),
6048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..                           mkU32(0x4500)
6049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..                    ));
6050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..                break;
6051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 3: /* FCOMP double-real */
6053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fcompl %s\n", dis_buf);
6054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* This forces C1 to zero, which isn't right. */
6055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_C3210(
6056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   unop(Iop_32Uto64,
6057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   binop( Iop_And32,
6058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          binop(Iop_Shl32,
6059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                binop(Iop_CmpF64,
6060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      get_ST(0),
6061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      loadLE(Ity_F64,mkexpr(addr))),
6062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                mkU8(8)),
6063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          mkU32(0x4500)
6064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   )));
6065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_pop();
6066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 4: /* FSUB double-real */
6069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_do_op_mem_ST_0 ( addr, "sub", dis_buf, Iop_SubF64, True );
6070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 5: /* FSUBR double-real */
6073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_do_oprev_mem_ST_0 ( addr, "subr", dis_buf, Iop_SubF64, True );
6074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 6: /* FDIV double-real */
6077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_do_op_mem_ST_0 ( addr, "div", dis_buf, Iop_DivF64, True );
6078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 7: /* FDIVR double-real */
6081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_do_oprev_mem_ST_0 ( addr, "divr", dis_buf, Iop_DivF64, True );
6082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
6085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf("unhandled opc_aux = 0x%2x\n", gregLO3ofRM(modrm));
6086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf("first_opcode == 0xDC\n");
6087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto decode_fail;
6088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
6089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
6091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         delta++;
6093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (modrm) {
6094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xC0 ... 0xC7: /* FADD %st(0),%st(?) */
6096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_do_op_ST_ST ( "add", Iop_AddF64, 0, modrm - 0xC0, False );
6097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xC8 ... 0xCF: /* FMUL %st(0),%st(?) */
6100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_do_op_ST_ST ( "mul", Iop_MulF64, 0, modrm - 0xC8, False );
6101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xE0 ... 0xE7: /* FSUBR %st(0),%st(?) */
6104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_do_oprev_ST_ST ( "subr", Iop_SubF64, 0, modrm - 0xE0, False );
6105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xE8 ... 0xEF: /* FSUB %st(0),%st(?) */
6108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_do_op_ST_ST ( "sub", Iop_SubF64, 0, modrm - 0xE8, False );
6109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xF0 ... 0xF7: /* FDIVR %st(0),%st(?) */
6112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_do_oprev_ST_ST ( "divr", Iop_DivF64, 0, modrm - 0xF0, False );
6113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xF8 ... 0xFF: /* FDIV %st(0),%st(?) */
6116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_do_op_ST_ST ( "div", Iop_DivF64, 0, modrm - 0xF8, False );
6117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
6120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto decode_fail;
6121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
6122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDD opcodes +-+-+-+-+-+-+-+ */
6127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
6128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (first_opcode == 0xDD) {
6129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (modrm < 0xC0) {
6131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* bits 5,4,3 are an opcode extension, and the modRM also
6133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            specifies an address. */
6134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp addr = disAMode( &len, vbi, pfx, delta, dis_buf, 0 );
6135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         delta += len;
6136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (gregLO3ofRM(modrm)) {
6138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0: /* FLD double-real */
6140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fldl %s\n", dis_buf);
6141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_push();
6142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST(0, loadLE(Ity_F64, mkexpr(addr)));
6143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 1: /* FISTTPQ m64 (SSE3) */
6146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fistppll %s\n", dis_buf);
6147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               storeLE( mkexpr(addr),
6148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_F64toI64S, mkU32(Irrm_ZERO), get_ST(0)) );
6149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_pop();
6150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 2: /* FST double-real */
6153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fstl %s\n", dis_buf);
6154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               storeLE(mkexpr(addr), get_ST(0));
6155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 3: /* FSTP double-real */
6158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fstpl %s\n", dis_buf);
6159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               storeLE(mkexpr(addr), get_ST(0));
6160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_pop();
6161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6163663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 4: { /* FRSTOR m94/m108 */
6164663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               IRTemp   ew = newTemp(Ity_I32);
6165663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               IRTemp  w64 = newTemp(Ity_I64);
6166663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               IRDirty*  d;
6167663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if ( have66(pfx) ) {
6168663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  /* Uses dirty helper:
6169663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     VexEmWarn amd64g_dirtyhelper_FRSTORS
6170663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  ( VexGuestAMD64State*, HWord ) */
6171663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  d = unsafeIRDirty_0_N (
6172663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         0/*regparms*/,
6173663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         "amd64g_dirtyhelper_FRSTORS",
6174663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         &amd64g_dirtyhelper_FRSTORS,
6175663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         mkIRExprVec_1( mkexpr(addr) )
6176663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      );
6177663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  d->mSize = 94;
6178663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               } else {
6179663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  /* Uses dirty helper:
6180663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     VexEmWarn amd64g_dirtyhelper_FRSTOR
6181663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  ( VexGuestAMD64State*, HWord ) */
6182663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  d = unsafeIRDirty_0_N (
6183663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         0/*regparms*/,
6184663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         "amd64g_dirtyhelper_FRSTOR",
6185663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         &amd64g_dirtyhelper_FRSTOR,
6186663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         mkIRExprVec_1( mkexpr(addr) )
6187663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      );
6188663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  d->mSize = 108;
6189663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
6190663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
6191663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               d->needsBBP = True;
6192663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               d->tmp      = w64;
6193663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* declare we're reading memory */
6194663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               d->mFx   = Ifx_Read;
6195663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               d->mAddr = mkexpr(addr);
6196663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* d->mSize set above */
6197663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
6198663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* declare we're writing guest state */
6199663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               d->nFxState = 5;
6200663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               vex_bzero(&d->fxState, sizeof(d->fxState));
6201663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
6202663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               d->fxState[0].fx     = Ifx_Write;
6203663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               d->fxState[0].offset = OFFB_FTOP;
6204663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               d->fxState[0].size   = sizeof(UInt);
6205663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
6206663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               d->fxState[1].fx     = Ifx_Write;
6207663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               d->fxState[1].offset = OFFB_FPREGS;
6208663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               d->fxState[1].size   = 8 * sizeof(ULong);
6209663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
6210663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               d->fxState[2].fx     = Ifx_Write;
6211663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               d->fxState[2].offset = OFFB_FPTAGS;
6212663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               d->fxState[2].size   = 8 * sizeof(UChar);
6213663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
6214663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               d->fxState[3].fx     = Ifx_Write;
6215663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               d->fxState[3].offset = OFFB_FPROUND;
6216663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               d->fxState[3].size   = sizeof(ULong);
6217663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
6218663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               d->fxState[4].fx     = Ifx_Write;
6219663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               d->fxState[4].offset = OFFB_FC3210;
6220663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               d->fxState[4].size   = sizeof(ULong);
6221663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
6222663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               stmt( IRStmt_Dirty(d) );
6223663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
6224663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* ew contains any emulation warning we may need to
6225663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  issue.  If needed, side-exit to the next insn,
6226663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  reporting the warning, so that Valgrind's dispatcher
6227663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  sees the warning. */
6228663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               assign(ew, unop(Iop_64to32,mkexpr(w64)) );
6229663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               put_emwarn( mkexpr(ew) );
6230663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               stmt(
6231663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  IRStmt_Exit(
6232663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     binop(Iop_CmpNE32, mkexpr(ew), mkU32(0)),
6233663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     Ijk_EmWarn,
6234663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     IRConst_U64( guest_RIP_bbstart+delta ),
6235663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     OFFB_RIP
6236663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  )
6237663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               );
6238663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
6239663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if ( have66(pfx) ) {
6240663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  DIP("frstors %s\n", dis_buf);
6241663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               } else {
6242663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  DIP("frstor %s\n", dis_buf);
6243663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
6244663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               break;
6245663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            }
6246663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
6247663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 6: { /* FNSAVE m94/m108 */
6248663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               IRDirty *d;
6249663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if ( have66(pfx) ) {
6250663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 /* Uses dirty helper:
6251663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    void amd64g_dirtyhelper_FNSAVES ( VexGuestX86State*, HWord ) */
6252663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  d = unsafeIRDirty_0_N (
6253663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         0/*regparms*/,
6254663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         "amd64g_dirtyhelper_FNSAVES",
6255663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         &amd64g_dirtyhelper_FNSAVES,
6256663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         mkIRExprVec_1( mkexpr(addr) )
6257663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         );
6258663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  d->mSize = 94;
6259663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               } else {
6260663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 /* Uses dirty helper:
6261663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    void amd64g_dirtyhelper_FNSAVE ( VexGuestX86State*, HWord ) */
6262663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  d = unsafeIRDirty_0_N (
6263663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         0/*regparms*/,
6264663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         "amd64g_dirtyhelper_FNSAVE",
6265663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         &amd64g_dirtyhelper_FNSAVE,
6266663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         mkIRExprVec_1( mkexpr(addr) )
6267663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         );
6268663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  d->mSize = 108;
6269663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
6270663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               d->needsBBP = True;
6271663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* declare we're writing memory */
6272663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               d->mFx   = Ifx_Write;
6273663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               d->mAddr = mkexpr(addr);
6274663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* d->mSize set above */
6275663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
6276663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* declare we're reading guest state */
6277663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               d->nFxState = 5;
6278663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               vex_bzero(&d->fxState, sizeof(d->fxState));
6279663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
6280663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               d->fxState[0].fx     = Ifx_Read;
6281663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               d->fxState[0].offset = OFFB_FTOP;
6282663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               d->fxState[0].size   = sizeof(UInt);
6283663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
6284663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               d->fxState[1].fx     = Ifx_Read;
6285663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               d->fxState[1].offset = OFFB_FPREGS;
6286663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               d->fxState[1].size   = 8 * sizeof(ULong);
6287663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
6288663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               d->fxState[2].fx     = Ifx_Read;
6289663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               d->fxState[2].offset = OFFB_FPTAGS;
6290663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               d->fxState[2].size   = 8 * sizeof(UChar);
6291663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
6292663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               d->fxState[3].fx     = Ifx_Read;
6293663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               d->fxState[3].offset = OFFB_FPROUND;
6294663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               d->fxState[3].size   = sizeof(ULong);
6295663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
6296663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               d->fxState[4].fx     = Ifx_Read;
6297663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               d->fxState[4].offset = OFFB_FC3210;
6298663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               d->fxState[4].size   = sizeof(ULong);
6299663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
6300663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               stmt( IRStmt_Dirty(d) );
6301663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
6302663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if ( have66(pfx) ) {
6303663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 DIP("fnsaves %s\n", dis_buf);
6304663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               } else {
6305663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 DIP("fnsave %s\n", dis_buf);
6306663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
6307663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               break;
6308663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            }
6309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 7: { /* FNSTSW m16 */
6311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRExpr* sw = get_FPU_sw();
6312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(typeOfIRExpr(irsb->tyenv, sw) == Ity_I16);
6313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               storeLE( mkexpr(addr), sw );
6314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fnstsw %s\n", dis_buf);
6315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
6317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
6319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf("unhandled opc_aux = 0x%2x\n", gregLO3ofRM(modrm));
6320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf("first_opcode == 0xDD\n");
6321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto decode_fail;
6322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
6323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
6324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         delta++;
6325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (modrm) {
6326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xC0 ... 0xC7: /* FFREE %st(?) */
6328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               r_dst = (UInt)modrm - 0xC0;
6329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("ffree %%st(%u)\n", r_dst);
6330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST_TAG ( r_dst, mkU8(0) );
6331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xD0 ... 0xD7: /* FST %st(0),%st(?) */
6334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               r_dst = (UInt)modrm - 0xD0;
6335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fst %%st(0),%%st(%u)\n", r_dst);
6336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* P4 manual says: "If the destination operand is a
6337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  non-empty register, the invalid-operation exception
6338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  is not generated.  Hence put_ST_UNCHECKED. */
6339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST_UNCHECKED(r_dst, get_ST(0));
6340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xD8 ... 0xDF: /* FSTP %st(0),%st(?) */
6343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               r_dst = (UInt)modrm - 0xD8;
6344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fstp %%st(0),%%st(%u)\n", r_dst);
6345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* P4 manual says: "If the destination operand is a
6346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  non-empty register, the invalid-operation exception
6347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  is not generated.  Hence put_ST_UNCHECKED. */
6348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST_UNCHECKED(r_dst, get_ST(0));
6349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_pop();
6350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xE0 ... 0xE7: /* FUCOM %st(0),%st(?) */
6353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               r_dst = (UInt)modrm - 0xE0;
6354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fucom %%st(0),%%st(%u)\n", r_dst);
6355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* This forces C1 to zero, which isn't right. */
6356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_C3210(
6357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   unop(Iop_32Uto64,
6358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   binop( Iop_And32,
6359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          binop(Iop_Shl32,
6360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                binop(Iop_CmpF64, get_ST(0), get_ST(r_dst)),
6361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                mkU8(8)),
6362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          mkU32(0x4500)
6363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   )));
6364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xE8 ... 0xEF: /* FUCOMP %st(0),%st(?) */
6367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               r_dst = (UInt)modrm - 0xE8;
6368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fucomp %%st(0),%%st(%u)\n", r_dst);
6369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* This forces C1 to zero, which isn't right. */
6370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_C3210(
6371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   unop(Iop_32Uto64,
6372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   binop( Iop_And32,
6373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          binop(Iop_Shl32,
6374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                binop(Iop_CmpF64, get_ST(0), get_ST(r_dst)),
6375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                mkU8(8)),
6376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          mkU32(0x4500)
6377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   )));
6378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_pop();
6379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
6382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto decode_fail;
6383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
6384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDE opcodes +-+-+-+-+-+-+-+ */
6388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
6389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (first_opcode == 0xDE) {
6390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (modrm < 0xC0) {
6392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* bits 5,4,3 are an opcode extension, and the modRM also
6394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            specifies an address. */
6395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IROp   fop;
6396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp addr = disAMode( &len, vbi, pfx, delta, dis_buf, 0 );
6397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         delta += len;
6398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (gregLO3ofRM(modrm)) {
6400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0: /* FIADD m16int */ /* ST(0) += m16int */
6402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fiaddw %s\n", dis_buf);
6403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fop = Iop_AddF64;
6404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto do_fop_m16;
6405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 1: /* FIMUL m16int */ /* ST(0) *= m16int */
6407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fimulw %s\n", dis_buf);
6408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fop = Iop_MulF64;
6409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto do_fop_m16;
6410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 4: /* FISUB m16int */ /* ST(0) -= m16int */
6412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fisubw %s\n", dis_buf);
6413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fop = Iop_SubF64;
6414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto do_fop_m16;
6415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 5: /* FISUBR m16int */ /* ST(0) = m16int - ST(0) */
6417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fisubrw %s\n", dis_buf);
6418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fop = Iop_SubF64;
6419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto do_foprev_m16;
6420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 6: /* FIDIV m16int */ /* ST(0) /= m16int */
6422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fisubw %s\n", dis_buf);
6423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fop = Iop_DivF64;
6424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto do_fop_m16;
6425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 7: /* FIDIVR m16int */ /* ST(0) = m16int / ST(0) */
6427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fidivrw %s\n", dis_buf);
6428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fop = Iop_DivF64;
6429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto do_foprev_m16;
6430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            do_fop_m16:
6432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST_UNCHECKED(0,
6433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  triop(fop,
6434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
6435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        get_ST(0),
6436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        unop(Iop_I32StoF64,
6437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             unop(Iop_16Sto32,
6438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  loadLE(Ity_I16, mkexpr(addr))))));
6439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            do_foprev_m16:
6442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST_UNCHECKED(0,
6443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  triop(fop,
6444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
6445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        unop(Iop_I32StoF64,
6446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             unop(Iop_16Sto32,
6447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  loadLE(Ity_I16, mkexpr(addr)))),
6448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        get_ST(0)));
6449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
6452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf("unhandled opc_aux = 0x%2x\n", gregLO3ofRM(modrm));
6453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf("first_opcode == 0xDE\n");
6454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto decode_fail;
6455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
6456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
6458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         delta++;
6460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (modrm) {
6461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xC0 ... 0xC7: /* FADDP %st(0),%st(?) */
6463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_do_op_ST_ST ( "add", Iop_AddF64, 0, modrm - 0xC0, True );
6464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xC8 ... 0xCF: /* FMULP %st(0),%st(?) */
6467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_do_op_ST_ST ( "mul", Iop_MulF64, 0, modrm - 0xC8, True );
6468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xD9: /* FCOMPP %st(0),%st(1) */
6471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fcompp %%st(0),%%st(1)\n");
6472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* This forces C1 to zero, which isn't right. */
6473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_C3210(
6474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   unop(Iop_32Uto64,
6475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   binop( Iop_And32,
6476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          binop(Iop_Shl32,
6477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                binop(Iop_CmpF64, get_ST(0), get_ST(1)),
6478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                mkU8(8)),
6479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          mkU32(0x4500)
6480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   )));
6481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_pop();
6482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_pop();
6483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xE0 ... 0xE7: /* FSUBRP %st(0),%st(?) */
6486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_do_oprev_ST_ST ( "subr", Iop_SubF64, 0,  modrm - 0xE0, True );
6487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xE8 ... 0xEF: /* FSUBP %st(0),%st(?) */
6490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_do_op_ST_ST ( "sub", Iop_SubF64, 0,  modrm - 0xE8, True );
6491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xF0 ... 0xF7: /* FDIVRP %st(0),%st(?) */
6494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_do_oprev_ST_ST ( "divr", Iop_DivF64, 0, modrm - 0xF0, True );
6495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xF8 ... 0xFF: /* FDIVP %st(0),%st(?) */
6498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_do_op_ST_ST ( "div", Iop_DivF64, 0, modrm - 0xF8, True );
6499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
6502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto decode_fail;
6503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
6504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDF opcodes +-+-+-+-+-+-+-+ */
6509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
6510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (first_opcode == 0xDF) {
6511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (modrm < 0xC0) {
6513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* bits 5,4,3 are an opcode extension, and the modRM also
6515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            specifies an address. */
6516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp addr = disAMode( &len, vbi, pfx, delta, dis_buf, 0 );
6517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         delta += len;
6518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (gregLO3ofRM(modrm)) {
6520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0: /* FILD m16int */
6522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fildw %s\n", dis_buf);
6523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_push();
6524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST(0, unop(Iop_I32StoF64,
6525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              unop(Iop_16Sto32,
6526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   loadLE(Ity_I16, mkexpr(addr)))));
6527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 1: /* FISTTPS m16 (SSE3) */
6530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fisttps %s\n", dis_buf);
6531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               storeLE( mkexpr(addr),
6532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        x87ishly_qnarrow_32_to_16(
6533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_F64toI32S, mkU32(Irrm_ZERO), get_ST(0)) ));
6534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_pop();
6535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 2: /* FIST m16 */
6538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fists %s\n", dis_buf);
6539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               storeLE( mkexpr(addr),
6540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        x87ishly_qnarrow_32_to_16(
6541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_F64toI32S, get_roundingmode(), get_ST(0)) ));
6542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 3: /* FISTP m16 */
6545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fistps %s\n", dis_buf);
6546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               storeLE( mkexpr(addr),
6547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        x87ishly_qnarrow_32_to_16(
6548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_F64toI32S, get_roundingmode(), get_ST(0)) ));
6549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_pop();
6550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 5: /* FILD m64 */
6553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fildll %s\n", dis_buf);
6554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_push();
6555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST(0, binop(Iop_I64StoF64,
6556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               get_roundingmode(),
6557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               loadLE(Ity_I64, mkexpr(addr))));
6558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 7: /* FISTP m64 */
6561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fistpll %s\n", dis_buf);
6562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               storeLE( mkexpr(addr),
6563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_F64toI64S, get_roundingmode(), get_ST(0)) );
6564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_pop();
6565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
6568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf("unhandled opc_aux = 0x%2x\n", gregLO3ofRM(modrm));
6569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf("first_opcode == 0xDF\n");
6570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto decode_fail;
6571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
6572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
6574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         delta++;
6576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (modrm) {
6577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xC0: /* FFREEP %st(0) */
6579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("ffreep %%st(%d)\n", 0);
6580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               put_ST_TAG ( 0, mkU8(0) );
6581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_pop();
6582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xE0: /* FNSTSW %ax */
6585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("fnstsw %%ax\n");
6586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* Invent a plausible-looking FPU status word value and
6587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  dump it in %AX:
6588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     ((ftop & 7) << 11) | (c3210 & 0x4700)
6589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               */
6590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putIRegRAX(
6591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  2,
6592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  unop(Iop_32to16,
6593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop(Iop_Or32,
6594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             binop(Iop_Shl32,
6595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   binop(Iop_And32, get_ftop(), mkU32(7)),
6596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   mkU8(11)),
6597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             binop(Iop_And32,
6598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   unop(Iop_64to32, get_C3210()),
6599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   mkU32(0x4700))
6600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               )));
6601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xE8 ... 0xEF: /* FUCOMIP %st(0),%st(?) */
6604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_do_ucomi_ST0_STi( (UInt)modrm - 0xE8, True );
6605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xF0 ... 0xF7: /* FCOMIP %st(0),%st(?) */
6608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* not really right since COMIP != UCOMIP */
6609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fp_do_ucomi_ST0_STi( (UInt)modrm - 0xF0, True );
6610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
6613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto decode_fail;
6614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
6615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
6620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_fail;
6621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *decode_ok = True;
6623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return delta;
6624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  decode_fail:
6626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *decode_ok = False;
6627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return delta;
6628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
6632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---                                                      ---*/
6633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- MMX INSTRUCTIONS                                     ---*/
6634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---                                                      ---*/
6635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
6636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Effect of MMX insns on x87 FPU state (table 11-2 of
6638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IA32 arch manual, volume 3):
6639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Read from, or write to MMX register (viz, any insn except EMMS):
6641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * All tags set to Valid (non-empty) -- FPTAGS[i] := nonzero
6642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * FP stack pointer set to zero
6643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   EMMS:
6645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * All tags set to Invalid (empty) -- FPTAGS[i] := zero
6646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * FP stack pointer set to zero
6647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
6648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void do_MMX_preamble ( void )
6650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int         i;
6652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRRegArray* descr = mkIRRegArray( OFFB_FPTAGS, Ity_I8, 8 );
6653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr*     zero  = mkU32(0);
6654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr*     tag1  = mkU8(1);
6655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   put_ftop(zero);
6656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < 8; i++)
6657663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      stmt( IRStmt_PutI( mkIRPutI(descr, zero, i, tag1) ) );
6658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void do_EMMS_preamble ( void )
6661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int         i;
6663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRRegArray* descr = mkIRRegArray( OFFB_FPTAGS, Ity_I8, 8 );
6664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr*     zero  = mkU32(0);
6665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr*     tag0  = mkU8(0);
6666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   put_ftop(zero);
6667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < 8; i++)
6668663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      stmt( IRStmt_PutI( mkIRPutI(descr, zero, i, tag0) ) );
6669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* getMMXReg ( UInt archreg )
6673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(archreg < 8);
6675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Get( OFFB_FPREGS + 8 * archreg, Ity_I64 );
6676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void putMMXReg ( UInt archreg, IRExpr* e )
6680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(archreg < 8);
6682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv,e) == Ity_I64);
6683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_FPREGS + 8 * archreg, e ) );
6684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Helper for non-shift MMX insns.  Note this is incomplete in the
6688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sense that it does not first call do_MMX_preamble() -- that is the
6689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   responsibility of its caller. */
6690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
6692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong dis_MMXop_regmem_to_reg ( VexAbiInfo* vbi,
6693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                Prefix      pfx,
6694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                Long        delta,
6695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                UChar       opc,
6696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                HChar*      name,
6697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                Bool        show_granularity )
6698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar   dis_buf[50];
6700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar   modrm = getUChar(delta);
6701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool    isReg = epartIsReg(modrm);
6702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* argL  = NULL;
6703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* argR  = NULL;
6704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* argG  = NULL;
6705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* argE  = NULL;
6706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  res   = newTemp(Ity_I64);
6707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool    invG  = False;
6709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IROp    op    = Iop_INVALID;
6710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   void*   hAddr = NULL;
6711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar*  hName = NULL;
6712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool    eLeft = False;
6713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define XXX(_name) do { hAddr = &_name; hName = #_name; } while (0)
6715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (opc) {
6717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Original MMX ones */
6718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xFC: op = Iop_Add8x8; break;
6719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xFD: op = Iop_Add16x4; break;
6720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xFE: op = Iop_Add32x2; break;
6721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xEC: op = Iop_QAdd8Sx8; break;
6723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xED: op = Iop_QAdd16Sx4; break;
6724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xDC: op = Iop_QAdd8Ux8; break;
6726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xDD: op = Iop_QAdd16Ux4; break;
6727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xF8: op = Iop_Sub8x8;  break;
6729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xF9: op = Iop_Sub16x4; break;
6730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xFA: op = Iop_Sub32x2; break;
6731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xE8: op = Iop_QSub8Sx8; break;
6733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xE9: op = Iop_QSub16Sx4; break;
6734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xD8: op = Iop_QSub8Ux8; break;
6736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xD9: op = Iop_QSub16Ux4; break;
6737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xE5: op = Iop_MulHi16Sx4; break;
6739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xD5: op = Iop_Mul16x4; break;
6740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xF5: XXX(amd64g_calculate_mmx_pmaddwd); break;
6741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x74: op = Iop_CmpEQ8x8; break;
6743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x75: op = Iop_CmpEQ16x4; break;
6744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x76: op = Iop_CmpEQ32x2; break;
6745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x64: op = Iop_CmpGT8Sx8; break;
6747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x65: op = Iop_CmpGT16Sx4; break;
6748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x66: op = Iop_CmpGT32Sx2; break;
6749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6750b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x6B: op = Iop_QNarrowBin32Sto16Sx4; eLeft = True; break;
6751b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x63: op = Iop_QNarrowBin16Sto8Sx8;  eLeft = True; break;
6752b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x67: op = Iop_QNarrowBin16Sto8Ux8;  eLeft = True; break;
6753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x68: op = Iop_InterleaveHI8x8;  eLeft = True; break;
6755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x69: op = Iop_InterleaveHI16x4; eLeft = True; break;
6756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x6A: op = Iop_InterleaveHI32x2; eLeft = True; break;
6757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x60: op = Iop_InterleaveLO8x8;  eLeft = True; break;
6759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x61: op = Iop_InterleaveLO16x4; eLeft = True; break;
6760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x62: op = Iop_InterleaveLO32x2; eLeft = True; break;
6761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xDB: op = Iop_And64; break;
6763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xDF: op = Iop_And64; invG = True; break;
6764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xEB: op = Iop_Or64; break;
6765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xEF: /* Possibly do better here if argL and argR are the
6766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    same reg */
6767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 op = Iop_Xor64; break;
6768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Introduced in SSE1 */
6770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xE0: op = Iop_Avg8Ux8;    break;
6771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xE3: op = Iop_Avg16Ux4;   break;
6772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xEE: op = Iop_Max16Sx4;   break;
6773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xDE: op = Iop_Max8Ux8;    break;
6774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xEA: op = Iop_Min16Sx4;   break;
6775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xDA: op = Iop_Min8Ux8;    break;
6776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xE4: op = Iop_MulHi16Ux4; break;
6777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xF6: XXX(amd64g_calculate_mmx_psadbw); break;
6778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Introduced in SSE2 */
6780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xD4: op = Iop_Add64; break;
6781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xFB: op = Iop_Sub64; break;
6782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
6784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n0x%x\n", (Int)opc);
6785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("dis_MMXop_regmem_to_reg");
6786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef XXX
6789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   argG = getMMXReg(gregLO3ofRM(modrm));
6791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (invG)
6792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      argG = unop(Iop_Not64, argG);
6793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (isReg) {
6795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delta++;
6796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      argE = getMMXReg(eregLO3ofRM(modrm));
6797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
6798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int    len;
6799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp addr = disAMode( &len, vbi, pfx, delta, dis_buf, 0 );
6800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delta += len;
6801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      argE = loadLE(Ity_I64, mkexpr(addr));
6802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (eLeft) {
6805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      argL = argE;
6806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      argR = argG;
6807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
6808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      argL = argG;
6809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      argR = argE;
6810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (op != Iop_INVALID) {
6813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(hName == NULL);
6814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(hAddr == NULL);
6815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(res, binop(op, argL, argR));
6816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
6817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(hName != NULL);
6818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(hAddr != NULL);
6819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( res,
6820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              mkIRExprCCall(
6821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 Ity_I64,
6822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 0/*regparms*/, hName, hAddr,
6823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 mkIRExprVec_2( argL, argR )
6824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              )
6825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            );
6826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   putMMXReg( gregLO3ofRM(modrm), mkexpr(res) );
6829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DIP("%s%s %s, %s\n",
6831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       name, show_granularity ? nameMMXGran(opc & 3) : "",
6832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       ( isReg ? nameMMXReg(eregLO3ofRM(modrm)) : dis_buf ),
6833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       nameMMXReg(gregLO3ofRM(modrm)) );
6834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return delta;
6836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Vector by scalar shift of G by the amount specified at the bottom
6840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   of E.  This is a straight copy of dis_SSE_shiftG_byE. */
6841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong dis_MMX_shiftG_byE ( VexAbiInfo* vbi,
6843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  Prefix pfx, Long delta,
6844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  HChar* opname, IROp op )
6845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar   dis_buf[50];
6847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     alen, size;
6848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  addr;
6849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool    shl, shr, sar;
6850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar   rm   = getUChar(delta);
6851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  g0   = newTemp(Ity_I64);
6852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  g1   = newTemp(Ity_I64);
6853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  amt  = newTemp(Ity_I64);
6854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  amt8 = newTemp(Ity_I8);
6855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (epartIsReg(rm)) {
6857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( amt, getMMXReg(eregLO3ofRM(rm)) );
6858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("%s %s,%s\n", opname,
6859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        nameMMXReg(eregLO3ofRM(rm)),
6860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        nameMMXReg(gregLO3ofRM(rm)) );
6861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delta++;
6862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
6863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
6864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( amt, loadLE(Ity_I64, mkexpr(addr)) );
6865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("%s %s,%s\n", opname,
6866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        dis_buf,
6867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        nameMMXReg(gregLO3ofRM(rm)) );
6868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delta += alen;
6869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( g0,   getMMXReg(gregLO3ofRM(rm)) );
6871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( amt8, unop(Iop_64to8, mkexpr(amt)) );
6872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   shl = shr = sar = False;
6874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   size = 0;
6875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op) {
6876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShlN16x4: shl = True; size = 32; break;
6877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShlN32x2: shl = True; size = 32; break;
6878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shl64:    shl = True; size = 64; break;
6879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShrN16x4: shr = True; size = 16; break;
6880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShrN32x2: shr = True; size = 32; break;
6881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shr64:    shr = True; size = 64; break;
6882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SarN16x4: sar = True; size = 16; break;
6883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SarN32x2: sar = True; size = 32; break;
6884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vassert(0);
6885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (shl || shr) {
6888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     assign(
6889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        g1,
6890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRExpr_Mux0X(
6891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           unop(Iop_1Uto8,binop(Iop_CmpLT64U,mkexpr(amt),mkU64(size))),
6892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           mkU64(0),
6893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           binop(op, mkexpr(g0), mkexpr(amt8))
6894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        )
6895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     );
6896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else
6897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (sar) {
6898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     assign(
6899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        g1,
6900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRExpr_Mux0X(
6901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           unop(Iop_1Uto8,binop(Iop_CmpLT64U,mkexpr(amt),mkU64(size))),
6902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           binop(op, mkexpr(g0), mkU8(size-1)),
6903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           binop(op, mkexpr(g0), mkexpr(amt8))
6904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        )
6905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     );
6906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
6907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(0);
6908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   putMMXReg( gregLO3ofRM(rm), mkexpr(g1) );
6911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return delta;
6912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Vector by scalar shift of E by an immediate byte.  This is a
6916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   straight copy of dis_SSE_shiftE_imm. */
6917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
6919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong dis_MMX_shiftE_imm ( Long delta, HChar* opname, IROp op )
6920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool    shl, shr, sar;
6922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar   rm   = getUChar(delta);
6923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  e0   = newTemp(Ity_I64);
6924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  e1   = newTemp(Ity_I64);
6925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar   amt, size;
6926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(epartIsReg(rm));
6927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(gregLO3ofRM(rm) == 2
6928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || gregLO3ofRM(rm) == 4 || gregLO3ofRM(rm) == 6);
6929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   amt = getUChar(delta+1);
6930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   delta += 2;
6931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DIP("%s $%d,%s\n", opname,
6932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      (Int)amt,
6933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      nameMMXReg(eregLO3ofRM(rm)) );
6934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( e0, getMMXReg(eregLO3ofRM(rm)) );
6936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   shl = shr = sar = False;
6938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   size = 0;
6939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op) {
6940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShlN16x4: shl = True; size = 16; break;
6941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShlN32x2: shl = True; size = 32; break;
6942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shl64:    shl = True; size = 64; break;
6943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SarN16x4: sar = True; size = 16; break;
6944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SarN32x2: sar = True; size = 32; break;
6945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShrN16x4: shr = True; size = 16; break;
6946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShrN32x2: shr = True; size = 32; break;
6947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shr64:    shr = True; size = 64; break;
6948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vassert(0);
6949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (shl || shr) {
6952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     assign( e1, amt >= size
6953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ? mkU64(0)
6954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    : binop(op, mkexpr(e0), mkU8(amt))
6955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     );
6956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else
6957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (sar) {
6958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     assign( e1, amt >= size
6959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ? binop(op, mkexpr(e0), mkU8(size-1))
6960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    : binop(op, mkexpr(e0), mkU8(amt))
6961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     );
6962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
6963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(0);
6964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   putMMXReg( eregLO3ofRM(rm), mkexpr(e1) );
6967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return delta;
6968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Completely handle all MMX instructions except emms. */
6972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
6974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong dis_MMX ( Bool* decode_ok,
6975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                VexAbiInfo* vbi, Prefix pfx, Int sz, Long delta )
6976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int   len;
6978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar modrm;
6979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar dis_buf[50];
6980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar opc = getUChar(delta);
6981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   delta++;
6982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* dis_MMX handles all insns except emms. */
6984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   do_MMX_preamble();
6985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (opc) {
6987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x6E:
6989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (sz == 4) {
6990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* MOVD (src)ireg32-or-mem32 (E), (dst)mmxreg (G)*/
6991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            modrm = getUChar(delta);
6992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (epartIsReg(modrm)) {
6993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               delta++;
6994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putMMXReg(
6995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  gregLO3ofRM(modrm),
6996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop( Iop_32HLto64,
6997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         mkU32(0),
6998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         getIReg32(eregOfRexRM(pfx,modrm)) ) );
6999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("movd %s, %s\n",
7000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   nameIReg32(eregOfRexRM(pfx,modrm)),
7001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   nameMMXReg(gregLO3ofRM(modrm)));
7002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
7003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp addr = disAMode( &len, vbi, pfx, delta, dis_buf, 0 );
7004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               delta += len;
7005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putMMXReg(
7006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  gregLO3ofRM(modrm),
7007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop( Iop_32HLto64,
7008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         mkU32(0),
7009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         loadLE(Ity_I32, mkexpr(addr)) ) );
7010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("movd %s, %s\n", dis_buf, nameMMXReg(gregLO3ofRM(modrm)));
7011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
7012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
7013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
7014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (sz == 8) {
7015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* MOVD (src)ireg64-or-mem64 (E), (dst)mmxreg (G)*/
7016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            modrm = getUChar(delta);
7017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (epartIsReg(modrm)) {
7018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               delta++;
7019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putMMXReg( gregLO3ofRM(modrm),
7020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          getIReg64(eregOfRexRM(pfx,modrm)) );
7021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("movd %s, %s\n",
7022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   nameIReg64(eregOfRexRM(pfx,modrm)),
7023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   nameMMXReg(gregLO3ofRM(modrm)));
7024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
7025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp addr = disAMode( &len, vbi, pfx, delta, dis_buf, 0 );
7026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               delta += len;
7027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putMMXReg( gregLO3ofRM(modrm),
7028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          loadLE(Ity_I64, mkexpr(addr)) );
7029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("movd{64} %s, %s\n", dis_buf, nameMMXReg(gregLO3ofRM(modrm)));
7030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
7031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
7032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else {
7033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto mmx_decode_failure;
7034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
7035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x7E:
7038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (sz == 4) {
7039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* MOVD (src)mmxreg (G), (dst)ireg32-or-mem32 (E) */
7040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            modrm = getUChar(delta);
7041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (epartIsReg(modrm)) {
7042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               delta++;
7043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putIReg32( eregOfRexRM(pfx,modrm),
7044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          unop(Iop_64to32, getMMXReg(gregLO3ofRM(modrm)) ) );
7045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("movd %s, %s\n",
7046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   nameMMXReg(gregLO3ofRM(modrm)),
7047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   nameIReg32(eregOfRexRM(pfx,modrm)));
7048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
7049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp addr = disAMode( &len, vbi, pfx, delta, dis_buf, 0 );
7050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               delta += len;
7051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               storeLE( mkexpr(addr),
7052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        unop(Iop_64to32, getMMXReg(gregLO3ofRM(modrm)) ) );
7053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("movd %s, %s\n", nameMMXReg(gregLO3ofRM(modrm)), dis_buf);
7054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
7055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
7056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
7057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (sz == 8) {
7058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* MOVD (src)mmxreg (G), (dst)ireg64-or-mem64 (E) */
7059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            modrm = getUChar(delta);
7060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (epartIsReg(modrm)) {
7061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               delta++;
7062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putIReg64( eregOfRexRM(pfx,modrm),
7063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          getMMXReg(gregLO3ofRM(modrm)) );
7064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("movd %s, %s\n",
7065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   nameMMXReg(gregLO3ofRM(modrm)),
7066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   nameIReg64(eregOfRexRM(pfx,modrm)));
7067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
7068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp addr = disAMode( &len, vbi, pfx, delta, dis_buf, 0 );
7069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               delta += len;
7070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               storeLE( mkexpr(addr),
7071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       getMMXReg(gregLO3ofRM(modrm)) );
7072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("movd{64} %s, %s\n", nameMMXReg(gregLO3ofRM(modrm)), dis_buf);
7073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
7074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
7075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto mmx_decode_failure;
7076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
7077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x6F:
7080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* MOVQ (src)mmxreg-or-mem, (dst)mmxreg */
7081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (sz != 4
7082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && /*ignore redundant REX.W*/!(sz==8 && haveNo66noF2noF3(pfx)))
7083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto mmx_decode_failure;
7084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         modrm = getUChar(delta);
7085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (epartIsReg(modrm)) {
7086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            delta++;
7087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putMMXReg( gregLO3ofRM(modrm), getMMXReg(eregLO3ofRM(modrm)) );
7088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("movq %s, %s\n",
7089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                nameMMXReg(eregLO3ofRM(modrm)),
7090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                nameMMXReg(gregLO3ofRM(modrm)));
7091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
7092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp addr = disAMode( &len, vbi, pfx, delta, dis_buf, 0 );
7093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            delta += len;
7094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putMMXReg( gregLO3ofRM(modrm), loadLE(Ity_I64, mkexpr(addr)) );
7095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("movq %s, %s\n",
7096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                dis_buf, nameMMXReg(gregLO3ofRM(modrm)));
7097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
7098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x7F:
7101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* MOVQ (src)mmxreg, (dst)mmxreg-or-mem */
7102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (sz != 4
7103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && /*ignore redundant REX.W*/!(sz==8 && haveNo66noF2noF3(pfx)))
7104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto mmx_decode_failure;
7105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         modrm = getUChar(delta);
7106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (epartIsReg(modrm)) {
7107663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta++;
7108663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putMMXReg( eregLO3ofRM(modrm), getMMXReg(gregLO3ofRM(modrm)) );
7109663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movq %s, %s\n",
7110663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                nameMMXReg(gregLO3ofRM(modrm)),
7111663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                nameMMXReg(eregLO3ofRM(modrm)));
7112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
7113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp addr = disAMode( &len, vbi, pfx, delta, dis_buf, 0 );
7114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            delta += len;
7115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            storeLE( mkexpr(addr), getMMXReg(gregLO3ofRM(modrm)) );
7116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("mov(nt)q %s, %s\n",
7117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                nameMMXReg(gregLO3ofRM(modrm)), dis_buf);
7118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
7119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xFC:
7122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xFD:
7123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xFE: /* PADDgg (src)mmxreg-or-mem, (dst)mmxreg */
7124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (sz != 4)
7125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto mmx_decode_failure;
7126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         delta = dis_MMXop_regmem_to_reg ( vbi, pfx, delta, opc, "padd", True );
7127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xEC:
7130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xED: /* PADDSgg (src)mmxreg-or-mem, (dst)mmxreg */
7131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (sz != 4
7132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && /*ignore redundant REX.W*/!(sz==8 && haveNo66noF2noF3(pfx)))
7133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto mmx_decode_failure;
7134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         delta = dis_MMXop_regmem_to_reg ( vbi, pfx, delta, opc, "padds", True );
7135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xDC:
7138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xDD: /* PADDUSgg (src)mmxreg-or-mem, (dst)mmxreg */
7139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (sz != 4)
7140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto mmx_decode_failure;
7141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         delta = dis_MMXop_regmem_to_reg ( vbi, pfx, delta, opc, "paddus", True );
7142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xF8:
7145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xF9:
7146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xFA: /* PSUBgg (src)mmxreg-or-mem, (dst)mmxreg */
7147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (sz != 4)
7148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto mmx_decode_failure;
7149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         delta = dis_MMXop_regmem_to_reg ( vbi, pfx, delta, opc, "psub", True );
7150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xE8:
7153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xE9: /* PSUBSgg (src)mmxreg-or-mem, (dst)mmxreg */
7154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (sz != 4)
7155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto mmx_decode_failure;
7156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         delta = dis_MMXop_regmem_to_reg ( vbi, pfx, delta, opc, "psubs", True );
7157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xD8:
7160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xD9: /* PSUBUSgg (src)mmxreg-or-mem, (dst)mmxreg */
7161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (sz != 4)
7162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto mmx_decode_failure;
7163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         delta = dis_MMXop_regmem_to_reg ( vbi, pfx, delta, opc, "psubus", True );
7164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xE5: /* PMULHW (src)mmxreg-or-mem, (dst)mmxreg */
7167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (sz != 4)
7168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto mmx_decode_failure;
7169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         delta = dis_MMXop_regmem_to_reg ( vbi, pfx, delta, opc, "pmulhw", False );
7170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xD5: /* PMULLW (src)mmxreg-or-mem, (dst)mmxreg */
7173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (sz != 4)
7174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto mmx_decode_failure;
7175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         delta = dis_MMXop_regmem_to_reg ( vbi, pfx, delta, opc, "pmullw", False );
7176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xF5: /* PMADDWD (src)mmxreg-or-mem, (dst)mmxreg */
7179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(sz == 4);
7180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         delta = dis_MMXop_regmem_to_reg ( vbi, pfx, delta, opc, "pmaddwd", False );
7181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x74:
7184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x75:
7185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x76: /* PCMPEQgg (src)mmxreg-or-mem, (dst)mmxreg */
7186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (sz != 4)
7187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto mmx_decode_failure;
7188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         delta = dis_MMXop_regmem_to_reg ( vbi, pfx, delta, opc, "pcmpeq", True );
7189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x64:
7192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x65:
7193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x66: /* PCMPGTgg (src)mmxreg-or-mem, (dst)mmxreg */
7194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (sz != 4)
7195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto mmx_decode_failure;
7196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         delta = dis_MMXop_regmem_to_reg ( vbi, pfx, delta, opc, "pcmpgt", True );
7197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x6B: /* PACKSSDW (src)mmxreg-or-mem, (dst)mmxreg */
7200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (sz != 4)
7201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto mmx_decode_failure;
7202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         delta = dis_MMXop_regmem_to_reg ( vbi, pfx, delta, opc, "packssdw", False );
7203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x63: /* PACKSSWB (src)mmxreg-or-mem, (dst)mmxreg */
7206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (sz != 4)
7207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto mmx_decode_failure;
7208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         delta = dis_MMXop_regmem_to_reg ( vbi, pfx, delta, opc, "packsswb", False );
7209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x67: /* PACKUSWB (src)mmxreg-or-mem, (dst)mmxreg */
7212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (sz != 4)
7213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto mmx_decode_failure;
7214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         delta = dis_MMXop_regmem_to_reg ( vbi, pfx, delta, opc, "packuswb", False );
7215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x68:
7218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x69:
7219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x6A: /* PUNPCKHgg (src)mmxreg-or-mem, (dst)mmxreg */
7220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (sz != 4
7221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && /*ignore redundant REX.W*/!(sz==8 && haveNo66noF2noF3(pfx)))
7222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto mmx_decode_failure;
7223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         delta = dis_MMXop_regmem_to_reg ( vbi, pfx, delta, opc, "punpckh", True );
7224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x60:
7227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x61:
7228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x62: /* PUNPCKLgg (src)mmxreg-or-mem, (dst)mmxreg */
7229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (sz != 4
7230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && /*ignore redundant REX.W*/!(sz==8 && haveNo66noF2noF3(pfx)))
7231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto mmx_decode_failure;
7232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         delta = dis_MMXop_regmem_to_reg ( vbi, pfx, delta, opc, "punpckl", True );
7233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xDB: /* PAND (src)mmxreg-or-mem, (dst)mmxreg */
7236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (sz != 4)
7237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto mmx_decode_failure;
7238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         delta = dis_MMXop_regmem_to_reg ( vbi, pfx, delta, opc, "pand", False );
7239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xDF: /* PANDN (src)mmxreg-or-mem, (dst)mmxreg */
7242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (sz != 4)
7243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto mmx_decode_failure;
7244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         delta = dis_MMXop_regmem_to_reg ( vbi, pfx, delta, opc, "pandn", False );
7245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xEB: /* POR (src)mmxreg-or-mem, (dst)mmxreg */
7248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (sz != 4)
7249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto mmx_decode_failure;
7250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         delta = dis_MMXop_regmem_to_reg ( vbi, pfx, delta, opc, "por", False );
7251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xEF: /* PXOR (src)mmxreg-or-mem, (dst)mmxreg */
7254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (sz != 4)
7255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto mmx_decode_failure;
7256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         delta = dis_MMXop_regmem_to_reg ( vbi, pfx, delta, opc, "pxor", False );
7257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#     define SHIFT_BY_REG(_name,_op)                                     \
7260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                delta = dis_MMX_shiftG_byE(vbi, pfx, delta, _name, _op); \
7261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
7262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* PSLLgg (src)mmxreg-or-mem, (dst)mmxreg */
7264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xF1: SHIFT_BY_REG("psllw", Iop_ShlN16x4);
7265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xF2: SHIFT_BY_REG("pslld", Iop_ShlN32x2);
7266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xF3: SHIFT_BY_REG("psllq", Iop_Shl64);
7267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* PSRLgg (src)mmxreg-or-mem, (dst)mmxreg */
7269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xD1: SHIFT_BY_REG("psrlw", Iop_ShrN16x4);
7270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xD2: SHIFT_BY_REG("psrld", Iop_ShrN32x2);
7271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xD3: SHIFT_BY_REG("psrlq", Iop_Shr64);
7272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* PSRAgg (src)mmxreg-or-mem, (dst)mmxreg */
7274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xE1: SHIFT_BY_REG("psraw", Iop_SarN16x4);
7275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xE2: SHIFT_BY_REG("psrad", Iop_SarN32x2);
7276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#     undef SHIFT_BY_REG
7278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x71:
7280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x72:
7281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x73: {
7282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* (sz==4): PSLLgg/PSRAgg/PSRLgg mmxreg by imm8 */
7283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UChar byte2, subopc;
7284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (sz != 4)
7285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto mmx_decode_failure;
7286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         byte2  = getUChar(delta);      /* amode / sub-opcode */
7287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         subopc = toUChar( (byte2 >> 3) & 7 );
7288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#        define SHIFT_BY_IMM(_name,_op)                        \
7290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            do { delta = dis_MMX_shiftE_imm(delta,_name,_op);  \
7291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } while (0)
7292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              if (subopc == 2 /*SRL*/ && opc == 0x71)
7294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  SHIFT_BY_IMM("psrlw", Iop_ShrN16x4);
7295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else if (subopc == 2 /*SRL*/ && opc == 0x72)
7296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 SHIFT_BY_IMM("psrld", Iop_ShrN32x2);
7297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else if (subopc == 2 /*SRL*/ && opc == 0x73)
7298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 SHIFT_BY_IMM("psrlq", Iop_Shr64);
7299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else if (subopc == 4 /*SAR*/ && opc == 0x71)
7301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 SHIFT_BY_IMM("psraw", Iop_SarN16x4);
7302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else if (subopc == 4 /*SAR*/ && opc == 0x72)
7303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 SHIFT_BY_IMM("psrad", Iop_SarN32x2);
7304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else if (subopc == 6 /*SHL*/ && opc == 0x71)
7306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 SHIFT_BY_IMM("psllw", Iop_ShlN16x4);
7307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else if (subopc == 6 /*SHL*/ && opc == 0x72)
7308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  SHIFT_BY_IMM("pslld", Iop_ShlN32x2);
7309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else if (subopc == 6 /*SHL*/ && opc == 0x73)
7310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 SHIFT_BY_IMM("psllq", Iop_Shl64);
7311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else goto mmx_decode_failure;
7313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#        undef SHIFT_BY_IMM
7315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
7317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xF7: {
7319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp addr    = newTemp(Ity_I64);
7320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp regD    = newTemp(Ity_I64);
7321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp regM    = newTemp(Ity_I64);
7322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp mask    = newTemp(Ity_I64);
7323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp olddata = newTemp(Ity_I64);
7324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp newdata = newTemp(Ity_I64);
7325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         modrm = getUChar(delta);
7327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (sz != 4 || (!epartIsReg(modrm)))
7328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto mmx_decode_failure;
7329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         delta++;
7330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( addr, handleAddrOverrides( vbi, pfx, getIReg64(R_RDI) ));
7332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( regM, getMMXReg( eregLO3ofRM(modrm) ));
7333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( regD, getMMXReg( gregLO3ofRM(modrm) ));
7334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( mask, binop(Iop_SarN8x8, mkexpr(regM), mkU8(7)) );
7335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( olddata, loadLE( Ity_I64, mkexpr(addr) ));
7336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( newdata,
7337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(Iop_Or64,
7338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop(Iop_And64,
7339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             mkexpr(regD),
7340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             mkexpr(mask) ),
7341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop(Iop_And64,
7342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             mkexpr(olddata),
7343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             unop(Iop_Not64, mkexpr(mask)))) );
7344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         storeLE( mkexpr(addr), mkexpr(newdata) );
7345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("maskmovq %s,%s\n", nameMMXReg( eregLO3ofRM(modrm) ),
7346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 nameMMXReg( gregLO3ofRM(modrm) ) );
7347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
7349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* --- MMX decode failure --- */
7351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
7352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      mmx_decode_failure:
7353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *decode_ok = False;
7354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return delta; /* ignored */
7355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
7357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *decode_ok = True;
7359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return delta;
7360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
7364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- More misc arithmetic and other obscure insns.        ---*/
7365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
7366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate base << amt with vacated places filled with stuff
7368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   from xtra.  amt guaranteed in 0 .. 63. */
7369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
7370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRExpr* shiftL64_with_extras ( IRTemp base, IRTemp xtra, IRTemp amt )
7371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* if   amt == 0
7373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      then base
7374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else (base << amt) | (xtra >>u (64-amt))
7375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
7376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return
7377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRExpr_Mux0X(
7378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mkexpr(amt),
7379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mkexpr(base),
7380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         binop(Iop_Or64,
7381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(Iop_Shl64, mkexpr(base), mkexpr(amt)),
7382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(Iop_Shr64, mkexpr(xtra),
7383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                binop(Iop_Sub8, mkU8(64), mkexpr(amt)))
7384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         )
7385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      );
7386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate base >>u amt with vacated places filled with stuff
7389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   from xtra.  amt guaranteed in 0 .. 63. */
7390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
7391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRExpr* shiftR64_with_extras ( IRTemp xtra, IRTemp base, IRTemp amt )
7392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* if   amt == 0
7394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      then base
7395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else (base >>u amt) | (xtra << (64-amt))
7396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
7397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return
7398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRExpr_Mux0X(
7399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mkexpr(amt),
7400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mkexpr(base),
7401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         binop(Iop_Or64,
7402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(Iop_Shr64, mkexpr(base), mkexpr(amt)),
7403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(Iop_Shl64, mkexpr(xtra),
7404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                binop(Iop_Sub8, mkU8(64), mkexpr(amt)))
7405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         )
7406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      );
7407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Double length left and right shifts.  Apparently only required in
7410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   v-size (no b- variant). */
7411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
7412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong dis_SHLRD_Gv_Ev ( VexAbiInfo* vbi,
7413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        Prefix pfx,
7414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        Long delta, UChar modrm,
7415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        Int sz,
7416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        IRExpr* shift_amt,
7417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        Bool amt_is_literal,
7418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        HChar* shift_amt_txt,
7419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        Bool left_shift )
7420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* shift_amt :: Ity_I8 is the amount to shift.  shift_amt_txt is used
7422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for printing it.   And eip on entry points at the modrm byte. */
7423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int len;
7424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar dis_buf[50];
7425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty     = szToITy(sz);
7427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp gsrc   = newTemp(ty);
7428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp esrc   = newTemp(ty);
7429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp addr   = IRTemp_INVALID;
7430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp tmpSH  = newTemp(Ity_I8);
7431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp tmpSS  = newTemp(Ity_I8);
7432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp tmp64  = IRTemp_INVALID;
7433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp res64  = IRTemp_INVALID;
7434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp rss64  = IRTemp_INVALID;
7435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp resTy  = IRTemp_INVALID;
7436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp rssTy  = IRTemp_INVALID;
7437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int    mask   = sz==8 ? 63 : 31;
7438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(sz == 2 || sz == 4 || sz == 8);
7440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* The E-part is the destination; this is shifted.  The G-part
7442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      supplies bits to be shifted into the E-part, but is not
7443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      changed.
7444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      If shifting left, form a double-length word with E at the top
7446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      and G at the bottom, and shift this left.  The result is then in
7447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      the high part.
7448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      If shifting right, form a double-length word with G at the top
7450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      and E at the bottom, and shift this right.  The result is then
7451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      at the bottom.  */
7452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Fetch the operands. */
7454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( gsrc, getIRegG(sz, pfx, modrm) );
7456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (epartIsReg(modrm)) {
7458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delta++;
7459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( esrc, getIRegE(sz, pfx, modrm) );
7460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("sh%cd%c %s, %s, %s\n",
7461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          ( left_shift ? 'l' : 'r' ), nameISize(sz),
7462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          shift_amt_txt,
7463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          nameIRegG(sz, pfx, modrm), nameIRegE(sz, pfx, modrm));
7464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
7465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addr = disAMode ( &len, vbi, pfx, delta, dis_buf,
7466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        /* # bytes following amode */
7467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        amt_is_literal ? 1 : 0 );
7468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delta += len;
7469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( esrc, loadLE(ty, mkexpr(addr)) );
7470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("sh%cd%c %s, %s, %s\n",
7471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          ( left_shift ? 'l' : 'r' ), nameISize(sz),
7472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          shift_amt_txt,
7473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          nameIRegG(sz, pfx, modrm), dis_buf);
7474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
7475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Calculate the masked shift amount (tmpSH), the masked subshift
7477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      amount (tmpSS), the shifted value (res64) and the subshifted
7478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      value (rss64). */
7479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( tmpSH, binop(Iop_And8, shift_amt, mkU8(mask)) );
7481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( tmpSS, binop(Iop_And8,
7482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_Sub8, mkexpr(tmpSH), mkU8(1) ),
7483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mkU8(mask)));
7484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tmp64 = newTemp(Ity_I64);
7486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   res64 = newTemp(Ity_I64);
7487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   rss64 = newTemp(Ity_I64);
7488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (sz == 2 || sz == 4) {
7490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* G is xtra; E is data */
7492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* what a freaking nightmare: */
7493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (sz == 4 && left_shift) {
7494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( tmp64, binop(Iop_32HLto64, mkexpr(esrc), mkexpr(gsrc)) );
7495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( res64,
7496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(Iop_Shr64,
7497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop(Iop_Shl64, mkexpr(tmp64), mkexpr(tmpSH)),
7498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       mkU8(32)) );
7499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rss64,
7500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(Iop_Shr64,
7501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop(Iop_Shl64, mkexpr(tmp64), mkexpr(tmpSS)),
7502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       mkU8(32)) );
7503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
7504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
7505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (sz == 4 && !left_shift) {
7506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( tmp64, binop(Iop_32HLto64, mkexpr(gsrc), mkexpr(esrc)) );
7507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( res64, binop(Iop_Shr64, mkexpr(tmp64), mkexpr(tmpSH)) );
7508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rss64, binop(Iop_Shr64, mkexpr(tmp64), mkexpr(tmpSS)) );
7509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
7510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
7511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (sz == 2 && left_shift) {
7512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( tmp64,
7513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(Iop_32HLto64,
7514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop(Iop_16HLto32, mkexpr(esrc), mkexpr(gsrc)),
7515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop(Iop_16HLto32, mkexpr(gsrc), mkexpr(gsrc))
7516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ));
7517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 /* result formed by shifting [esrc'gsrc'gsrc'gsrc] */
7518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( res64,
7519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(Iop_Shr64,
7520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop(Iop_Shl64, mkexpr(tmp64), mkexpr(tmpSH)),
7521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       mkU8(48)) );
7522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* subshift formed by shifting [esrc'0000'0000'0000] */
7523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rss64,
7524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(Iop_Shr64,
7525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop(Iop_Shl64,
7526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             binop(Iop_Shl64, unop(Iop_16Uto64, mkexpr(esrc)),
7527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                              mkU8(48)),
7528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             mkexpr(tmpSS)),
7529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       mkU8(48)) );
7530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
7531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
7532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (sz == 2 && !left_shift) {
7533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( tmp64,
7534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(Iop_32HLto64,
7535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop(Iop_16HLto32, mkexpr(gsrc), mkexpr(gsrc)),
7536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop(Iop_16HLto32, mkexpr(gsrc), mkexpr(esrc))
7537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ));
7538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* result formed by shifting [gsrc'gsrc'gsrc'esrc] */
7539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( res64, binop(Iop_Shr64, mkexpr(tmp64), mkexpr(tmpSH)) );
7540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* subshift formed by shifting [0000'0000'0000'esrc] */
7541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rss64, binop(Iop_Shr64,
7542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              unop(Iop_16Uto64, mkexpr(esrc)),
7543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkexpr(tmpSS)) );
7544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
7545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
7547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(sz == 8);
7549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (left_shift) {
7550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( res64, shiftL64_with_extras( esrc, gsrc, tmpSH ));
7551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rss64, shiftL64_with_extras( esrc, gsrc, tmpSS ));
7552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
7553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( res64, shiftR64_with_extras( gsrc, esrc, tmpSH ));
7554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rss64, shiftR64_with_extras( gsrc, esrc, tmpSS ));
7555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
7556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
7558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   resTy = newTemp(ty);
7560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   rssTy = newTemp(ty);
7561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( resTy, narrowTo(ty, mkexpr(res64)) );
7562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( rssTy, narrowTo(ty, mkexpr(rss64)) );
7563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Put result back and write the flags thunk. */
7565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   setFlags_DEP1_DEP2_shift ( left_shift ? Iop_Shl64 : Iop_Sar64,
7566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              resTy, rssTy, ty, tmpSH );
7567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (epartIsReg(modrm)) {
7569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIRegE(sz, pfx, modrm, mkexpr(resTy));
7570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
7571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      storeLE( mkexpr(addr), mkexpr(resTy) );
7572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
7573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (amt_is_literal) delta++;
7575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return delta;
7576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Handle BT/BTS/BTR/BTC Gv, Ev.  Apparently b-size is not
7580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   required. */
7581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef enum { BtOpNone, BtOpSet, BtOpReset, BtOpComp } BtOp;
7583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HChar* nameBtOp ( BtOp op )
7585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op) {
7587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case BtOpNone:  return "";
7588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case BtOpSet:   return "s";
7589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case BtOpReset: return "r";
7590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case BtOpComp:  return "c";
7591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vpanic("nameBtOp(amd64)");
7592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
7593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
7597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong dis_bt_G_E ( VexAbiInfo* vbi,
7598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   Prefix pfx, Int sz, Long delta, BtOp op )
7599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar  dis_buf[50];
7601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar  modrm;
7602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int    len;
7603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp t_fetched, t_bitno0, t_bitno1, t_bitno2, t_addr0,
7604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     t_addr1, t_rsp, t_mask, t_new;
7605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(sz == 2 || sz == 4 || sz == 8);
7607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   t_fetched = t_bitno0 = t_bitno1 = t_bitno2
7609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             = t_addr0 = t_addr1 = t_rsp
7610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             = t_mask = t_new = IRTemp_INVALID;
7611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   t_fetched = newTemp(Ity_I8);
7613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   t_new     = newTemp(Ity_I8);
7614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   t_bitno0  = newTemp(Ity_I64);
7615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   t_bitno1  = newTemp(Ity_I64);
7616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   t_bitno2  = newTemp(Ity_I8);
7617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   t_addr1   = newTemp(Ity_I64);
7618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   modrm     = getUChar(delta);
7619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( t_bitno0, widenSto64(getIRegG(sz, pfx, modrm)) );
7621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (epartIsReg(modrm)) {
7623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delta++;
7624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Get it onto the client's stack.  Oh, this is a horrible
7625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         kludge.  See https://bugs.kde.org/show_bug.cgi?id=245925.
7626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Because of the ELF ABI stack redzone, there may be live data
7627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         up to 128 bytes below %RSP.  So we can't just push it on the
7628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         stack, else we may wind up trashing live data, and causing
7629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         impossible-to-find simulation errors.  (Yes, this did
7630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         happen.)  So we need to drop RSP before at least 128 before
7631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         pushing it.  That unfortunately means hitting Memcheck's
7632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         fast-case painting code.  Ideally we should drop more than
7633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         128, to reduce the chances of breaking buggy programs that
7634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         have live data below -128(%RSP).  Memcheck fast-cases moves
7635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         of 288 bytes due to the need to handle ppc64-linux quickly,
7636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         so let's use 288.  Of course the real fix is to get rid of
7637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         this kludge entirely.  */
7638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      t_rsp = newTemp(Ity_I64);
7639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      t_addr0 = newTemp(Ity_I64);
7640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(vbi->guest_stack_redzone_size == 128);
7642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( t_rsp, binop(Iop_Sub64, getIReg64(R_RSP), mkU64(288)) );
7643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIReg64(R_RSP, mkexpr(t_rsp));
7644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      storeLE( mkexpr(t_rsp), getIRegE(sz, pfx, modrm) );
7646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Make t_addr0 point at it. */
7648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( t_addr0, mkexpr(t_rsp) );
7649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Mask out upper bits of the shift amount, since we're doing a
7651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         reg. */
7652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( t_bitno1, binop(Iop_And64,
7653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkexpr(t_bitno0),
7654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkU64(sz == 8 ? 63 : sz == 4 ? 31 : 15)) );
7655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
7657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      t_addr0 = disAMode ( &len, vbi, pfx, delta, dis_buf, 0 );
7658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delta += len;
7659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( t_bitno1, mkexpr(t_bitno0) );
7660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
7661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* At this point: t_addr0 is the address being operated on.  If it
7663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      was a reg, we will have pushed it onto the client's stack.
7664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      t_bitno1 is the bit number, suitably masked in the case of a
7665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      reg.  */
7666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Now the main sequence. */
7668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( t_addr1,
7669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           binop(Iop_Add64,
7670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 mkexpr(t_addr0),
7671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(Iop_Sar64, mkexpr(t_bitno1), mkU8(3))) );
7672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* t_addr1 now holds effective address */
7674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( t_bitno2,
7676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           unop(Iop_64to8,
7677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop(Iop_And64, mkexpr(t_bitno1), mkU64(7))) );
7678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* t_bitno2 contains offset of bit within byte */
7680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (op != BtOpNone) {
7682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      t_mask = newTemp(Ity_I8);
7683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( t_mask, binop(Iop_Shl8, mkU8(1), mkexpr(t_bitno2)) );
7684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
7685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* t_mask is now a suitable byte mask */
7687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( t_fetched, loadLE(Ity_I8, mkexpr(t_addr1)) );
7689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (op != BtOpNone) {
7691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (op) {
7692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BtOpSet:
7693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( t_new,
7694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    binop(Iop_Or8, mkexpr(t_fetched), mkexpr(t_mask)) );
7695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
7696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BtOpComp:
7697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( t_new,
7698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    binop(Iop_Xor8, mkexpr(t_fetched), mkexpr(t_mask)) );
7699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
7700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BtOpReset:
7701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( t_new,
7702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    binop(Iop_And8, mkexpr(t_fetched),
7703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    unop(Iop_Not8, mkexpr(t_mask))) );
7704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
7705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
7706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vpanic("dis_bt_G_E(amd64)");
7707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
7708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ((pfx & PFX_LOCK) && !epartIsReg(modrm)) {
7709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         casLE( mkexpr(t_addr1), mkexpr(t_fetched)/*expd*/,
7710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 mkexpr(t_new)/*new*/,
7711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 guest_RIP_curr_instr );
7712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
7713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         storeLE( mkexpr(t_addr1), mkexpr(t_new) );
7714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
7715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
7716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Side effect done; now get selected bit into Carry flag */
7718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Flags: C=selected bit, O,S,Z,A,P undefined, so are set to zero. */
7719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_CC_OP,   mkU64(AMD64G_CC_OP_COPY) ));
7720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_CC_DEP2, mkU64(0) ));
7721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put(
7722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            OFFB_CC_DEP1,
7723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            binop(Iop_And64,
7724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(Iop_Shr64,
7725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        unop(Iop_8Uto64, mkexpr(t_fetched)),
7726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mkexpr(t_bitno2)),
7727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  mkU64(1)))
7728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       );
7729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Set NDEP even though it isn't used.  This makes redundant-PUT
7730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      elimination of previous stores to this field work better. */
7731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_CC_NDEP, mkU64(0) ));
7732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Move reg operand from stack back to reg */
7734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (epartIsReg(modrm)) {
7735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* t_rsp still points at it. */
7736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* only write the reg if actually modifying it; doing otherwise
7737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         zeroes the top half erroneously when doing btl due to
7738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         standard zero-extend rule */
7739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (op != BtOpNone)
7740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegE(sz, pfx, modrm, loadLE(szToITy(sz), mkexpr(t_rsp)) );
7741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIReg64(R_RSP, binop(Iop_Add64, mkexpr(t_rsp), mkU64(288)) );
7742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
7743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DIP("bt%s%c %s, %s\n",
7745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       nameBtOp(op), nameISize(sz), nameIRegG(sz, pfx, modrm),
7746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       ( epartIsReg(modrm) ? nameIRegE(sz, pfx, modrm) : dis_buf ) );
7747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return delta;
7749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Handle BSF/BSR.  Only v-size seems necessary. */
7754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
7755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong dis_bs_E_G ( VexAbiInfo* vbi,
7756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   Prefix pfx, Int sz, Long delta, Bool fwds )
7757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool   isReg;
7759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar  modrm;
7760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar  dis_buf[50];
7761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty    = szToITy(sz);
7763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp src   = newTemp(ty);
7764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp dst   = newTemp(ty);
7765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp src64 = newTemp(Ity_I64);
7766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp dst64 = newTemp(Ity_I64);
7767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp src8  = newTemp(Ity_I8);
7768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(sz == 8 || sz == 4 || sz == 2);
7770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   modrm = getUChar(delta);
7772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   isReg = epartIsReg(modrm);
7773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (isReg) {
7774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delta++;
7775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( src, getIRegE(sz, pfx, modrm) );
7776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
7777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int    len;
7778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp addr = disAMode( &len, vbi, pfx, delta, dis_buf, 0 );
7779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delta += len;
7780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( src, loadLE(ty, mkexpr(addr)) );
7781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
7782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DIP("bs%c%c %s, %s\n",
7784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       fwds ? 'f' : 'r', nameISize(sz),
7785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       ( isReg ? nameIRegE(sz, pfx, modrm) : dis_buf ),
7786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       nameIRegG(sz, pfx, modrm));
7787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* First, widen src to 64 bits if it is not already. */
7789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( src64, widenUto64(mkexpr(src)) );
7790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Generate an 8-bit expression which is zero iff the
7792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      original is zero, and nonzero otherwise */
7793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( src8,
7794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           unop(Iop_1Uto8,
7795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop(Iop_CmpNE64,
7796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      mkexpr(src64), mkU64(0))) );
7797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Flags: Z is 1 iff source value is zero.  All others
7799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      are undefined -- we force them to zero. */
7800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_CC_OP,   mkU64(AMD64G_CC_OP_COPY) ));
7801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_CC_DEP2, mkU64(0) ));
7802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put(
7803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            OFFB_CC_DEP1,
7804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr_Mux0X( mkexpr(src8),
7805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          /* src==0 */
7806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          mkU64(AMD64G_CC_MASK_Z),
7807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          /* src!=0 */
7808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          mkU64(0)
7809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        )
7810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       ));
7811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Set NDEP even though it isn't used.  This makes redundant-PUT
7812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      elimination of previous stores to this field work better. */
7813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_CC_NDEP, mkU64(0) ));
7814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Result: iff source value is zero, we can't use
7816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Iop_Clz64/Iop_Ctz64 as they have no defined result in that case.
7817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      But anyway, amd64 semantics say the result is undefined in
7818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      such situations.  Hence handle the zero case specially. */
7819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Bleh.  What we compute:
7821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          bsf64:  if src == 0 then {dst is unchanged}
7823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              else Ctz64(src)
7824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          bsr64:  if src == 0 then {dst is unchanged}
7826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              else 63 - Clz64(src)
7827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          bsf32:  if src == 0 then {dst is unchanged}
7829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              else Ctz64(32Uto64(src))
7830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          bsr32:  if src == 0 then {dst is unchanged}
7832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              else 63 - Clz64(32Uto64(src))
7833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          bsf16:  if src == 0 then {dst is unchanged}
7835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              else Ctz64(32Uto64(16Uto32(src)))
7836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          bsr16:  if src == 0 then {dst is unchanged}
7838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              else 63 - Clz64(32Uto64(16Uto32(src)))
7839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
7840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* The main computation, guarding against zero. */
7842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( dst64,
7843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           IRExpr_Mux0X(
7844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              mkexpr(src8),
7845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              /* src == 0 -- leave dst unchanged */
7846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              widenUto64( getIRegG( sz, pfx, modrm ) ),
7847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              /* src != 0 */
7848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              fwds ? unop(Iop_Ctz64, mkexpr(src64))
7849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   : binop(Iop_Sub64,
7850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           mkU64(63),
7851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           unop(Iop_Clz64, mkexpr(src64)))
7852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           )
7853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         );
7854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (sz == 2)
7856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( dst, unop(Iop_64to16, mkexpr(dst64)) );
7857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
7858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (sz == 4)
7859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( dst, unop(Iop_64to32, mkexpr(dst64)) );
7860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
7861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( dst, mkexpr(dst64) );
7862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* dump result back */
7864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   putIRegG( sz, pfx, modrm, mkexpr(dst) );
7865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return delta;
7867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* swap rAX with the reg specified by reg and REX.B */
7871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
7872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid codegen_xchg_rAX_Reg ( Prefix pfx, Int sz, UInt regLo3 )
7873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = szToITy(sz);
7875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp t1 = newTemp(ty);
7876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp t2 = newTemp(ty);
7877b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   vassert(sz == 2 || sz == 4 || sz == 8);
7878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(regLo3 < 8);
7879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (sz == 8) {
7880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( t1, getIReg64(R_RAX) );
7881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( t2, getIRegRexB(8, pfx, regLo3) );
7882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIReg64( R_RAX, mkexpr(t2) );
7883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIRegRexB(8, pfx, regLo3, mkexpr(t1) );
7884b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   } else if (sz == 4) {
7885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( t1, getIReg32(R_RAX) );
7886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( t2, getIRegRexB(4, pfx, regLo3) );
7887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIReg32( R_RAX, mkexpr(t2) );
7888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIRegRexB(4, pfx, regLo3, mkexpr(t1) );
7889b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   } else {
7890b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      assign( t1, getIReg16(R_RAX) );
7891b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      assign( t2, getIRegRexB(2, pfx, regLo3) );
7892b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      putIReg16( R_RAX, mkexpr(t2) );
7893b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      putIRegRexB(2, pfx, regLo3, mkexpr(t1) );
7894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
7895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DIP("xchg%c %s, %s\n",
7896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       nameISize(sz), nameIRegRAX(sz),
7897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      nameIRegRexB(sz,pfx, regLo3));
7898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
7902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid codegen_SAHF ( void )
7903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Set the flags to:
7905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (amd64g_calculate_flags_all() & AMD64G_CC_MASK_O)
7906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    -- retain the old O flag
7907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      | (%AH & (AMD64G_CC_MASK_S|AMD64G_CC_MASK_Z|AMD64G_CC_MASK_A
7908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                |AMD64G_CC_MASK_P|AMD64G_CC_MASK_C)
7909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
7910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong  mask_SZACP = AMD64G_CC_MASK_S|AMD64G_CC_MASK_Z|AMD64G_CC_MASK_A
7911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       |AMD64G_CC_MASK_C|AMD64G_CC_MASK_P;
7912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp oldflags   = newTemp(Ity_I64);
7913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( oldflags, mk_amd64g_calculate_rflags_all() );
7914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_CC_OP,   mkU64(AMD64G_CC_OP_COPY) ));
7915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_CC_NDEP, mkU64(0) ));
7916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_CC_DEP2, mkU64(0) ));
7917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_CC_DEP1,
7918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         binop(Iop_Or64,
7919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(Iop_And64, mkexpr(oldflags), mkU64(AMD64G_CC_MASK_O)),
7920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(Iop_And64,
7921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_Shr64, getIReg64(R_RAX), mkU8(8)),
7922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkU64(mask_SZACP))
7923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              )
7924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ));
7925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
7929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid codegen_LAHF ( void  )
7930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* AH <- EFLAGS(SF:ZF:0:AF:0:PF:1:CF) */
7932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* rax_with_hole;
7933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* new_byte;
7934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* new_rax;
7935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong   mask_SZACP = AMD64G_CC_MASK_S|AMD64G_CC_MASK_Z|AMD64G_CC_MASK_A
7936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        |AMD64G_CC_MASK_C|AMD64G_CC_MASK_P;
7937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  flags = newTemp(Ity_I64);
7939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( flags, mk_amd64g_calculate_rflags_all() );
7940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   rax_with_hole
7942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = binop(Iop_And64, getIReg64(R_RAX), mkU64(~0xFF00ULL));
7943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   new_byte
7944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = binop(Iop_Or64, binop(Iop_And64, mkexpr(flags), mkU64(mask_SZACP)),
7945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mkU64(1<<1));
7946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   new_rax
7947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = binop(Iop_Or64, rax_with_hole,
7948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_Shl64, new_byte, mkU8(8)));
7949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   putIReg64(R_RAX, new_rax);
7950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
7954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong dis_cmpxchg_G_E ( /*OUT*/Bool* ok,
7955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        VexAbiInfo*  vbi,
7956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        Prefix       pfx,
7957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        Int          size,
7958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        Long         delta0 )
7959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar dis_buf[50];
7961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int   len;
7962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty    = szToITy(size);
7964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp acc   = newTemp(ty);
7965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp src   = newTemp(ty);
7966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp dest  = newTemp(ty);
7967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp dest2 = newTemp(ty);
7968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp acc2  = newTemp(ty);
7969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp cond8 = newTemp(Ity_I8);
7970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp addr  = IRTemp_INVALID;
7971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar  rm    = getUChar(delta0);
7972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* There are 3 cases to consider:
7974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      reg-reg: ignore any lock prefix, generate sequence based
7976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               on Mux0X
7977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      reg-mem, not locked: ignore any lock prefix, generate sequence
7979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           based on Mux0X
7980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      reg-mem, locked: use IRCAS
7982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
7983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (epartIsReg(rm)) {
7985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* case 1 */
7986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( dest, getIRegE(size, pfx, rm) );
7987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delta0++;
7988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( src, getIRegG(size, pfx, rm) );
7989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( acc, getIRegRAX(size) );
7990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      setFlags_DEP1_DEP2(Iop_Sub8, acc, dest, ty);
7991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( cond8, unop(Iop_1Uto8, mk_amd64g_calculate_condition(AMD64CondZ)) );
7992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( dest2, IRExpr_Mux0X(mkexpr(cond8), mkexpr(dest), mkexpr(src)) );
7993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( acc2,  IRExpr_Mux0X(mkexpr(cond8), mkexpr(dest), mkexpr(acc)) );
7994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIRegRAX(size, mkexpr(acc2));
7995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIRegE(size, pfx, rm, mkexpr(dest2));
7996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("cmpxchg%c %s,%s\n", nameISize(size),
7997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               nameIRegG(size,pfx,rm),
7998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               nameIRegE(size,pfx,rm) );
7999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if (!epartIsReg(rm) && !(pfx & PFX_LOCK)) {
8001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* case 2 */
8002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addr = disAMode ( &len, vbi, pfx, delta0, dis_buf, 0 );
8003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( dest, loadLE(ty, mkexpr(addr)) );
8004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delta0 += len;
8005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( src, getIRegG(size, pfx, rm) );
8006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( acc, getIRegRAX(size) );
8007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      setFlags_DEP1_DEP2(Iop_Sub8, acc, dest, ty);
8008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( cond8, unop(Iop_1Uto8, mk_amd64g_calculate_condition(AMD64CondZ)) );
8009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( dest2, IRExpr_Mux0X(mkexpr(cond8), mkexpr(dest), mkexpr(src)) );
8010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( acc2,  IRExpr_Mux0X(mkexpr(cond8), mkexpr(dest), mkexpr(acc)) );
8011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIRegRAX(size, mkexpr(acc2));
8012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      storeLE( mkexpr(addr), mkexpr(dest2) );
8013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("cmpxchg%c %s,%s\n", nameISize(size),
8014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               nameIRegG(size,pfx,rm), dis_buf);
8015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if (!epartIsReg(rm) && (pfx & PFX_LOCK)) {
8017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* case 3 */
8018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* src is new value.  acc is expected value.  dest is old value.
8019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Compute success from the output of the IRCAS, and steer the
8020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         new value for RAX accordingly: in case of success, RAX is
8021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         unchanged. */
8022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addr = disAMode ( &len, vbi, pfx, delta0, dis_buf, 0 );
8023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delta0 += len;
8024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( src, getIRegG(size, pfx, rm) );
8025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( acc, getIRegRAX(size) );
8026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt( IRStmt_CAS(
8027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mkIRCAS( IRTemp_INVALID, dest, Iend_LE, mkexpr(addr),
8028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  NULL, mkexpr(acc), NULL, mkexpr(src) )
8029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ));
8030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      setFlags_DEP1_DEP2(Iop_Sub8, acc, dest, ty);
8031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( cond8, unop(Iop_1Uto8, mk_amd64g_calculate_condition(AMD64CondZ)) );
8032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( acc2,  IRExpr_Mux0X(mkexpr(cond8), mkexpr(dest), mkexpr(acc)) );
8033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIRegRAX(size, mkexpr(acc2));
8034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("cmpxchg%c %s,%s\n", nameISize(size),
8035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               nameIRegG(size,pfx,rm), dis_buf);
8036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else vassert(0);
8038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *ok = True;
8040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return delta0;
8041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Handle conditional move instructions of the form
8045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cmovcc E(reg-or-mem), G(reg)
8046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   E(src) is reg-or-mem
8048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   G(dst) is reg.
8049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   If E is reg, -->    GET %E, tmps
8051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       GET %G, tmpd
8052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       CMOVcc tmps, tmpd
8053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       PUT tmpd, %G
8054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   If E is mem  -->    (getAddr E) -> tmpa
8056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       LD (tmpa), tmps
8057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       GET %G, tmpd
8058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       CMOVcc tmps, tmpd
8059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       PUT tmpd, %G
8060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
8061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
8062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong dis_cmov_E_G ( VexAbiInfo* vbi,
8063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     Prefix        pfx,
8064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     Int           sz,
8065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     AMD64Condcode cond,
8066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     Long          delta0 )
8067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rm  = getUChar(delta0);
8069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar dis_buf[50];
8070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int   len;
8071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty   = szToITy(sz);
8073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp tmps = newTemp(ty);
8074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp tmpd = newTemp(ty);
8075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (epartIsReg(rm)) {
8077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( tmps, getIRegE(sz, pfx, rm) );
8078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( tmpd, getIRegG(sz, pfx, rm) );
8079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIRegG( sz, pfx, rm,
8081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                IRExpr_Mux0X( unop(Iop_1Uto8,
8082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   mk_amd64g_calculate_condition(cond)),
8083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkexpr(tmpd),
8084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkexpr(tmps) )
8085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              );
8086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("cmov%s %s,%s\n", name_AMD64Condcode(cond),
8087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            nameIRegE(sz,pfx,rm),
8088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            nameIRegG(sz,pfx,rm));
8089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return 1+delta0;
8090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* E refers to memory */
8093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
8094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp addr = disAMode ( &len, vbi, pfx, delta0, dis_buf, 0 );
8095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( tmps, loadLE(ty, mkexpr(addr)) );
8096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( tmpd, getIRegG(sz, pfx, rm) );
8097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIRegG( sz, pfx, rm,
8099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                IRExpr_Mux0X( unop(Iop_1Uto8,
8100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   mk_amd64g_calculate_condition(cond)),
8101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkexpr(tmpd),
8102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkexpr(tmps) )
8103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              );
8104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("cmov%s %s,%s\n", name_AMD64Condcode(cond),
8106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            dis_buf,
8107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            nameIRegG(sz,pfx,rm));
8108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return len+delta0;
8109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
8114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong dis_xadd_G_E ( /*OUT*/Bool* decode_ok,
8115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     VexAbiInfo* vbi,
8116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     Prefix pfx, Int sz, Long delta0 )
8117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int   len;
8119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rm = getUChar(delta0);
8120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar dis_buf[50];
8121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty    = szToITy(sz);
8123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp tmpd  = newTemp(ty);
8124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp tmpt0 = newTemp(ty);
8125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp tmpt1 = newTemp(ty);
8126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* There are 3 cases to consider:
8128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      reg-reg: ignore any lock prefix,
8130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               generate 'naive' (non-atomic) sequence
8131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      reg-mem, not locked: ignore any lock prefix, generate 'naive'
8133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           (non-atomic) sequence
8134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      reg-mem, locked: use IRCAS
8136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
8137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (epartIsReg(rm)) {
8139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* case 1 */
8140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( tmpd, getIRegE(sz, pfx, rm) );
8141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( tmpt0, getIRegG(sz, pfx, rm) );
8142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( tmpt1, binop(mkSizedOp(ty,Iop_Add8),
8143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           mkexpr(tmpd), mkexpr(tmpt0)) );
8144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      setFlags_DEP1_DEP2( Iop_Add8, tmpd, tmpt0, ty );
8145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIRegG(sz, pfx, rm, mkexpr(tmpd));
8146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIRegE(sz, pfx, rm, mkexpr(tmpt1));
8147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("xadd%c %s, %s\n",
8148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          nameISize(sz), nameIRegG(sz,pfx,rm),
8149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          				 nameIRegE(sz,pfx,rm));
8150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *decode_ok = True;
8151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return 1+delta0;
8152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if (!epartIsReg(rm) && !(pfx & PFX_LOCK)) {
8154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* case 2 */
8155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp addr = disAMode ( &len, vbi, pfx, delta0, dis_buf, 0 );
8156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( tmpd,  loadLE(ty, mkexpr(addr)) );
8157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( tmpt0, getIRegG(sz, pfx, rm) );
8158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( tmpt1, binop(mkSizedOp(ty,Iop_Add8),
8159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           mkexpr(tmpd), mkexpr(tmpt0)) );
8160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      setFlags_DEP1_DEP2( Iop_Add8, tmpd, tmpt0, ty );
8161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      storeLE( mkexpr(addr), mkexpr(tmpt1) );
8162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIRegG(sz, pfx, rm, mkexpr(tmpd));
8163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("xadd%c %s, %s\n",
8164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          nameISize(sz), nameIRegG(sz,pfx,rm), dis_buf);
8165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *decode_ok = True;
8166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return len+delta0;
8167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if (!epartIsReg(rm) && (pfx & PFX_LOCK)) {
8169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* case 3 */
8170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp addr = disAMode ( &len, vbi, pfx, delta0, dis_buf, 0 );
8171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( tmpd,  loadLE(ty, mkexpr(addr)) );
8172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( tmpt0, getIRegG(sz, pfx, rm) );
8173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( tmpt1, binop(mkSizedOp(ty,Iop_Add8),
8174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           mkexpr(tmpd), mkexpr(tmpt0)) );
8175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      casLE( mkexpr(addr), mkexpr(tmpd)/*expVal*/,
8176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           mkexpr(tmpt1)/*newVal*/, guest_RIP_curr_instr );
8177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      setFlags_DEP1_DEP2( Iop_Add8, tmpd, tmpt0, ty );
8178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIRegG(sz, pfx, rm, mkexpr(tmpd));
8179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("xadd%c %s, %s\n",
8180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          nameISize(sz), nameIRegG(sz,pfx,rm), dis_buf);
8181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *decode_ok = True;
8182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return len+delta0;
8183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /*UNREACHED*/
8185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(0);
8186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//.. /* Move 16 bits from Ew (ireg or mem) to G (a segment register). */
8189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..
8190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//.. static
8191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//.. UInt dis_mov_Ew_Sw ( UChar sorb, Long delta0 )
8192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//.. {
8193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..    Int    len;
8194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..    IRTemp addr;
8195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..    UChar  rm  = getUChar(delta0);
8196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..    HChar  dis_buf[50];
8197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..
8198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..    if (epartIsReg(rm)) {
8199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..       putSReg( gregOfRM(rm), getIReg(2, eregOfRM(rm)) );
8200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..       DIP("movw %s,%s\n", nameIReg(2,eregOfRM(rm)), nameSReg(gregOfRM(rm)));
8201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..       return 1+delta0;
8202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..    } else {
8203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..       addr = disAMode ( &len, sorb, delta0, dis_buf );
8204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..       putSReg( gregOfRM(rm), loadLE(Ity_I16, mkexpr(addr)) );
8205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..       DIP("movw %s,%s\n", dis_buf, nameSReg(gregOfRM(rm)));
8206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..       return len+delta0;
8207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..    }
8208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//.. }
8209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..
8210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//.. /* Move 16 bits from G (a segment register) to Ew (ireg or mem).  If
8211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..    dst is ireg and sz==4, zero out top half of it.  */
8212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..
8213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//.. static
8214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//.. UInt dis_mov_Sw_Ew ( UChar sorb,
8215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..                      Int   sz,
8216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..                      UInt  delta0 )
8217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//.. {
8218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..    Int    len;
8219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..    IRTemp addr;
8220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..    UChar  rm  = getUChar(delta0);
8221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..    HChar  dis_buf[50];
8222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..
8223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..    vassert(sz == 2 || sz == 4);
8224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..
8225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..    if (epartIsReg(rm)) {
8226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..       if (sz == 4)
8227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..          putIReg(4, eregOfRM(rm), unop(Iop_16Uto32, getSReg(gregOfRM(rm))));
8228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..       else
8229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..          putIReg(2, eregOfRM(rm), getSReg(gregOfRM(rm)));
8230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..
8231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..       DIP("mov %s,%s\n", nameSReg(gregOfRM(rm)), nameIReg(sz,eregOfRM(rm)));
8232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..       return 1+delta0;
8233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..    } else {
8234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..       addr = disAMode ( &len, sorb, delta0, dis_buf );
8235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..       storeLE( mkexpr(addr), getSReg(gregOfRM(rm)) );
8236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..       DIP("mov %s,%s\n", nameSReg(gregOfRM(rm)), dis_buf);
8237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..       return len+delta0;
8238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..    }
8239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//.. }
8240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..
8241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..
8242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//.. static
8243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//.. void dis_push_segreg ( UInt sreg, Int sz )
8244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//.. {
8245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..     IRTemp t1 = newTemp(Ity_I16);
8246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..     IRTemp ta = newTemp(Ity_I32);
8247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..     vassert(sz == 2 || sz == 4);
8248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..
8249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..     assign( t1, getSReg(sreg) );
8250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..     assign( ta, binop(Iop_Sub32, getIReg(4, R_ESP), mkU32(sz)) );
8251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..     putIReg(4, R_ESP, mkexpr(ta));
8252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..     storeLE( mkexpr(ta), mkexpr(t1) );
8253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..
8254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..     DIP("pushw %s\n", nameSReg(sreg));
8255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//.. }
8256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..
8257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//.. static
8258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//.. void dis_pop_segreg ( UInt sreg, Int sz )
8259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//.. {
8260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..     IRTemp t1 = newTemp(Ity_I16);
8261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..     IRTemp ta = newTemp(Ity_I32);
8262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..     vassert(sz == 2 || sz == 4);
8263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..
8264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..     assign( ta, getIReg(4, R_ESP) );
8265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..     assign( t1, loadLE(Ity_I16, mkexpr(ta)) );
8266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..
8267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..     putIReg(4, R_ESP, binop(Iop_Add32, mkexpr(ta), mkU32(sz)) );
8268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..     putSReg( sreg, mkexpr(t1) );
8269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..     DIP("pop %s\n", nameSReg(sreg));
8270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//.. }
8271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
8273663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengvoid dis_ret ( /*MOD*/DisResult* dres, VexAbiInfo* vbi, ULong d64 )
8274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp t1 = newTemp(Ity_I64);
8276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp t2 = newTemp(Ity_I64);
8277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp t3 = newTemp(Ity_I64);
8278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(t1, getIReg64(R_RSP));
8279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(t2, loadLE(Ity_I64,mkexpr(t1)));
8280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(t3, binop(Iop_Add64, mkexpr(t1), mkU64(8+d64)));
8281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   putIReg64(R_RSP, mkexpr(t3));
8282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   make_redzone_AbiHint(vbi, t3, t2/*nia*/, "ret");
8283663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   jmp_treg(dres, Ijk_Ret, t2);
8284663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(dres->whatNext == Dis_StopHere);
8285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
8289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- SSE/SSE2/SSE3 helpers                                ---*/
8290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
8291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Worker function; do not call directly.
8293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Handles full width G = G `op` E   and   G = (not G) `op` E.
8294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
8295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong dis_SSE_E_to_G_all_wrk (
8297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                VexAbiInfo* vbi,
8298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                Prefix pfx, Long delta,
8299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                HChar* opname, IROp op,
8300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                Bool   invertG
8301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             )
8302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar   dis_buf[50];
8304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     alen;
8305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  addr;
8306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar   rm = getUChar(delta);
8307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* gpart
8308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = invertG ? unop(Iop_NotV128, getXMMReg(gregOfRexRM(pfx,rm)))
8309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : getXMMReg(gregOfRexRM(pfx,rm));
8310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (epartIsReg(rm)) {
8311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putXMMReg( gregOfRexRM(pfx,rm),
8312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(op, gpart,
8313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           getXMMReg(eregOfRexRM(pfx,rm))) );
8314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("%s %s,%s\n", opname,
8315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        nameXMMReg(eregOfRexRM(pfx,rm)),
8316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        nameXMMReg(gregOfRexRM(pfx,rm)) );
8317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return delta+1;
8318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
8319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
8320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putXMMReg( gregOfRexRM(pfx,rm),
8321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(op, gpart,
8322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           loadLE(Ity_V128, mkexpr(addr))) );
8323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("%s %s,%s\n", opname,
8324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        dis_buf,
8325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        nameXMMReg(gregOfRexRM(pfx,rm)) );
8326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return delta+alen;
8327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* All lanes SSE binary operation, G = G `op` E. */
8332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
8334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong dis_SSE_E_to_G_all ( VexAbiInfo* vbi,
8335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           Prefix pfx, Long delta,
8336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           HChar* opname, IROp op )
8337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return dis_SSE_E_to_G_all_wrk( vbi, pfx, delta, opname, op, False );
8339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* All lanes SSE binary operation, G = (not G) `op` E. */
8342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
8344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong dis_SSE_E_to_G_all_invG ( VexAbiInfo* vbi,
8345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                Prefix pfx, Long delta,
8346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                HChar* opname, IROp op )
8347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return dis_SSE_E_to_G_all_wrk( vbi, pfx, delta, opname, op, True );
8349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Lowest 32-bit lane only SSE binary operation, G = G `op` E. */
8353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong dis_SSE_E_to_G_lo32 ( VexAbiInfo* vbi,
8355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   Prefix pfx, Long delta,
8356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   HChar* opname, IROp op )
8357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar   dis_buf[50];
8359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     alen;
8360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  addr;
8361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar   rm = getUChar(delta);
8362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* gpart = getXMMReg(gregOfRexRM(pfx,rm));
8363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (epartIsReg(rm)) {
8364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putXMMReg( gregOfRexRM(pfx,rm),
8365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(op, gpart,
8366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           getXMMReg(eregOfRexRM(pfx,rm))) );
8367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("%s %s,%s\n", opname,
8368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        nameXMMReg(eregOfRexRM(pfx,rm)),
8369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        nameXMMReg(gregOfRexRM(pfx,rm)) );
8370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return delta+1;
8371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
8372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* We can only do a 32-bit memory read, so the upper 3/4 of the
8373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         E operand needs to be made simply of zeroes. */
8374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp epart = newTemp(Ity_V128);
8375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
8376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( epart, unop( Iop_32UtoV128,
8377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           loadLE(Ity_I32, mkexpr(addr))) );
8378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putXMMReg( gregOfRexRM(pfx,rm),
8379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(op, gpart, mkexpr(epart)) );
8380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("%s %s,%s\n", opname,
8381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        dis_buf,
8382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        nameXMMReg(gregOfRexRM(pfx,rm)) );
8383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return delta+alen;
8384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Lower 64-bit lane only SSE binary operation, G = G `op` E. */
8389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong dis_SSE_E_to_G_lo64 ( VexAbiInfo* vbi,
8391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   Prefix pfx, Long delta,
8392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   HChar* opname, IROp op )
8393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar   dis_buf[50];
8395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     alen;
8396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  addr;
8397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar   rm = getUChar(delta);
8398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* gpart = getXMMReg(gregOfRexRM(pfx,rm));
8399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (epartIsReg(rm)) {
8400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putXMMReg( gregOfRexRM(pfx,rm),
8401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(op, gpart,
8402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           getXMMReg(eregOfRexRM(pfx,rm))) );
8403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("%s %s,%s\n", opname,
8404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        nameXMMReg(eregOfRexRM(pfx,rm)),
8405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        nameXMMReg(gregOfRexRM(pfx,rm)) );
8406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return delta+1;
8407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
8408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* We can only do a 64-bit memory read, so the upper half of the
8409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         E operand needs to be made simply of zeroes. */
8410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp epart = newTemp(Ity_V128);
8411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
8412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( epart, unop( Iop_64UtoV128,
8413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           loadLE(Ity_I64, mkexpr(addr))) );
8414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putXMMReg( gregOfRexRM(pfx,rm),
8415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(op, gpart, mkexpr(epart)) );
8416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("%s %s,%s\n", opname,
8417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        dis_buf,
8418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        nameXMMReg(gregOfRexRM(pfx,rm)) );
8419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return delta+alen;
8420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* All lanes unary SSE operation, G = op(E). */
8425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong dis_SSE_E_to_G_unary_all (
8427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                VexAbiInfo* vbi,
8428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                Prefix pfx, Long delta,
8429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                HChar* opname, IROp op
8430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             )
8431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar   dis_buf[50];
8433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     alen;
8434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  addr;
8435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar   rm = getUChar(delta);
8436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (epartIsReg(rm)) {
8437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putXMMReg( gregOfRexRM(pfx,rm),
8438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 unop(op, getXMMReg(eregOfRexRM(pfx,rm))) );
8439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("%s %s,%s\n", opname,
8440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        nameXMMReg(eregOfRexRM(pfx,rm)),
8441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        nameXMMReg(gregOfRexRM(pfx,rm)) );
8442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return delta+1;
8443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
8444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
8445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putXMMReg( gregOfRexRM(pfx,rm),
8446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 unop(op, loadLE(Ity_V128, mkexpr(addr))) );
8447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("%s %s,%s\n", opname,
8448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        dis_buf,
8449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        nameXMMReg(gregOfRexRM(pfx,rm)) );
8450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return delta+alen;
8451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Lowest 32-bit lane only unary SSE operation, G = op(E). */
8456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong dis_SSE_E_to_G_unary_lo32 (
8458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                VexAbiInfo* vbi,
8459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                Prefix pfx, Long delta,
8460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                HChar* opname, IROp op
8461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             )
8462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* First we need to get the old G value and patch the low 32 bits
8464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      of the E operand into it.  Then apply op and write back to G. */
8465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar   dis_buf[50];
8466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     alen;
8467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  addr;
8468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar   rm = getUChar(delta);
8469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  oldG0 = newTemp(Ity_V128);
8470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  oldG1 = newTemp(Ity_V128);
8471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( oldG0, getXMMReg(gregOfRexRM(pfx,rm)) );
8473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (epartIsReg(rm)) {
8475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( oldG1,
8476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              binop( Iop_SetV128lo32,
8477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkexpr(oldG0),
8478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     getXMMRegLane32(eregOfRexRM(pfx,rm), 0)) );
8479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putXMMReg( gregOfRexRM(pfx,rm), unop(op, mkexpr(oldG1)) );
8480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("%s %s,%s\n", opname,
8481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        nameXMMReg(eregOfRexRM(pfx,rm)),
8482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        nameXMMReg(gregOfRexRM(pfx,rm)) );
8483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return delta+1;
8484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
8485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
8486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( oldG1,
8487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              binop( Iop_SetV128lo32,
8488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkexpr(oldG0),
8489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     loadLE(Ity_I32, mkexpr(addr)) ));
8490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putXMMReg( gregOfRexRM(pfx,rm), unop(op, mkexpr(oldG1)) );
8491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("%s %s,%s\n", opname,
8492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        dis_buf,
8493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        nameXMMReg(gregOfRexRM(pfx,rm)) );
8494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return delta+alen;
8495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Lowest 64-bit lane only unary SSE operation, G = op(E). */
8500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong dis_SSE_E_to_G_unary_lo64 (
8502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                VexAbiInfo* vbi,
8503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                Prefix pfx, Long delta,
8504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                HChar* opname, IROp op
8505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             )
8506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* First we need to get the old G value and patch the low 64 bits
8508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      of the E operand into it.  Then apply op and write back to G. */
8509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar   dis_buf[50];
8510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     alen;
8511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  addr;
8512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar   rm = getUChar(delta);
8513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  oldG0 = newTemp(Ity_V128);
8514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  oldG1 = newTemp(Ity_V128);
8515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( oldG0, getXMMReg(gregOfRexRM(pfx,rm)) );
8517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (epartIsReg(rm)) {
8519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( oldG1,
8520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              binop( Iop_SetV128lo64,
8521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkexpr(oldG0),
8522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     getXMMRegLane64(eregOfRexRM(pfx,rm), 0)) );
8523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putXMMReg( gregOfRexRM(pfx,rm), unop(op, mkexpr(oldG1)) );
8524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("%s %s,%s\n", opname,
8525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        nameXMMReg(eregOfRexRM(pfx,rm)),
8526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        nameXMMReg(gregOfRexRM(pfx,rm)) );
8527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return delta+1;
8528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
8529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
8530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( oldG1,
8531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              binop( Iop_SetV128lo64,
8532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkexpr(oldG0),
8533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     loadLE(Ity_I64, mkexpr(addr)) ));
8534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putXMMReg( gregOfRexRM(pfx,rm), unop(op, mkexpr(oldG1)) );
8535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("%s %s,%s\n", opname,
8536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        dis_buf,
8537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        nameXMMReg(gregOfRexRM(pfx,rm)) );
8538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return delta+alen;
8539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* SSE integer binary operation:
8544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      G = G `op` E   (eLeft == False)
8545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      G = E `op` G   (eLeft == True)
8546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
8547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong dis_SSEint_E_to_G(
8548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                VexAbiInfo* vbi,
8549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                Prefix pfx, Long delta,
8550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                HChar* opname, IROp op,
8551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                Bool   eLeft
8552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             )
8553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar   dis_buf[50];
8555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     alen;
8556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  addr;
8557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar   rm = getUChar(delta);
8558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* gpart = getXMMReg(gregOfRexRM(pfx,rm));
8559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* epart = NULL;
8560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (epartIsReg(rm)) {
8561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      epart = getXMMReg(eregOfRexRM(pfx,rm));
8562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("%s %s,%s\n", opname,
8563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        nameXMMReg(eregOfRexRM(pfx,rm)),
8564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        nameXMMReg(gregOfRexRM(pfx,rm)) );
8565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delta += 1;
8566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
8567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addr  = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
8568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      epart = loadLE(Ity_V128, mkexpr(addr));
8569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("%s %s,%s\n", opname,
8570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        dis_buf,
8571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        nameXMMReg(gregOfRexRM(pfx,rm)) );
8572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delta += alen;
8573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   putXMMReg( gregOfRexRM(pfx,rm),
8575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              eLeft ? binop(op, epart, gpart)
8576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	            : binop(op, gpart, epart) );
8577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return delta;
8578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8581663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Helper for doing SSE FP comparisons.  False return ==> unhandled.
8582663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   This is all a bit of a kludge in that it ignores the subtleties of
8583663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   ordered-vs-unordered and signalling-vs-nonsignalling in the Intel
8584663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   spec. */
8585663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Bool findSSECmpOp ( /*OUT*/Bool* preSwapP,
8586663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           /*OUT*/IROp* opP,
8587663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           /*OUT*/Bool* postNotP,
8588663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           UInt imm8, Bool all_lanes, Int sz )
8589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8590663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (imm8 >= 32) return False;
8591663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
8592663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* First, compute a (preSwap, op, postNot) triple from
8593663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      the supplied imm8. */
8594663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Bool pre = False;
8595663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IROp op  = Iop_INVALID;
8596663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Bool not = False;
8597663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
8598663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  define XXX(_pre, _op, _not) { pre = _pre; op = _op; not = _not; }
8599663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // If you add a case here, add a corresponding test for both VCMPSD_128
8600663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // and VCMPSS_128 in avx-1.c.
8601663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (imm8) {
8602663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      // "O" = ordered, "U" = unordered
8603663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      // "Q" = non-signalling (quiet), "S" = signalling
8604663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //
8605663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //             swap operands?
8606663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //             |
8607663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //             |      cmp op          invert after?
8608663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //             |      |               |
8609663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //             v      v               v
8610663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x0:  XXX(False, Iop_CmpEQ32Fx4, False); break; // EQ_OQ
8611663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x1:  XXX(False, Iop_CmpLT32Fx4, False); break; // LT_OS
8612663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x2:  XXX(False, Iop_CmpLE32Fx4, False); break; // LE_OS
8613663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x3:  XXX(False, Iop_CmpUN32Fx4, False); break; // UNORD_Q
8614663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x4:  XXX(False, Iop_CmpEQ32Fx4, True);  break; // NEQ_UQ
8615663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x5:  XXX(False, Iop_CmpLT32Fx4, True);  break; // NLT_US
8616663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x6:  XXX(False, Iop_CmpLE32Fx4, True);  break; // NLE_US
8617663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x7:  XXX(False, Iop_CmpUN32Fx4, True);  break; // ORD_Q
8618663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      // 0x8  EQ_UQ
8619663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x9:  XXX(True,  Iop_CmpLE32Fx4, True);  break; // NGE_US
8620663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* "Enhanced Comparison Predicate[s] for VEX-Encoded [insns] */
8621663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0xA:  XXX(True,  Iop_CmpLT32Fx4, True);  break; // NGT_US
8622663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      // 0xB  FALSE_OQ
8623663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      // 0xC: this isn't really right because it returns all-1s when
8624663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      // either operand is a NaN, and it should return all-0s.
8625663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0xC:  XXX(False, Iop_CmpEQ32Fx4, True);  break; // NEQ_OQ
8626663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0xD:  XXX(True,  Iop_CmpLE32Fx4, False); break; // GE_OS
8627663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0xE:  XXX(True,  Iop_CmpLT32Fx4, False); break; // GT_OS
8628663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      // 0xF  TRUE_UQ
8629663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      // 0x10  EQ_OS
8630663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x11: XXX(False, Iop_CmpLT32Fx4, False); break; // LT_OQ
8631663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x12: XXX(False, Iop_CmpLE32Fx4, False); break; // LE_OQ
8632663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      // 0x13  UNORD_S
8633663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      // 0x14  NEQ_US
8634663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      // 0x15  NLT_UQ
8635663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x16: XXX(False, Iop_CmpLE32Fx4, True);  break; // NLE_UQ
8636663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      // 0x17  ORD_S
8637663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      // 0x18  EQ_US
8638663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      // 0x19  NGE_UQ
8639663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      // 0x1A  NGT_UQ
8640663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      // 0x1B  FALSE_OS
8641663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      // 0x1C  NEQ_OS
8642663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      // 0x1D  GE_OQ
8643663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x1E: XXX(True,  Iop_CmpLT32Fx4, False); break; // GT_OQ
8644663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      // 0x1F  TRUE_US
8645663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Don't forget to add test cases to VCMPSS_128_<imm8> in
8646663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         avx-1.c if new cases turn up. */
8647663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default: break;
8648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8649663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  undef XXX
8650663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (op == Iop_INVALID) return False;
8651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8652663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Now convert the op into one with the same arithmetic but that is
8653663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      correct for the width and laneage requirements. */
8654663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
8655663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /**/ if (sz == 4 && all_lanes) {
8656663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (op) {
8657663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_CmpEQ32Fx4: op = Iop_CmpEQ32Fx4; break;
8658663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_CmpLT32Fx4: op = Iop_CmpLT32Fx4; break;
8659663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_CmpLE32Fx4: op = Iop_CmpLE32Fx4; break;
8660663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_CmpUN32Fx4: op = Iop_CmpUN32Fx4; break;
8661663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         default: vassert(0);
8662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
8663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8664663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   else if (sz == 4 && !all_lanes) {
8665663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (op) {
8666663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_CmpEQ32Fx4: op = Iop_CmpEQ32F0x4; break;
8667663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_CmpLT32Fx4: op = Iop_CmpLT32F0x4; break;
8668663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_CmpLE32Fx4: op = Iop_CmpLE32F0x4; break;
8669663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_CmpUN32Fx4: op = Iop_CmpUN32F0x4; break;
8670663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         default: vassert(0);
8671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
8672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8673663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   else if (sz == 8 && all_lanes) {
8674663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (op) {
8675663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_CmpEQ32Fx4: op = Iop_CmpEQ64Fx2; break;
8676663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_CmpLT32Fx4: op = Iop_CmpLT64Fx2; break;
8677663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_CmpLE32Fx4: op = Iop_CmpLE64Fx2; break;
8678663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_CmpUN32Fx4: op = Iop_CmpUN64Fx2; break;
8679663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         default: vassert(0);
8680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
8681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8682663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   else if (sz == 8 && !all_lanes) {
8683663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (op) {
8684663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_CmpEQ32Fx4: op = Iop_CmpEQ64F0x2; break;
8685663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_CmpLT32Fx4: op = Iop_CmpLT64F0x2; break;
8686663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_CmpLE32Fx4: op = Iop_CmpLE64F0x2; break;
8687663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_CmpUN32Fx4: op = Iop_CmpUN64F0x2; break;
8688663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         default: vassert(0);
8689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
8690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8691663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   else {
8692663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vpanic("findSSECmpOp(amd64,guest)");
8693663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
8694663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
8695663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *preSwapP = pre; *opP = op; *postNotP = not;
8696663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return True;
8697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8700663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Handles SSE 32F/64F comparisons.  It can fail, in which case it
8701663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   returns the original delta to indicate failure. */
8702663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
8703663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_SSE_cmp_E_to_G ( VexAbiInfo* vbi,
8704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 Prefix pfx, Long delta,
8705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 HChar* opname, Bool all_lanes, Int sz )
8706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8707663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Long    delta0 = delta;
8708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar   dis_buf[50];
8709663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int     alen;
8710663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt    imm8;
8711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  addr;
8712663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Bool    preSwap = False;
8713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IROp    op      = Iop_INVALID;
8714663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Bool    postNot = False;
8715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  plain   = newTemp(Ity_V128);
8716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar   rm      = getUChar(delta);
8717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UShort  mask    = 0;
8718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(sz == 4 || sz == 8);
8719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (epartIsReg(rm)) {
8720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      imm8 = getUChar(delta+1);
8721663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (imm8 >= 8) return delta0; /* FAIL */
8722663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Bool ok = findSSECmpOp(&preSwap, &op, &postNot, imm8, all_lanes, sz);
8723663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (!ok) return delta0; /* FAIL */
8724663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(!preSwap); /* never needed for imm8 < 8 */
8725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( plain, binop(op, getXMMReg(gregOfRexRM(pfx,rm)),
8726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               getXMMReg(eregOfRexRM(pfx,rm))) );
8727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delta += 2;
8728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("%s $%d,%s,%s\n", opname,
8729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            (Int)imm8,
8730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            nameXMMReg(eregOfRexRM(pfx,rm)),
8731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            nameXMMReg(gregOfRexRM(pfx,rm)) );
8732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
8733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 1 );
8734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      imm8 = getUChar(delta+alen);
8735663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (imm8 >= 8) return delta0; /* FAIL */
8736663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Bool ok = findSSECmpOp(&preSwap, &op, &postNot, imm8, all_lanes, sz);
8737663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (!ok) return delta0; /* FAIL */
8738663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(!preSwap); /* never needed for imm8 < 8 */
8739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( plain,
8740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              binop(
8741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 op,
8742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 getXMMReg(gregOfRexRM(pfx,rm)),
8743663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   all_lanes
8744663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      ? loadLE(Ity_V128, mkexpr(addr))
8745663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   : sz == 8
8746663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      ? unop( Iop_64UtoV128, loadLE(Ity_I64, mkexpr(addr)))
8747663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   : /*sz==4*/
8748663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      unop( Iop_32UtoV128, loadLE(Ity_I32, mkexpr(addr)))
8749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	      )
8750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      );
8751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delta += alen+1;
8752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("%s $%d,%s,%s\n", opname,
8753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            (Int)imm8,
8754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            dis_buf,
8755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            nameXMMReg(gregOfRexRM(pfx,rm)) );
8756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8758663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (postNot && all_lanes) {
8759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putXMMReg( gregOfRexRM(pfx,rm),
8760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 unop(Iop_NotV128, mkexpr(plain)) );
8761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
8763663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (postNot && !all_lanes) {
8764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      mask = toUShort(sz==4 ? 0x000F : 0x00FF);
8765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putXMMReg( gregOfRexRM(pfx,rm),
8766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(Iop_XorV128, mkexpr(plain), mkV128(mask)) );
8767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else {
8769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putXMMReg( gregOfRexRM(pfx,rm), mkexpr(plain) );
8770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return delta;
8773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Vector by scalar shift of G by the amount specified at the bottom
8777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   of E. */
8778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong dis_SSE_shiftG_byE ( VexAbiInfo* vbi,
8780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  Prefix pfx, Long delta,
8781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  HChar* opname, IROp op )
8782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar   dis_buf[50];
8784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     alen, size;
8785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  addr;
8786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool    shl, shr, sar;
8787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar   rm   = getUChar(delta);
8788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  g0   = newTemp(Ity_V128);
8789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  g1   = newTemp(Ity_V128);
8790663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp  amt  = newTemp(Ity_I64);
8791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  amt8 = newTemp(Ity_I8);
8792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (epartIsReg(rm)) {
8793663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( amt, getXMMRegLane64(eregOfRexRM(pfx,rm), 0) );
8794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("%s %s,%s\n", opname,
8795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        nameXMMReg(eregOfRexRM(pfx,rm)),
8796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        nameXMMReg(gregOfRexRM(pfx,rm)) );
8797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delta++;
8798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
8799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
8800663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( amt, loadLE(Ity_I64, mkexpr(addr)) );
8801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("%s %s,%s\n", opname,
8802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        dis_buf,
8803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        nameXMMReg(gregOfRexRM(pfx,rm)) );
8804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delta += alen;
8805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( g0,   getXMMReg(gregOfRexRM(pfx,rm)) );
8807663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( amt8, unop(Iop_64to8, mkexpr(amt)) );
8808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   shl = shr = sar = False;
8810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   size = 0;
8811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op) {
8812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShlN16x8: shl = True; size = 32; break;
8813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShlN32x4: shl = True; size = 32; break;
8814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShlN64x2: shl = True; size = 64; break;
8815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SarN16x8: sar = True; size = 16; break;
8816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SarN32x4: sar = True; size = 32; break;
8817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShrN16x8: shr = True; size = 16; break;
8818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShrN32x4: shr = True; size = 32; break;
8819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShrN64x2: shr = True; size = 64; break;
8820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vassert(0);
8821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (shl || shr) {
8824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     assign(
8825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        g1,
8826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRExpr_Mux0X(
8827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           unop(Iop_1Uto8,
8828663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                binop(Iop_CmpLT64U, mkexpr(amt), mkU64(size))),
8829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           mkV128(0x0000),
8830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           binop(op, mkexpr(g0), mkexpr(amt8))
8831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        )
8832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     );
8833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else
8834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (sar) {
8835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     assign(
8836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        g1,
8837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRExpr_Mux0X(
8838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           unop(Iop_1Uto8,
8839663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                binop(Iop_CmpLT64U, mkexpr(amt), mkU64(size))),
8840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           binop(op, mkexpr(g0), mkU8(size-1)),
8841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           binop(op, mkexpr(g0), mkexpr(amt8))
8842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        )
8843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     );
8844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
8845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(0);
8846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   putXMMReg( gregOfRexRM(pfx,rm), mkexpr(g1) );
8849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return delta;
8850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Vector by scalar shift of E by an immediate byte. */
8854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
8856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong dis_SSE_shiftE_imm ( Prefix pfx,
8857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           Long delta, HChar* opname, IROp op )
8858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool    shl, shr, sar;
8860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar   rm   = getUChar(delta);
8861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  e0   = newTemp(Ity_V128);
8862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  e1   = newTemp(Ity_V128);
8863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar   amt, size;
8864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(epartIsReg(rm));
8865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(gregLO3ofRM(rm) == 2
8866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || gregLO3ofRM(rm) == 4 || gregLO3ofRM(rm) == 6);
8867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   amt = getUChar(delta+1);
8868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   delta += 2;
8869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DIP("%s $%d,%s\n", opname,
8870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      (Int)amt,
8871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      nameXMMReg(eregOfRexRM(pfx,rm)) );
8872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( e0, getXMMReg(eregOfRexRM(pfx,rm)) );
8873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   shl = shr = sar = False;
8875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   size = 0;
8876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op) {
8877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShlN16x8: shl = True; size = 16; break;
8878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShlN32x4: shl = True; size = 32; break;
8879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShlN64x2: shl = True; size = 64; break;
8880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SarN16x8: sar = True; size = 16; break;
8881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SarN32x4: sar = True; size = 32; break;
8882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShrN16x8: shr = True; size = 16; break;
8883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShrN32x4: shr = True; size = 32; break;
8884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShrN64x2: shr = True; size = 64; break;
8885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vassert(0);
8886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (shl || shr) {
8889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     assign( e1, amt >= size
8890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ? mkV128(0x0000)
8891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    : binop(op, mkexpr(e0), mkU8(amt))
8892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     );
8893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else
8894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (sar) {
8895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     assign( e1, amt >= size
8896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ? binop(op, mkexpr(e0), mkU8(size-1))
8897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    : binop(op, mkexpr(e0), mkU8(amt))
8898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     );
8899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
8900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(0);
8901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   putXMMReg( eregOfRexRM(pfx,rm), mkexpr(e1) );
8904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return delta;
8905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Get the current SSE rounding mode. */
8909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* /* :: Ity_I32 */ get_sse_roundingmode ( void )
8911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return
8913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      unop( Iop_64to32,
8914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            binop( Iop_And64,
8915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   IRExpr_Get( OFFB_SSEROUND, Ity_I64 ),
8916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   mkU64(3) ));
8917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void put_sse_roundingmode ( IRExpr* sseround )
8920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv, sseround) == Ity_I32);
8922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_SSEROUND,
8923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     unop(Iop_32Uto64,sseround) ) );
8924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8926663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Break a V128-bit value up into four 32-bit ints. */
8927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8928663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void breakupV128to32s ( IRTemp t128,
8929663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               /*OUTs*/
8930663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               IRTemp* t3, IRTemp* t2,
8931663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               IRTemp* t1, IRTemp* t0 )
8932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp hi64 = newTemp(Ity_I64);
8934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp lo64 = newTemp(Ity_I64);
8935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( hi64, unop(Iop_V128HIto64, mkexpr(t128)) );
8936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( lo64, unop(Iop_V128to64,   mkexpr(t128)) );
8937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(t0 && *t0 == IRTemp_INVALID);
8939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(t1 && *t1 == IRTemp_INVALID);
8940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(t2 && *t2 == IRTemp_INVALID);
8941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(t3 && *t3 == IRTemp_INVALID);
8942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *t0 = newTemp(Ity_I32);
8944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *t1 = newTemp(Ity_I32);
8945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *t2 = newTemp(Ity_I32);
8946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *t3 = newTemp(Ity_I32);
8947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( *t0, unop(Iop_64to32,   mkexpr(lo64)) );
8948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( *t1, unop(Iop_64HIto32, mkexpr(lo64)) );
8949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( *t2, unop(Iop_64to32,   mkexpr(hi64)) );
8950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( *t3, unop(Iop_64HIto32, mkexpr(hi64)) );
8951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8953663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Construct a V128-bit value from four 32-bit ints. */
8954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8955663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRExpr* mkV128from32s ( IRTemp t3, IRTemp t2,
8956663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               IRTemp t1, IRTemp t0 )
8957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return
8959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      binop( Iop_64HLtoV128,
8960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             binop(Iop_32HLto64, mkexpr(t3), mkexpr(t2)),
8961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             binop(Iop_32HLto64, mkexpr(t1), mkexpr(t0))
8962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   );
8963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Break a 64-bit value up into four 16-bit ints. */
8966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void breakup64to16s ( IRTemp t64,
8968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             /*OUTs*/
8969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRTemp* t3, IRTemp* t2,
8970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRTemp* t1, IRTemp* t0 )
8971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp hi32 = newTemp(Ity_I32);
8973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp lo32 = newTemp(Ity_I32);
8974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( hi32, unop(Iop_64HIto32, mkexpr(t64)) );
8975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( lo32, unop(Iop_64to32,   mkexpr(t64)) );
8976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(t0 && *t0 == IRTemp_INVALID);
8978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(t1 && *t1 == IRTemp_INVALID);
8979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(t2 && *t2 == IRTemp_INVALID);
8980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(t3 && *t3 == IRTemp_INVALID);
8981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *t0 = newTemp(Ity_I16);
8983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *t1 = newTemp(Ity_I16);
8984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *t2 = newTemp(Ity_I16);
8985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *t3 = newTemp(Ity_I16);
8986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( *t0, unop(Iop_32to16,   mkexpr(lo32)) );
8987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( *t1, unop(Iop_32HIto16, mkexpr(lo32)) );
8988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( *t2, unop(Iop_32to16,   mkexpr(hi32)) );
8989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( *t3, unop(Iop_32HIto16, mkexpr(hi32)) );
8990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Construct a 64-bit value from four 16-bit ints. */
8993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mk64from16s ( IRTemp t3, IRTemp t2,
8995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRTemp t1, IRTemp t0 )
8996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return
8998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      binop( Iop_32HLto64,
8999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             binop(Iop_16HLto32, mkexpr(t3), mkexpr(t2)),
9000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             binop(Iop_16HLto32, mkexpr(t1), mkexpr(t0))
9001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   );
9002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
9003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9004663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Break a V256-bit value up into four 64-bit ints. */
9005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9006663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void breakupV256to64s ( IRTemp t256,
9007663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               /*OUTs*/
9008663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               IRTemp* t3, IRTemp* t2,
9009663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               IRTemp* t1, IRTemp* t0 )
9010663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
9011663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(t0 && *t0 == IRTemp_INVALID);
9012663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(t1 && *t1 == IRTemp_INVALID);
9013663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(t2 && *t2 == IRTemp_INVALID);
9014663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(t3 && *t3 == IRTemp_INVALID);
9015663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *t0 = newTemp(Ity_I64);
9016663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *t1 = newTemp(Ity_I64);
9017663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *t2 = newTemp(Ity_I64);
9018663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *t3 = newTemp(Ity_I64);
9019663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( *t0, unop(Iop_V256to64_0, mkexpr(t256)) );
9020663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( *t1, unop(Iop_V256to64_1, mkexpr(t256)) );
9021663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( *t2, unop(Iop_V256to64_2, mkexpr(t256)) );
9022663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( *t3, unop(Iop_V256to64_3, mkexpr(t256)) );
9023663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
9024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9025663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Break a V256-bit value up into two V128s. */
9026663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
9027663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void breakupV256toV128s ( IRTemp t256,
9028663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                 /*OUTs*/
9029663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                 IRTemp* t1, IRTemp* t0 )
9030663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
9031663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(t0 && *t0 == IRTemp_INVALID);
9032663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(t1 && *t1 == IRTemp_INVALID);
9033663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *t0 = newTemp(Ity_V128);
9034663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *t1 = newTemp(Ity_V128);
9035663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(*t1, unop(Iop_V256toV128_1, mkexpr(t256)));
9036663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(*t0, unop(Iop_V256toV128_0, mkexpr(t256)));
9037663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
9038663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
9039663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Break a V256-bit value up into eight 32-bit ints.  */
9040663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
9041663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void breakupV256to32s ( IRTemp t256,
9042663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               /*OUTs*/
9043663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               IRTemp* t7, IRTemp* t6,
9044663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               IRTemp* t5, IRTemp* t4,
9045663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               IRTemp* t3, IRTemp* t2,
9046663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               IRTemp* t1, IRTemp* t0 )
9047663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
9048663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t128_1 = IRTemp_INVALID;
9049663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t128_0 = IRTemp_INVALID;
9050663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV256toV128s( t256, &t128_1, &t128_0 );
9051663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV128to32s( t128_1, t7, t6, t5, t4 );
9052663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV128to32s( t128_0, t3, t2, t1, t0 );
9053663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
9054663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
9055663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Break a V128-bit value up into two 64-bit ints. */
9056663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
9057663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void breakupV128to64s ( IRTemp t128,
9058663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               /*OUTs*/
9059663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               IRTemp* t1, IRTemp* t0 )
9060663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
9061663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(t0 && *t0 == IRTemp_INVALID);
9062663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(t1 && *t1 == IRTemp_INVALID);
9063663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *t0 = newTemp(Ity_I64);
9064663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *t1 = newTemp(Ity_I64);
9065663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( *t0, unop(Iop_V128to64,   mkexpr(t128)) );
9066663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( *t1, unop(Iop_V128HIto64, mkexpr(t128)) );
9067663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
9068663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
9069663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Construct a V256-bit value from eight 32-bit ints. */
9070663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
9071663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRExpr* mkV256from32s ( IRTemp t7, IRTemp t6,
9072663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               IRTemp t5, IRTemp t4,
9073663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               IRTemp t3, IRTemp t2,
9074663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               IRTemp t1, IRTemp t0 )
9075663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
9076663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return
9077663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      binop( Iop_V128HLtoV256,
9078663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             binop( Iop_64HLtoV128,
9079663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    binop(Iop_32HLto64, mkexpr(t7), mkexpr(t6)),
9080663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    binop(Iop_32HLto64, mkexpr(t5), mkexpr(t4)) ),
9081663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             binop( Iop_64HLtoV128,
9082663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    binop(Iop_32HLto64, mkexpr(t3), mkexpr(t2)),
9083663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    binop(Iop_32HLto64, mkexpr(t1), mkexpr(t0)) )
9084663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   );
9085663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
9086663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
9087663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Construct a V256-bit value from four 64-bit ints. */
9088663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
9089663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRExpr* mkV256from64s ( IRTemp t3, IRTemp t2,
9090663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               IRTemp t1, IRTemp t0 )
9091663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
9092663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return
9093663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      binop( Iop_V128HLtoV256,
9094663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             binop(Iop_64HLtoV128, mkexpr(t3), mkexpr(t2)),
9095663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             binop(Iop_64HLtoV128, mkexpr(t1), mkexpr(t0))
9096663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   );
9097663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
9098663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
9099663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Helper for the SSSE3 (not SSE3) PMULHRSW insns.  Given two 64-bit
9100663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   values (aa,bb), computes, for each of the 4 16-bit lanes:
9101663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
9102663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   (((aa_lane *s32 bb_lane) >>u 14) + 1) >>u 1
9103663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng*/
9104663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRExpr* dis_PMULHRSW_helper ( IRExpr* aax, IRExpr* bbx )
9105663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
9106663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp aa      = newTemp(Ity_I64);
9107663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp bb      = newTemp(Ity_I64);
9108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp aahi32s = newTemp(Ity_I64);
9109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp aalo32s = newTemp(Ity_I64);
9110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp bbhi32s = newTemp(Ity_I64);
9111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp bblo32s = newTemp(Ity_I64);
9112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp rHi     = newTemp(Ity_I64);
9113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp rLo     = newTemp(Ity_I64);
9114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp one32x2 = newTemp(Ity_I64);
9115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(aa, aax);
9116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(bb, bbx);
9117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( aahi32s,
9118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           binop(Iop_SarN32x2,
9119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(Iop_InterleaveHI16x4, mkexpr(aa), mkexpr(aa)),
9120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 mkU8(16) ));
9121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( aalo32s,
9122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           binop(Iop_SarN32x2,
9123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(Iop_InterleaveLO16x4, mkexpr(aa), mkexpr(aa)),
9124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 mkU8(16) ));
9125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( bbhi32s,
9126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           binop(Iop_SarN32x2,
9127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(Iop_InterleaveHI16x4, mkexpr(bb), mkexpr(bb)),
9128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 mkU8(16) ));
9129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( bblo32s,
9130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           binop(Iop_SarN32x2,
9131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(Iop_InterleaveLO16x4, mkexpr(bb), mkexpr(bb)),
9132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 mkU8(16) ));
9133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(one32x2, mkU64( (1ULL << 32) + 1 ));
9134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(
9135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      rHi,
9136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      binop(
9137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Iop_ShrN32x2,
9138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         binop(
9139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Iop_Add32x2,
9140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            binop(
9141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Iop_ShrN32x2,
9142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(Iop_Mul32x2, mkexpr(aahi32s), mkexpr(bbhi32s)),
9143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               mkU8(14)
9144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ),
9145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mkexpr(one32x2)
9146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ),
9147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mkU8(1)
9148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      )
9149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   );
9150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(
9151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      rLo,
9152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      binop(
9153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Iop_ShrN32x2,
9154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         binop(
9155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Iop_Add32x2,
9156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            binop(
9157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Iop_ShrN32x2,
9158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(Iop_Mul32x2, mkexpr(aalo32s), mkexpr(bblo32s)),
9159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               mkU8(14)
9160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ),
9161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mkexpr(one32x2)
9162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ),
9163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mkU8(1)
9164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      )
9165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   );
9166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return
9167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      binop(Iop_CatEvenLanes16x4, mkexpr(rHi), mkexpr(rLo));
9168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
9169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Helper for the SSSE3 (not SSE3) PSIGN{B,W,D} insns.  Given two 64-bit
9171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   values (aa,bb), computes, for each lane:
9172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          if aa_lane < 0 then - bb_lane
9174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     else if aa_lane > 0 then bb_lane
9175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     else 0
9176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
9177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* dis_PSIGN_helper ( IRExpr* aax, IRExpr* bbx, Int laneszB )
9178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
9179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp aa       = newTemp(Ity_I64);
9180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp bb       = newTemp(Ity_I64);
9181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp zero     = newTemp(Ity_I64);
9182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp bbNeg    = newTemp(Ity_I64);
9183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp negMask  = newTemp(Ity_I64);
9184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp posMask  = newTemp(Ity_I64);
9185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IROp   opSub    = Iop_INVALID;
9186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IROp   opCmpGTS = Iop_INVALID;
9187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (laneszB) {
9189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 1: opSub = Iop_Sub8x8;  opCmpGTS = Iop_CmpGT8Sx8;  break;
9190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2: opSub = Iop_Sub16x4; opCmpGTS = Iop_CmpGT16Sx4; break;
9191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 4: opSub = Iop_Sub32x2; opCmpGTS = Iop_CmpGT32Sx2; break;
9192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vassert(0);
9193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
9194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( aa,      aax );
9196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( bb,      bbx );
9197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( zero,    mkU64(0) );
9198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( bbNeg,   binop(opSub,    mkexpr(zero), mkexpr(bb)) );
9199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( negMask, binop(opCmpGTS, mkexpr(zero), mkexpr(aa)) );
9200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( posMask, binop(opCmpGTS, mkexpr(aa),   mkexpr(zero)) );
9201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return
9203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      binop(Iop_Or64,
9204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            binop(Iop_And64, mkexpr(bb),    mkexpr(posMask)),
9205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            binop(Iop_And64, mkexpr(bbNeg), mkexpr(negMask)) );
9206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
9208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9209663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
9210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Helper for the SSSE3 (not SSE3) PABS{B,W,D} insns.  Given a 64-bit
9211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   value aa, computes, for each lane
9212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if aa < 0 then -aa else aa
9214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Note that the result is interpreted as unsigned, so that the
9216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   absolute value of the most negative signed input can be
9217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   represented.
9218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
9219663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRTemp math_PABS_MMX ( IRTemp aa, Int laneszB )
9220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
9221663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp res     = newTemp(Ity_I64);
9222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp zero    = newTemp(Ity_I64);
9223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp aaNeg   = newTemp(Ity_I64);
9224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp negMask = newTemp(Ity_I64);
9225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp posMask = newTemp(Ity_I64);
9226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IROp   opSub   = Iop_INVALID;
9227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IROp   opSarN  = Iop_INVALID;
9228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (laneszB) {
9230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 1: opSub = Iop_Sub8x8;  opSarN = Iop_SarN8x8;  break;
9231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2: opSub = Iop_Sub16x4; opSarN = Iop_SarN16x4; break;
9232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 4: opSub = Iop_Sub32x2; opSarN = Iop_SarN32x2; break;
9233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vassert(0);
9234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
9235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( negMask, binop(opSarN, mkexpr(aa), mkU8(8*laneszB-1)) );
9237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( posMask, unop(Iop_Not64, mkexpr(negMask)) );
9238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( zero,    mkU64(0) );
9239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( aaNeg,   binop(opSub, mkexpr(zero), mkexpr(aa)) );
9240663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( res,
9241663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           binop(Iop_Or64,
9242663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 binop(Iop_And64, mkexpr(aa),    mkexpr(posMask)),
9243663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 binop(Iop_And64, mkexpr(aaNeg), mkexpr(negMask)) ));
9244663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return res;
9245663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
9246663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
9247663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* XMM version of math_PABS_MMX. */
9248663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRTemp math_PABS_XMM ( IRTemp aa, Int laneszB )
9249663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
9250663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp res  = newTemp(Ity_V128);
9251663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp aaHi = newTemp(Ity_I64);
9252663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp aaLo = newTemp(Ity_I64);
9253663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(aaHi, unop(Iop_V128HIto64, mkexpr(aa)));
9254663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(aaLo, unop(Iop_V128to64, mkexpr(aa)));
9255663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(res, binop(Iop_64HLtoV128,
9256663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     mkexpr(math_PABS_MMX(aaHi, laneszB)),
9257663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     mkexpr(math_PABS_MMX(aaLo, laneszB))));
9258663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return res;
9259663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
9260663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
9261663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Specialisations of math_PABS_XMM, since there's no easy way to do
9262663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   partial applications in C :-( */
9263663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRTemp math_PABS_XMM_pap4 ( IRTemp aa ) {
9264663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return math_PABS_XMM(aa, 4);
9265663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
9266663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
9267663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRTemp math_PABS_XMM_pap2 ( IRTemp aa ) {
9268663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return math_PABS_XMM(aa, 2);
9269663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
9270663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
9271663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRTemp math_PABS_XMM_pap1 ( IRTemp aa ) {
9272663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return math_PABS_XMM(aa, 1);
9273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
9274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* dis_PALIGNR_XMM_helper ( IRTemp hi64,
9276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        IRTemp lo64, Long byteShift )
9277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
9278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(byteShift >= 1 && byteShift <= 7);
9279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return
9280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      binop(Iop_Or64,
9281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            binop(Iop_Shl64, mkexpr(hi64), mkU8(8*(8-byteShift))),
9282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            binop(Iop_Shr64, mkexpr(lo64), mkU8(8*byteShift))
9283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      );
9284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
9285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9286663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRTemp math_PALIGNR_XMM ( IRTemp sV, IRTemp dV, UInt imm8 )
9287663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
9288663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp res = newTemp(Ity_V128);
9289663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp sHi = newTemp(Ity_I64);
9290663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp sLo = newTemp(Ity_I64);
9291663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp dHi = newTemp(Ity_I64);
9292663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp dLo = newTemp(Ity_I64);
9293663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp rHi = newTemp(Ity_I64);
9294663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp rLo = newTemp(Ity_I64);
9295663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
9296663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( dHi, unop(Iop_V128HIto64, mkexpr(dV)) );
9297663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( dLo, unop(Iop_V128to64,   mkexpr(dV)) );
9298663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( sHi, unop(Iop_V128HIto64, mkexpr(sV)) );
9299663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( sLo, unop(Iop_V128to64,   mkexpr(sV)) );
9300663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
9301663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (imm8 == 0) {
9302663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( rHi, mkexpr(sHi) );
9303663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( rLo, mkexpr(sLo) );
9304663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
9305663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   else if (imm8 >= 1 && imm8 <= 7) {
9306663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( rHi, dis_PALIGNR_XMM_helper(dLo, sHi, imm8) );
9307663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( rLo, dis_PALIGNR_XMM_helper(sHi, sLo, imm8) );
9308663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
9309663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   else if (imm8 == 8) {
9310663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( rHi, mkexpr(dLo) );
9311663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( rLo, mkexpr(sHi) );
9312663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
9313663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   else if (imm8 >= 9 && imm8 <= 15) {
9314663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( rHi, dis_PALIGNR_XMM_helper(dHi, dLo, imm8-8) );
9315663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( rLo, dis_PALIGNR_XMM_helper(dLo, sHi, imm8-8) );
9316663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
9317663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   else if (imm8 == 16) {
9318663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( rHi, mkexpr(dHi) );
9319663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( rLo, mkexpr(dLo) );
9320663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
9321663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   else if (imm8 >= 17 && imm8 <= 23) {
9322663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( rHi, binop(Iop_Shr64, mkexpr(dHi), mkU8(8*(imm8-16))) );
9323663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( rLo, dis_PALIGNR_XMM_helper(dHi, dLo, imm8-16) );
9324663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
9325663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   else if (imm8 == 24) {
9326663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( rHi, mkU64(0) );
9327663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( rLo, mkexpr(dHi) );
9328663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
9329663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   else if (imm8 >= 25 && imm8 <= 31) {
9330663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( rHi, mkU64(0) );
9331663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( rLo, binop(Iop_Shr64, mkexpr(dHi), mkU8(8*(imm8-24))) );
9332663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
9333663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   else if (imm8 >= 32 && imm8 <= 255) {
9334663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( rHi, mkU64(0) );
9335663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( rLo, mkU64(0) );
9336663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
9337663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   else
9338663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(0);
9339663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
9340663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( res, binop(Iop_64HLtoV128, mkexpr(rHi), mkexpr(rLo)));
9341663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return res;
9342663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
9343663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
9344663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
9345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate a SIGSEGV followed by a restart of the current instruction
9346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if effective_addr is not 16-aligned.  This is required behaviour
9347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for some SSE3 instructions and all 128-bit SSSE3 instructions.
9348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This assumes that guest_RIP_curr_instr is set correctly! */
9349663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic
9350663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengvoid gen_SEGV_if_not_XX_aligned ( IRTemp effective_addr, ULong mask )
9351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
9352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt(
9353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRStmt_Exit(
9354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         binop(Iop_CmpNE64,
9355663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               binop(Iop_And64,mkexpr(effective_addr),mkU64(mask)),
9356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               mkU64(0)),
9357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Ijk_SigSEGV,
9358663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRConst_U64(guest_RIP_curr_instr),
9359663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         OFFB_RIP
9360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      )
9361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   );
9362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
9363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9364663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void gen_SEGV_if_not_16_aligned ( IRTemp effective_addr ) {
9365663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   gen_SEGV_if_not_XX_aligned(effective_addr, 16-1);
9366663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
9367663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
9368663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void gen_SEGV_if_not_32_aligned ( IRTemp effective_addr ) {
9369663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   gen_SEGV_if_not_XX_aligned(effective_addr, 32-1);
9370663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
9371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Helper for deciding whether a given insn (starting at the opcode
9373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   byte) may validly be used with a LOCK prefix.  The following insns
9374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   may be used with LOCK when their destination operand is in memory.
9375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AFAICS this is exactly the same for both 32-bit and 64-bit mode.
9376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ADD        80 /0,  81 /0,  82 /0,  83 /0,  00,  01
9378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OR         80 /1,  81 /1,  82 /x,  83 /1,  08,  09
9379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ADC        80 /2,  81 /2,  82 /2,  83 /2,  10,  11
9380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SBB        81 /3,  81 /3,  82 /x,  83 /3,  18,  19
9381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AND        80 /4,  81 /4,  82 /x,  83 /4,  20,  21
9382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SUB        80 /5,  81 /5,  82 /x,  83 /5,  28,  29
9383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   XOR        80 /6,  81 /6,  82 /x,  83 /6,  30,  31
9384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DEC        FE /1,  FF /1
9386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   INC        FE /0,  FF /0
9387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   NEG        F6 /3,  F7 /3
9389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   NOT        F6 /2,  F7 /2
9390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   XCHG       86, 87
9392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   BTC        0F BB,  0F BA /7
9394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   BTR        0F B3,  0F BA /6
9395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   BTS        0F AB,  0F BA /5
9396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CMPXCHG    0F B0,  0F B1
9398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CMPXCHG8B  0F C7 /1
9399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   XADD       0F C0,  0F C1
9401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ------------------------------
9403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   80 /0  =  addb $imm8,  rm8
9405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   81 /0  =  addl $imm32, rm32  and  addw $imm16, rm16
9406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   82 /0  =  addb $imm8,  rm8
9407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   83 /0  =  addl $simm8, rm32  and  addw $simm8, rm16
9408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   00     =  addb r8,  rm8
9410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   01     =  addl r32, rm32  and  addw r16, rm16
9411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Same for ADD OR ADC SBB AND SUB XOR
9413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   FE /1  = dec rm8
9415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   FF /1  = dec rm32  and  dec rm16
9416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   FE /0  = inc rm8
9418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   FF /0  = inc rm32  and  inc rm16
9419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   F6 /3  = neg rm8
9421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   F7 /3  = neg rm32  and  neg rm16
9422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   F6 /2  = not rm8
9424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   F7 /2  = not rm32  and  not rm16
9425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   0F BB     = btcw r16, rm16    and  btcl r32, rm32
9427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OF BA /7  = btcw $imm8, rm16  and  btcw $imm8, rm32
9428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Same for BTS, BTR
9430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
9431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool can_be_used_with_LOCK_prefix ( UChar* opc )
9432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
9433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (opc[0]) {
9434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x00: case 0x01: case 0x08: case 0x09:
9435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x10: case 0x11: case 0x18: case 0x19:
9436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x20: case 0x21: case 0x28: case 0x29:
9437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x30: case 0x31:
9438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!epartIsReg(opc[1]))
9439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return True;
9440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
9441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x80: case 0x81: case 0x82: case 0x83:
9443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (gregLO3ofRM(opc[1]) >= 0 && gregLO3ofRM(opc[1]) <= 6
9444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && !epartIsReg(opc[1]))
9445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return True;
9446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
9447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xFE: case 0xFF:
9449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (gregLO3ofRM(opc[1]) >= 0 && gregLO3ofRM(opc[1]) <= 1
9450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && !epartIsReg(opc[1]))
9451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return True;
9452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
9453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xF6: case 0xF7:
9455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (gregLO3ofRM(opc[1]) >= 2 && gregLO3ofRM(opc[1]) <= 3
9456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && !epartIsReg(opc[1]))
9457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return True;
9458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
9459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x86: case 0x87:
9461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!epartIsReg(opc[1]))
9462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return True;
9463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
9464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x0F: {
9466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (opc[1]) {
9467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xBB: case 0xB3: case 0xAB:
9468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (!epartIsReg(opc[2]))
9469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  return True;
9470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
9471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xBA:
9472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (gregLO3ofRM(opc[2]) >= 5 && gregLO3ofRM(opc[2]) <= 7
9473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   && !epartIsReg(opc[2]))
9474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  return True;
9475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
9476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xB0: case 0xB1:
9477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (!epartIsReg(opc[2]))
9478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  return True;
9479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
9480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xC7:
9481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (gregLO3ofRM(opc[2]) == 1 && !epartIsReg(opc[2]) )
9482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  return True;
9483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
9484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xC0: case 0xC1:
9485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (!epartIsReg(opc[2]))
9486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  return True;
9487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
9488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
9489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
9490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } /* switch (opc[1]) */
9491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
9492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
9493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
9495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
9496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* switch (opc[0]) */
9497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return False;
9499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
9500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
9503663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---                                                      ---*/
9504663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*--- Top-level SSE/SSE2: dis_ESC_0F__SSE2                 ---*/
9505663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---                                                      ---*/
9506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
9507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9508663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_COMISD ( VexAbiInfo* vbi, Prefix pfx,
9509663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         Long delta, Bool isAvx, UChar opc )
9510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
9511663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(opc == 0x2F/*COMISD*/ || opc == 0x2E/*UCOMISD*/);
9512663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen  = 0;
9513663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
9514663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp argL  = newTemp(Ity_F64);
9515663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp argR  = newTemp(Ity_F64);
9516663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm = getUChar(delta);
9517663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr  = IRTemp_INVALID;
9518663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (epartIsReg(modrm)) {
9519663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( argR, getXMMRegLane64F( eregOfRexRM(pfx,modrm),
9520663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                      0/*lowest lane*/ ) );
9521663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1;
9522663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%s%scomisd %s,%s\n", isAvx ? "v" : "",
9523663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                opc==0x2E ? "u" : "",
9524663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                nameXMMReg(eregOfRexRM(pfx,modrm)),
9525663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                nameXMMReg(gregOfRexRM(pfx,modrm)) );
9526663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
9527663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
9528663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( argR, loadLE(Ity_F64, mkexpr(addr)) );
9529663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen;
9530663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%s%scomisd %s,%s\n", isAvx ? "v" : "",
9531663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                opc==0x2E ? "u" : "",
9532663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                dis_buf,
9533663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                nameXMMReg(gregOfRexRM(pfx,modrm)) );
9534663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
9535663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( argL, getXMMRegLane64F( gregOfRexRM(pfx,modrm),
9536663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   0/*lowest lane*/ ) );
9537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9538663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   stmt( IRStmt_Put( OFFB_CC_OP,   mkU64(AMD64G_CC_OP_COPY) ));
9539663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   stmt( IRStmt_Put( OFFB_CC_DEP2, mkU64(0) ));
9540663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   stmt( IRStmt_Put(
9541663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            OFFB_CC_DEP1,
9542663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            binop( Iop_And64,
9543663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   unop( Iop_32Uto64,
9544663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         binop(Iop_CmpF64, mkexpr(argL), mkexpr(argR)) ),
9545663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   mkU64(0x45)
9546663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       )));
9547663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
9548663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
9549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9551663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_COMISS ( VexAbiInfo* vbi, Prefix pfx,
9552663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         Long delta, Bool isAvx, UChar opc )
9553663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
9554663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(opc == 0x2F/*COMISS*/ || opc == 0x2E/*UCOMISS*/);
9555663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen  = 0;
9556663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
9557663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp argL  = newTemp(Ity_F32);
9558663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp argR  = newTemp(Ity_F32);
9559663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm = getUChar(delta);
9560663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr  = IRTemp_INVALID;
9561663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (epartIsReg(modrm)) {
9562663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( argR, getXMMRegLane32F( eregOfRexRM(pfx,modrm),
9563663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                      0/*lowest lane*/ ) );
9564663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1;
9565663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%s%scomiss %s,%s\n", isAvx ? "v" : "",
9566663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                opc==0x2E ? "u" : "",
9567663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                nameXMMReg(eregOfRexRM(pfx,modrm)),
9568663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                nameXMMReg(gregOfRexRM(pfx,modrm)) );
9569663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
9570663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
9571663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( argR, loadLE(Ity_F32, mkexpr(addr)) );
9572663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen;
9573663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%s%scomiss %s,%s\n", isAvx ? "v" : "",
9574663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                opc==0x2E ? "u" : "",
9575663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                dis_buf,
9576663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                nameXMMReg(gregOfRexRM(pfx,modrm)) );
9577663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
9578663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( argL, getXMMRegLane32F( gregOfRexRM(pfx,modrm),
9579663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   0/*lowest lane*/ ) );
9580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9581663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   stmt( IRStmt_Put( OFFB_CC_OP,   mkU64(AMD64G_CC_OP_COPY) ));
9582663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   stmt( IRStmt_Put( OFFB_CC_DEP2, mkU64(0) ));
9583663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   stmt( IRStmt_Put(
9584663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            OFFB_CC_DEP1,
9585663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            binop( Iop_And64,
9586663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   unop( Iop_32Uto64,
9587663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         binop(Iop_CmpF64,
9588663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               unop(Iop_F32toF64,mkexpr(argL)),
9589663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               unop(Iop_F32toF64,mkexpr(argR)))),
9590663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   mkU64(0x45)
9591663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       )));
9592663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
9593663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
9594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9596663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_PSHUFD_32x4 ( VexAbiInfo* vbi, Prefix pfx,
9597663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              Long delta, Bool writesYmm )
9598663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
9599663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    order;
9600663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen  = 0;
9601663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
9602663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp sV    = newTemp(Ity_V128);
9603663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm = getUChar(delta);
9604663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar* strV  = writesYmm ? "v" : "";
9605663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr  = IRTemp_INVALID;
9606663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (epartIsReg(modrm)) {
9607663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( sV, getXMMReg(eregOfRexRM(pfx,modrm)) );
9608663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      order = (Int)getUChar(delta+1);
9609663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1+1;
9610663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%spshufd $%d,%s,%s\n", strV, order,
9611663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  nameXMMReg(eregOfRexRM(pfx,modrm)),
9612663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  nameXMMReg(gregOfRexRM(pfx,modrm)));
9613663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
9614663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode ( &alen, vbi, pfx, delta, dis_buf,
9615663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        1/*byte after the amode*/ );
9616663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
9617663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      order = (Int)getUChar(delta+alen);
9618663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen+1;
9619663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%spshufd $%d,%s,%s\n", strV, order,
9620663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                 dis_buf,
9621663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                 nameXMMReg(gregOfRexRM(pfx,modrm)));
9622663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
9623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9624663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp s3, s2, s1, s0;
9625663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   s3 = s2 = s1 = s0 = IRTemp_INVALID;
9626663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV128to32s( sV, &s3, &s2, &s1, &s0 );
9627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9628663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  define SEL(n)  ((n)==0 ? s0 : ((n)==1 ? s1 : ((n)==2 ? s2 : s3)))
9629663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp dV = newTemp(Ity_V128);
9630663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(dV,
9631663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          mkV128from32s( SEL((order>>6)&3), SEL((order>>4)&3),
9632663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         SEL((order>>2)&3), SEL((order>>0)&3) )
9633663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   );
9634663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  undef SEL
9635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9636663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   (writesYmm ? putYMMRegLoAndZU : putXMMReg)
9637663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      (gregOfRexRM(pfx,modrm), mkexpr(dV));
9638663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
9639663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
9640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9642663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRTemp math_PSRLDQ ( IRTemp sV, Int imm )
9643663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
9644663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp dV    = newTemp(Ity_V128);
9645663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp hi64  = newTemp(Ity_I64);
9646663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp lo64  = newTemp(Ity_I64);
9647663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp hi64r = newTemp(Ity_I64);
9648663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp lo64r = newTemp(Ity_I64);
9649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9650663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(imm >= 0 && imm <= 255);
9651663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (imm >= 16) {
9652663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(dV, mkV128(0x0000));
9653663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return dV;
9654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
9655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9656663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( hi64, unop(Iop_V128HIto64, mkexpr(sV)) );
9657663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( lo64, unop(Iop_V128to64, mkexpr(sV)) );
9658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9659663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (imm == 0) {
9660663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( lo64r, mkexpr(lo64) );
9661663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( hi64r, mkexpr(hi64) );
9662663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
9663663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   else
9664663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (imm == 8) {
9665663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( hi64r, mkU64(0) );
9666663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( lo64r, mkexpr(hi64) );
9667663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
9668663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   else
9669663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (imm > 8) {
9670663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( hi64r, mkU64(0) );
9671663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( lo64r, binop( Iop_Shr64, mkexpr(hi64), mkU8( 8*(imm-8) ) ));
9672663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
9673663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( hi64r, binop( Iop_Shr64, mkexpr(hi64), mkU8(8 * imm) ));
9674663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( lo64r,
9675663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              binop( Iop_Or64,
9676663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     binop(Iop_Shr64, mkexpr(lo64),
9677663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           mkU8(8 * imm)),
9678663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     binop(Iop_Shl64, mkexpr(hi64),
9679663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           mkU8(8 * (8 - imm)) )
9680663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     )
9681663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              );
9682663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
9683663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
9684663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( dV, binop(Iop_64HLtoV128, mkexpr(hi64r), mkexpr(lo64r)) );
9685663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return dV;
9686663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
9687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9689663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRTemp math_PSLLDQ ( IRTemp sV, Int imm )
9690663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
9691663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp       dV    = newTemp(Ity_V128);
9692663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp       hi64  = newTemp(Ity_I64);
9693663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp       lo64  = newTemp(Ity_I64);
9694663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp       hi64r = newTemp(Ity_I64);
9695663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp       lo64r = newTemp(Ity_I64);
9696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9697663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(imm >= 0 && imm <= 255);
9698663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (imm >= 16) {
9699663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(dV, mkV128(0x0000));
9700663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return dV;
9701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
9702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9703663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( hi64, unop(Iop_V128HIto64, mkexpr(sV)) );
9704663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( lo64, unop(Iop_V128to64, mkexpr(sV)) );
9705663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
9706663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (imm == 0) {
9707663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( lo64r, mkexpr(lo64) );
9708663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( hi64r, mkexpr(hi64) );
9709663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
9710663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   else
9711663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (imm == 8) {
9712663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( lo64r, mkU64(0) );
9713663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( hi64r, mkexpr(lo64) );
9714663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
9715663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   else
9716663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (imm > 8) {
9717663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( lo64r, mkU64(0) );
9718663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( hi64r, binop( Iop_Shl64, mkexpr(lo64), mkU8( 8*(imm-8) ) ));
9719663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
9720663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( lo64r, binop( Iop_Shl64, mkexpr(lo64), mkU8(8 * imm) ));
9721663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( hi64r,
9722663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              binop( Iop_Or64,
9723663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     binop(Iop_Shl64, mkexpr(hi64),
9724663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           mkU8(8 * imm)),
9725663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     binop(Iop_Shr64, mkexpr(lo64),
9726663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           mkU8(8 * (8 - imm)) )
9727663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     )
9728663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              );
9729663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
9730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9731663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( dV, binop(Iop_64HLtoV128, mkexpr(hi64r), mkexpr(lo64r)) );
9732663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return dV;
9733663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
9734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9736663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_CVTxSD2SI ( VexAbiInfo* vbi, Prefix pfx,
9737663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            Long delta, Bool isAvx, UChar opc, Int sz )
9738663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
9739663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(opc == 0x2D/*CVTSD2SI*/ || opc == 0x2C/*CVTTSD2SI*/);
9740663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
9741663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen   = 0;
9742663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm  = getUChar(delta);
9743663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr   = IRTemp_INVALID;
9744663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp rmode  = newTemp(Ity_I32);
9745663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp f64lo  = newTemp(Ity_F64);
9746663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Bool   r2zero = toBool(opc == 0x2C);
9747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9748663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (epartIsReg(modrm)) {
9749663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1;
9750663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(f64lo, getXMMRegLane64F(eregOfRexRM(pfx,modrm), 0));
9751663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%scvt%ssd2si %s,%s\n", isAvx ? "v" : "", r2zero ? "t" : "",
9752663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  nameXMMReg(eregOfRexRM(pfx,modrm)),
9753663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  nameIReg(sz, gregOfRexRM(pfx,modrm),
9754663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                           False));
9755663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
9756663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
9757663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(f64lo, loadLE(Ity_F64, mkexpr(addr)));
9758663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen;
9759663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%scvt%ssd2si %s,%s\n", isAvx ? "v" : "", r2zero ? "t" : "",
9760663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  dis_buf,
9761663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  nameIReg(sz, gregOfRexRM(pfx,modrm),
9762663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                           False));
9763663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
9764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9765663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (r2zero) {
9766663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( rmode, mkU32((UInt)Irrm_ZERO) );
9767663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
9768663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( rmode, get_sse_roundingmode() );
9769663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
9770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9771663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (sz == 4) {
9772663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      putIReg32( gregOfRexRM(pfx,modrm),
9773663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 binop( Iop_F64toI32S, mkexpr(rmode), mkexpr(f64lo)) );
9774663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
9775663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(sz == 8);
9776663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      putIReg64( gregOfRexRM(pfx,modrm),
9777663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 binop( Iop_F64toI64S, mkexpr(rmode), mkexpr(f64lo)) );
9778663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
9779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9780663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
9781663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
9782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9784663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_CVTxSS2SI ( VexAbiInfo* vbi, Prefix pfx,
9785663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            Long delta, Bool isAvx, UChar opc, Int sz )
9786663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
9787663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(opc == 0x2D/*CVTSS2SI*/ || opc == 0x2C/*CVTTSS2SI*/);
9788663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
9789663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen   = 0;
9790663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm  = getUChar(delta);
9791663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr   = IRTemp_INVALID;
9792663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp rmode  = newTemp(Ity_I32);
9793663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp f32lo  = newTemp(Ity_F32);
9794663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Bool   r2zero = toBool(opc == 0x2C);
9795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9796663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (epartIsReg(modrm)) {
9797663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1;
9798663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(f32lo, getXMMRegLane32F(eregOfRexRM(pfx,modrm), 0));
9799663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%scvt%sss2si %s,%s\n", isAvx ? "v" : "", r2zero ? "t" : "",
9800663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  nameXMMReg(eregOfRexRM(pfx,modrm)),
9801663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  nameIReg(sz, gregOfRexRM(pfx,modrm),
9802663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                           False));
9803663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
9804663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
9805663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(f32lo, loadLE(Ity_F32, mkexpr(addr)));
9806663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen;
9807663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%scvt%sss2si %s,%s\n", isAvx ? "v" : "", r2zero ? "t" : "",
9808663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  dis_buf,
9809663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  nameIReg(sz, gregOfRexRM(pfx,modrm),
9810663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                           False));
9811663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
9812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9813663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (r2zero) {
9814663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( rmode, mkU32((UInt)Irrm_ZERO) );
9815663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
9816663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( rmode, get_sse_roundingmode() );
9817663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
9818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9819663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (sz == 4) {
9820663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      putIReg32( gregOfRexRM(pfx,modrm),
9821663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 binop( Iop_F64toI32S,
9822663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        mkexpr(rmode),
9823663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        unop(Iop_F32toF64, mkexpr(f32lo))) );
9824663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
9825663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(sz == 8);
9826663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      putIReg64( gregOfRexRM(pfx,modrm),
9827663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 binop( Iop_F64toI64S,
9828663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        mkexpr(rmode),
9829663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        unop(Iop_F32toF64, mkexpr(f32lo))) );
9830663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
9831663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
9832663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
9833663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
9834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9836663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_CVTPS2PD_128 ( VexAbiInfo* vbi, Prefix pfx,
9837663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               Long delta, Bool isAvx )
9838663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
9839663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr  = IRTemp_INVALID;
9840663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen  = 0;
9841663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
9842663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp f32lo = newTemp(Ity_F32);
9843663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp f32hi = newTemp(Ity_F32);
9844663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm = getUChar(delta);
9845663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rG    = gregOfRexRM(pfx,modrm);
9846663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (epartIsReg(modrm)) {
9847663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt rE = eregOfRexRM(pfx,modrm);
9848663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( f32lo, getXMMRegLane32F(rE, 0) );
9849663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( f32hi, getXMMRegLane32F(rE, 1) );
9850663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1;
9851663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%scvtps2pd %s,%s\n",
9852663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          isAvx ? "v" : "", nameXMMReg(rE), nameXMMReg(rG));
9853663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
9854663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
9855663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( f32lo, loadLE(Ity_F32, mkexpr(addr)) );
9856663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( f32hi, loadLE(Ity_F32,
9857663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            binop(Iop_Add64,mkexpr(addr),mkU64(4))) );
9858663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen;
9859663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%scvtps2pd %s,%s\n",
9860663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          isAvx ? "v" : "", dis_buf, nameXMMReg(rG));
9861663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
9862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9863663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putXMMRegLane64F( rG, 1, unop(Iop_F32toF64, mkexpr(f32hi)) );
9864663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putXMMRegLane64F( rG, 0, unop(Iop_F32toF64, mkexpr(f32lo)) );
9865663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (isAvx)
9866663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      putYMMRegLane128( rG, 1, mkV128(0));
9867663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
9868663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
9869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9871663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_CVTPS2PD_256 ( VexAbiInfo* vbi, Prefix pfx,
9872663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               Long delta )
9873663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
9874663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr  = IRTemp_INVALID;
9875663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen  = 0;
9876663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
9877663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp f32_0 = newTemp(Ity_F32);
9878663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp f32_1 = newTemp(Ity_F32);
9879663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp f32_2 = newTemp(Ity_F32);
9880663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp f32_3 = newTemp(Ity_F32);
9881663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm = getUChar(delta);
9882663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rG    = gregOfRexRM(pfx,modrm);
9883663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (epartIsReg(modrm)) {
9884663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt rE = eregOfRexRM(pfx,modrm);
9885663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( f32_0, getXMMRegLane32F(rE, 0) );
9886663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( f32_1, getXMMRegLane32F(rE, 1) );
9887663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( f32_2, getXMMRegLane32F(rE, 2) );
9888663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( f32_3, getXMMRegLane32F(rE, 3) );
9889663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1;
9890663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("vcvtps2pd %s,%s\n", nameXMMReg(rE), nameYMMReg(rG));
9891663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
9892663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
9893663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( f32_0, loadLE(Ity_F32, mkexpr(addr)) );
9894663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( f32_1, loadLE(Ity_F32,
9895663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            binop(Iop_Add64,mkexpr(addr),mkU64(4))) );
9896663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( f32_2, loadLE(Ity_F32,
9897663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            binop(Iop_Add64,mkexpr(addr),mkU64(8))) );
9898663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( f32_3, loadLE(Ity_F32,
9899663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            binop(Iop_Add64,mkexpr(addr),mkU64(12))) );
9900663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen;
9901663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("vcvtps2pd %s,%s\n", dis_buf, nameYMMReg(rG));
9902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
9903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9904663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putYMMRegLane64F( rG, 3, unop(Iop_F32toF64, mkexpr(f32_3)) );
9905663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putYMMRegLane64F( rG, 2, unop(Iop_F32toF64, mkexpr(f32_2)) );
9906663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putYMMRegLane64F( rG, 1, unop(Iop_F32toF64, mkexpr(f32_1)) );
9907663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putYMMRegLane64F( rG, 0, unop(Iop_F32toF64, mkexpr(f32_0)) );
9908663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
9909663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
9910f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
9911f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
9912663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_CVTPD2PS_128 ( VexAbiInfo* vbi, Prefix pfx,
9913663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               Long delta, Bool isAvx )
9914663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
9915663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr  = IRTemp_INVALID;
9916663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen  = 0;
9917663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
9918663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm = getUChar(delta);
9919663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rG    = gregOfRexRM(pfx,modrm);
9920663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp argV  = newTemp(Ity_V128);
9921663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp rmode = newTemp(Ity_I32);
9922663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (epartIsReg(modrm)) {
9923663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt rE = eregOfRexRM(pfx,modrm);
9924663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( argV, getXMMReg(rE) );
9925663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1;
9926663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%scvtpd2ps %s,%s\n", isAvx ? "v" : "",
9927663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          nameXMMReg(rE), nameXMMReg(rG));
9928663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
9929663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
9930663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( argV, loadLE(Ity_V128, mkexpr(addr)) );
9931663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen;
9932663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%scvtpd2ps %s,%s\n", isAvx ? "v" : "",
9933663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          dis_buf, nameXMMReg(rG) );
9934663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
9935663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
9936663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( rmode, get_sse_roundingmode() );
9937663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t0 = newTemp(Ity_F64);
9938663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t1 = newTemp(Ity_F64);
9939663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( t0, unop(Iop_ReinterpI64asF64,
9940663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    unop(Iop_V128to64, mkexpr(argV))) );
9941663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( t1, unop(Iop_ReinterpI64asF64,
9942663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    unop(Iop_V128HIto64, mkexpr(argV))) );
9943663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
9944663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  define CVT(_t)  binop( Iop_F64toF32, mkexpr(rmode), mkexpr(_t) )
9945663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putXMMRegLane32(  rG, 3, mkU32(0) );
9946663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putXMMRegLane32(  rG, 2, mkU32(0) );
9947663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putXMMRegLane32F( rG, 1, CVT(t1) );
9948663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putXMMRegLane32F( rG, 0, CVT(t0) );
9949663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  undef CVT
9950663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (isAvx)
9951663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      putYMMRegLane128( rG, 1, mkV128(0) );
9952f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
9953663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
9954663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
9955f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
9956f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
9957663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_CVTxPS2DQ_128 ( VexAbiInfo* vbi, Prefix pfx,
9958663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                Long delta, Bool isAvx, Bool r2zero )
9959663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
9960663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr  = IRTemp_INVALID;
9961663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen  = 0;
9962663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
9963663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm = getUChar(delta);
9964663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp argV  = newTemp(Ity_V128);
9965663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp rmode = newTemp(Ity_I32);
9966663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rG    = gregOfRexRM(pfx,modrm);
9967663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t0, t1, t2, t3;
9968f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
9969663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (epartIsReg(modrm)) {
9970663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt rE = eregOfRexRM(pfx,modrm);
9971663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( argV, getXMMReg(rE) );
9972663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1;
9973663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%scvt%sps2dq %s,%s\n",
9974663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          isAvx ? "v" : "", r2zero ? "t" : "", nameXMMReg(rE), nameXMMReg(rG));
9975663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
9976663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
9977663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( argV, loadLE(Ity_V128, mkexpr(addr)) );
9978663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen;
9979663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%scvt%sps2dq %s,%s\n",
9980663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          isAvx ? "v" : "", r2zero ? "t" : "", dis_buf, nameXMMReg(rG) );
9981663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
9982663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
9983663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( rmode, r2zero ? mkU32((UInt)Irrm_ZERO)
9984663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         : get_sse_roundingmode() );
9985663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t0 = t1 = t2 = t3 = IRTemp_INVALID;
9986663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV128to32s( argV, &t3, &t2, &t1, &t0 );
9987663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* This is less than ideal.  If it turns out to be a performance
9988663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      bottleneck it can be improved. */
9989663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  define CVT(_t)                             \
9990663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      binop( Iop_F64toI32S,                   \
9991663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             mkexpr(rmode),                   \
9992663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             unop( Iop_F32toF64,              \
9993663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   unop( Iop_ReinterpI32asF32, mkexpr(_t))) )
9994663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
9995663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putXMMRegLane32( rG, 3, CVT(t3) );
9996663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putXMMRegLane32( rG, 2, CVT(t2) );
9997663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putXMMRegLane32( rG, 1, CVT(t1) );
9998663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putXMMRegLane32( rG, 0, CVT(t0) );
9999663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  undef CVT
10000663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (isAvx)
10001663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      putYMMRegLane128( rG, 1, mkV128(0) );
10002f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
10003663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
10004663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
10005f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
10006f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
10007663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_CVTxPS2DQ_256 ( VexAbiInfo* vbi, Prefix pfx,
10008663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                Long delta, Bool r2zero )
10009663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
10010663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr  = IRTemp_INVALID;
10011663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen  = 0;
10012663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
10013663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm = getUChar(delta);
10014663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp argV  = newTemp(Ity_V256);
10015663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp rmode = newTemp(Ity_I32);
10016663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rG    = gregOfRexRM(pfx,modrm);
10017663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t0, t1, t2, t3, t4, t5, t6, t7;
10018f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
10019663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (epartIsReg(modrm)) {
10020663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt rE = eregOfRexRM(pfx,modrm);
10021663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( argV, getYMMReg(rE) );
10022663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1;
10023663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("vcvt%sps2dq %s,%s\n",
10024663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          r2zero ? "t" : "", nameYMMReg(rE), nameYMMReg(rG));
10025663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
10026663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
10027663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( argV, loadLE(Ity_V256, mkexpr(addr)) );
10028663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen;
10029663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("vcvt%sps2dq %s,%s\n",
10030663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          r2zero ? "t" : "", dis_buf, nameYMMReg(rG) );
10031663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
10032663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10033663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( rmode, r2zero ? mkU32((UInt)Irrm_ZERO)
10034663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         : get_sse_roundingmode() );
10035663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t0 = t1 = t2 = t3 = t4 = t5 = t6 = t7 = IRTemp_INVALID;
10036663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV256to32s( argV, &t7, &t6, &t5, &t4, &t3, &t2, &t1, &t0 );
10037663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* This is less than ideal.  If it turns out to be a performance
10038663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      bottleneck it can be improved. */
10039663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  define CVT(_t)                             \
10040663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      binop( Iop_F64toI32S,                   \
10041663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             mkexpr(rmode),                   \
10042663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             unop( Iop_F32toF64,              \
10043663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   unop( Iop_ReinterpI32asF32, mkexpr(_t))) )
10044663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10045663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putYMMRegLane32( rG, 7, CVT(t7) );
10046663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putYMMRegLane32( rG, 6, CVT(t6) );
10047663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putYMMRegLane32( rG, 5, CVT(t5) );
10048663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putYMMRegLane32( rG, 4, CVT(t4) );
10049663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putYMMRegLane32( rG, 3, CVT(t3) );
10050663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putYMMRegLane32( rG, 2, CVT(t2) );
10051663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putYMMRegLane32( rG, 1, CVT(t1) );
10052663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putYMMRegLane32( rG, 0, CVT(t0) );
10053663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  undef CVT
10054f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
10055663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
10056663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
10057f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
10058f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
10059663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_CVTxPD2DQ_128 ( VexAbiInfo* vbi, Prefix pfx,
10060663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                Long delta, Bool isAvx, Bool r2zero )
10061663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
10062663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr  = IRTemp_INVALID;
10063663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen  = 0;
10064663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
10065663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm = getUChar(delta);
10066663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp argV  = newTemp(Ity_V128);
10067663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp rmode = newTemp(Ity_I32);
10068663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rG    = gregOfRexRM(pfx,modrm);
10069663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t0, t1;
10070f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
10071663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (epartIsReg(modrm)) {
10072663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt rE = eregOfRexRM(pfx,modrm);
10073663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( argV, getXMMReg(rE) );
10074663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1;
10075663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%scvt%spd2dq %s,%s\n",
10076663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          isAvx ? "v" : "", r2zero ? "t" : "", nameXMMReg(rE), nameXMMReg(rG));
10077663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
10078663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
10079663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( argV, loadLE(Ity_V128, mkexpr(addr)) );
10080663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen;
10081663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%scvt%spd2dqx %s,%s\n",
10082663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          isAvx ? "v" : "", r2zero ? "t" : "", dis_buf, nameXMMReg(rG) );
10083663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
10084f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
10085663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (r2zero) {
10086663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(rmode, mkU32((UInt)Irrm_ZERO) );
10087663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
10088663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( rmode, get_sse_roundingmode() );
10089f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   }
10090f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
10091663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t0 = newTemp(Ity_F64);
10092663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t1 = newTemp(Ity_F64);
10093663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( t0, unop(Iop_ReinterpI64asF64,
10094663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    unop(Iop_V128to64, mkexpr(argV))) );
10095663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( t1, unop(Iop_ReinterpI64asF64,
10096663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    unop(Iop_V128HIto64, mkexpr(argV))) );
10097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10098663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  define CVT(_t)  binop( Iop_F64toI32S,                   \
10099663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          mkexpr(rmode),                   \
10100663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          mkexpr(_t) )
10101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10102663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putXMMRegLane32( rG, 3, mkU32(0) );
10103663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putXMMRegLane32( rG, 2, mkU32(0) );
10104663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putXMMRegLane32( rG, 1, CVT(t1) );
10105663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putXMMRegLane32( rG, 0, CVT(t0) );
10106663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  undef CVT
10107663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (isAvx)
10108663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      putYMMRegLane128( rG, 1, mkV128(0) );
10109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10110663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
10111663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
10112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10114663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_CVTxPD2DQ_256 ( VexAbiInfo* vbi, Prefix pfx,
10115663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                Long delta, Bool r2zero )
10116663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
10117663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr  = IRTemp_INVALID;
10118663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen  = 0;
10119663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
10120663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm = getUChar(delta);
10121663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp argV  = newTemp(Ity_V256);
10122663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp rmode = newTemp(Ity_I32);
10123663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rG    = gregOfRexRM(pfx,modrm);
10124663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t0, t1, t2, t3;
10125663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10126663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (epartIsReg(modrm)) {
10127663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt rE = eregOfRexRM(pfx,modrm);
10128663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( argV, getYMMReg(rE) );
10129663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1;
10130663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("vcvt%spd2dq %s,%s\n",
10131663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          r2zero ? "t" : "", nameYMMReg(rE), nameXMMReg(rG));
10132663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
10133663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
10134663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( argV, loadLE(Ity_V256, mkexpr(addr)) );
10135663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen;
10136663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("vcvt%spd2dqy %s,%s\n",
10137663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          r2zero ? "t" : "", dis_buf, nameXMMReg(rG) );
10138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
10139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10140663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (r2zero) {
10141663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(rmode, mkU32((UInt)Irrm_ZERO) );
10142663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
10143663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( rmode, get_sse_roundingmode() );
10144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
10145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10146663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t0 = IRTemp_INVALID;
10147663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t1 = IRTemp_INVALID;
10148663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t2 = IRTemp_INVALID;
10149663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t3 = IRTemp_INVALID;
10150663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV256to64s( argV, &t3, &t2, &t1, &t0 );
10151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10152663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  define CVT(_t)  binop( Iop_F64toI32S,                   \
10153663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          mkexpr(rmode),                   \
10154663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          unop( Iop_ReinterpI64asF64,      \
10155663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                mkexpr(_t) ) )
10156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10157663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putXMMRegLane32( rG, 3, CVT(t3) );
10158663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putXMMRegLane32( rG, 2, CVT(t2) );
10159663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putXMMRegLane32( rG, 1, CVT(t1) );
10160663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putXMMRegLane32( rG, 0, CVT(t0) );
10161663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  undef CVT
10162663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putYMMRegLane128( rG, 1, mkV128(0) );
10163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10164663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
10165663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
10166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10168663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_CVTDQ2PS_128 ( VexAbiInfo* vbi, Prefix pfx,
10169663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               Long delta, Bool isAvx )
10170663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
10171663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr  = IRTemp_INVALID;
10172663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen  = 0;
10173663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
10174663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm = getUChar(delta);
10175663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp argV  = newTemp(Ity_V128);
10176663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp rmode = newTemp(Ity_I32);
10177663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rG    = gregOfRexRM(pfx,modrm);
10178663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t0, t1, t2, t3;
10179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10180663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (epartIsReg(modrm)) {
10181663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt rE = eregOfRexRM(pfx,modrm);
10182663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( argV, getXMMReg(rE) );
10183663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1;
10184663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%scvtdq2ps %s,%s\n",
10185663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          isAvx ? "v" : "", nameXMMReg(rE), nameXMMReg(rG));
10186663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
10187663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
10188663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( argV, loadLE(Ity_V128, mkexpr(addr)) );
10189663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen;
10190663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%scvtdq2ps %s,%s\n",
10191663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          isAvx ? "v" : "", dis_buf, nameXMMReg(rG) );
10192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
10193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10194663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( rmode, get_sse_roundingmode() );
10195663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t0 = IRTemp_INVALID;
10196663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t1 = IRTemp_INVALID;
10197663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t2 = IRTemp_INVALID;
10198663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t3 = IRTemp_INVALID;
10199663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV128to32s( argV, &t3, &t2, &t1, &t0 );
10200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10201663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  define CVT(_t)  binop( Iop_F64toF32,                    \
10202663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          mkexpr(rmode),                   \
10203663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          unop(Iop_I32StoF64,mkexpr(_t)))
10204663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10205663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putXMMRegLane32F( rG, 3, CVT(t3) );
10206663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putXMMRegLane32F( rG, 2, CVT(t2) );
10207663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putXMMRegLane32F( rG, 1, CVT(t1) );
10208663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putXMMRegLane32F( rG, 0, CVT(t0) );
10209663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  undef CVT
10210663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (isAvx)
10211663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      putYMMRegLane128( rG, 1, mkV128(0) );
10212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10213663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
10214663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
10215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10216663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_CVTDQ2PS_256 ( VexAbiInfo* vbi, Prefix pfx,
10217663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               Long delta )
10218663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
10219663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr   = IRTemp_INVALID;
10220663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen   = 0;
10221663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
10222663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm  = getUChar(delta);
10223663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp argV   = newTemp(Ity_V256);
10224663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp rmode  = newTemp(Ity_I32);
10225663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rG     = gregOfRexRM(pfx,modrm);
10226663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t0, t1, t2, t3, t4, t5, t6, t7;
10227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10228663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (epartIsReg(modrm)) {
10229663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt rE = eregOfRexRM(pfx,modrm);
10230663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( argV, getYMMReg(rE) );
10231663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1;
10232663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("vcvtdq2ps %s,%s\n", nameYMMReg(rE), nameYMMReg(rG));
10233663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
10234663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
10235663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( argV, loadLE(Ity_V256, mkexpr(addr)) );
10236663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen;
10237663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("vcvtdq2ps %s,%s\n", dis_buf, nameYMMReg(rG) );
10238663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
10239663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10240663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( rmode, get_sse_roundingmode() );
10241663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t0 = IRTemp_INVALID;
10242663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t1 = IRTemp_INVALID;
10243663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t2 = IRTemp_INVALID;
10244663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t3 = IRTemp_INVALID;
10245663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t4 = IRTemp_INVALID;
10246663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t5 = IRTemp_INVALID;
10247663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t6 = IRTemp_INVALID;
10248663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t7 = IRTemp_INVALID;
10249663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV256to32s( argV, &t7, &t6, &t5, &t4, &t3, &t2, &t1, &t0 );
10250663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10251663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  define CVT(_t)  binop( Iop_F64toF32,                    \
10252663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          mkexpr(rmode),                   \
10253663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          unop(Iop_I32StoF64,mkexpr(_t)))
10254663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10255663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putYMMRegLane32F( rG, 7, CVT(t7) );
10256663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putYMMRegLane32F( rG, 6, CVT(t6) );
10257663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putYMMRegLane32F( rG, 5, CVT(t5) );
10258663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putYMMRegLane32F( rG, 4, CVT(t4) );
10259663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putYMMRegLane32F( rG, 3, CVT(t3) );
10260663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putYMMRegLane32F( rG, 2, CVT(t2) );
10261663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putYMMRegLane32F( rG, 1, CVT(t1) );
10262663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putYMMRegLane32F( rG, 0, CVT(t0) );
10263663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  undef CVT
10264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10265663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
10266663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
10267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10269663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_PMOVMSKB_128 ( VexAbiInfo* vbi, Prefix pfx,
10270663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               Long delta, Bool isAvx )
10271663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
10272663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* UInt x86g_calculate_sse_pmovmskb ( ULong w64hi, ULong w64lo ); */
10273663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar modrm = getUChar(delta);
10274663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(epartIsReg(modrm)); /* ensured by caller */
10275663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rE = eregOfRexRM(pfx,modrm);
10276663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rG = gregOfRexRM(pfx,modrm);
10277663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t0 = newTemp(Ity_I64);
10278663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t1 = newTemp(Ity_I64);
10279663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t5 = newTemp(Ity_I64);
10280663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(t0, getXMMRegLane64(rE, 0));
10281663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(t1, getXMMRegLane64(rE, 1));
10282663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(t5, mkIRExprCCall( Ity_I64, 0/*regparms*/,
10283663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             "amd64g_calculate_sse_pmovmskb",
10284663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             &amd64g_calculate_sse_pmovmskb,
10285663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             mkIRExprVec_2( mkexpr(t1), mkexpr(t0) )));
10286663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putIReg32(rG, unop(Iop_64to32,mkexpr(t5)));
10287663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   DIP("%spmovmskb %s,%s\n", isAvx ? "v" : "", nameXMMReg(rE),
10288663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       nameIReg32(rG));
10289663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   delta += 1;
10290663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
10291663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
10292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10294663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* FIXME: why not just use InterleaveLO / InterleaveHI?  I think the
10295663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   relevant ops are "xIsH ? InterleaveHI32x4 : InterleaveLO32x4". */
10296663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Does the maths for 128 bit versions of UNPCKLPS and UNPCKHPS */
10297663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRTemp math_UNPCKxPS_128 ( IRTemp sV, IRTemp dV, Bool xIsH )
10298663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
10299663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp s3, s2, s1, s0, d3, d2, d1, d0;
10300663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   s3 = s2 = s1 = s0 = d3 = d2 = d1 = d0 = IRTemp_INVALID;
10301663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV128to32s( dV, &d3, &d2, &d1, &d0 );
10302663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV128to32s( sV, &s3, &s2, &s1, &s0 );
10303663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp res = newTemp(Ity_V128);
10304663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(res,  xIsH ? mkV128from32s( s3, d3, s2, d2 )
10305663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     : mkV128from32s( s1, d1, s0, d0 ));
10306663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return res;
10307663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
10308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10310663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* FIXME: why not just use InterleaveLO / InterleaveHI ?? */
10311663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Does the maths for 128 bit versions of UNPCKLPD and UNPCKHPD */
10312663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRTemp math_UNPCKxPD_128 ( IRTemp sV, IRTemp dV, Bool xIsH )
10313663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
10314663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp s1 = newTemp(Ity_I64);
10315663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp s0 = newTemp(Ity_I64);
10316663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp d1 = newTemp(Ity_I64);
10317663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp d0 = newTemp(Ity_I64);
10318663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( d1, unop(Iop_V128HIto64, mkexpr(dV)) );
10319663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( d0, unop(Iop_V128to64,   mkexpr(dV)) );
10320663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( s1, unop(Iop_V128HIto64, mkexpr(sV)) );
10321663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( s0, unop(Iop_V128to64,   mkexpr(sV)) );
10322663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp res = newTemp(Ity_V128);
10323663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(res, xIsH ? binop(Iop_64HLtoV128, mkexpr(s1), mkexpr(d1))
10324663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    : binop(Iop_64HLtoV128, mkexpr(s0), mkexpr(d0)));
10325663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return res;
10326663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
10327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10329663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Does the maths for 256 bit versions of UNPCKLPD and UNPCKHPD.
10330663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Doesn't seem like this fits in either of the Iop_Interleave{LO,HI}
10331663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   or the Iop_Cat{Odd,Even}Lanes idioms, hence just do it the stupid
10332663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   way. */
10333663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRTemp math_UNPCKxPD_256 ( IRTemp sV, IRTemp dV, Bool xIsH )
10334663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
10335663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp s3, s2, s1, s0, d3, d2, d1, d0;
10336663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   s3 = s2 = s1 = s0 = d3 = d2 = d1 = d0 = IRTemp_INVALID;
10337663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV256to64s( dV, &d3, &d2, &d1, &d0 );
10338663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV256to64s( sV, &s3, &s2, &s1, &s0 );
10339663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp res = newTemp(Ity_V256);
10340663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(res, xIsH
10341663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               ? IRExpr_Qop(Iop_64x4toV256, mkexpr(s3), mkexpr(d3),
10342663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                            mkexpr(s1), mkexpr(d1))
10343663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               : IRExpr_Qop(Iop_64x4toV256, mkexpr(s2), mkexpr(d2),
10344663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                            mkexpr(s0), mkexpr(d0)));
10345663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return res;
10346663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
10347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10349663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* FIXME: this is really bad.  Surely can do something better here?
10350663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   One observation is that the steering in the upper and lower 128 bit
10351663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   halves is the same as with math_UNPCKxPS_128, so we simply split
10352663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   into two halves, and use that.  Consequently any improvement in
10353663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   math_UNPCKxPS_128 (probably, to use interleave-style primops)
10354663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   benefits this too. */
10355663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRTemp math_UNPCKxPS_256 ( IRTemp sV, IRTemp dV, Bool xIsH )
10356663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
10357663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp sVhi = IRTemp_INVALID, sVlo = IRTemp_INVALID;
10358663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp dVhi = IRTemp_INVALID, dVlo = IRTemp_INVALID;
10359663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV256toV128s( sV, &sVhi, &sVlo );
10360663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV256toV128s( dV, &dVhi, &dVlo );
10361663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp rVhi = math_UNPCKxPS_128(sVhi, dVhi, xIsH);
10362663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp rVlo = math_UNPCKxPS_128(sVlo, dVlo, xIsH);
10363663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp rV   = newTemp(Ity_V256);
10364663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(rV, binop(Iop_V128HLtoV256, mkexpr(rVhi), mkexpr(rVlo)));
10365663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return rV;
10366663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
10367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10369663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRTemp math_SHUFPS_128 ( IRTemp sV, IRTemp dV, UInt imm8 )
10370663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
10371663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp s3, s2, s1, s0, d3, d2, d1, d0;
10372663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   s3 = s2 = s1 = s0 = d3 = d2 = d1 = d0 = IRTemp_INVALID;
10373663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(imm8 < 256);
10374663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10375663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV128to32s( dV, &d3, &d2, &d1, &d0 );
10376663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV128to32s( sV, &s3, &s2, &s1, &s0 );
10377663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10378663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  define SELD(n) ((n)==0 ? d0 : ((n)==1 ? d1 : ((n)==2 ? d2 : d3)))
10379663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  define SELS(n) ((n)==0 ? s0 : ((n)==1 ? s1 : ((n)==2 ? s2 : s3)))
10380663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp res = newTemp(Ity_V128);
10381663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(res,
10382663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          mkV128from32s( SELS((imm8>>6)&3), SELS((imm8>>4)&3),
10383663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         SELD((imm8>>2)&3), SELD((imm8>>0)&3) ) );
10384663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  undef SELD
10385663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  undef SELS
10386663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return res;
10387663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
10388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10390663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* 256-bit SHUFPS appears to steer each of the 128-bit halves
10391663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   identically.  Hence do the clueless thing and use math_SHUFPS_128
10392663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   twice. */
10393663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRTemp math_SHUFPS_256 ( IRTemp sV, IRTemp dV, UInt imm8 )
10394663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
10395663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp sVhi = IRTemp_INVALID, sVlo = IRTemp_INVALID;
10396663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp dVhi = IRTemp_INVALID, dVlo = IRTemp_INVALID;
10397663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV256toV128s( sV, &sVhi, &sVlo );
10398663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV256toV128s( dV, &dVhi, &dVlo );
10399663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp rVhi = math_SHUFPS_128(sVhi, dVhi, imm8);
10400663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp rVlo = math_SHUFPS_128(sVlo, dVlo, imm8);
10401663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp rV   = newTemp(Ity_V256);
10402663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(rV, binop(Iop_V128HLtoV256, mkexpr(rVhi), mkexpr(rVlo)));
10403663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return rV;
10404663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
10405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10407663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRTemp math_SHUFPD_128 ( IRTemp sV, IRTemp dV, UInt imm8 )
10408663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
10409663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp s1 = newTemp(Ity_I64);
10410663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp s0 = newTemp(Ity_I64);
10411663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp d1 = newTemp(Ity_I64);
10412663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp d0 = newTemp(Ity_I64);
10413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10414663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( d1, unop(Iop_V128HIto64, mkexpr(dV)) );
10415663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( d0, unop(Iop_V128to64,   mkexpr(dV)) );
10416663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( s1, unop(Iop_V128HIto64, mkexpr(sV)) );
10417663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( s0, unop(Iop_V128to64,   mkexpr(sV)) );
10418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10419663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  define SELD(n) mkexpr((n)==0 ? d0 : d1)
10420663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  define SELS(n) mkexpr((n)==0 ? s0 : s1)
10421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10422663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp res = newTemp(Ity_V128);
10423663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(res, binop( Iop_64HLtoV128,
10424663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      SELS((imm8>>1)&1), SELD((imm8>>0)&1) ) );
10425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10426663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  undef SELD
10427663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  undef SELS
10428663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return res;
10429663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
10430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10432663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRTemp math_SHUFPD_256 ( IRTemp sV, IRTemp dV, UInt imm8 )
10433663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
10434663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp sVhi = IRTemp_INVALID, sVlo = IRTemp_INVALID;
10435663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp dVhi = IRTemp_INVALID, dVlo = IRTemp_INVALID;
10436663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV256toV128s( sV, &sVhi, &sVlo );
10437663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV256toV128s( dV, &dVhi, &dVlo );
10438663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp rVhi = math_SHUFPD_128(sVhi, dVhi, (imm8 >> 2) & 3);
10439663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp rVlo = math_SHUFPD_128(sVlo, dVlo, imm8 & 3);
10440663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp rV   = newTemp(Ity_V256);
10441663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(rV, binop(Iop_V128HLtoV256, mkexpr(rVhi), mkexpr(rVlo)));
10442663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return rV;
10443663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
10444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10446663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRTemp math_BLENDPD_128 ( IRTemp sV, IRTemp dV, UInt imm8 )
10447663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
10448663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UShort imm8_mask_16;
10449663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp imm8_mask = newTemp(Ity_V128);
10450663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10451663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch( imm8 & 3 ) {
10452663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0:  imm8_mask_16 = 0x0000; break;
10453663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 1:  imm8_mask_16 = 0x00FF; break;
10454663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 2:  imm8_mask_16 = 0xFF00; break;
10455663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 3:  imm8_mask_16 = 0xFFFF; break;
10456663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default: vassert(0);            break;
10457663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
10458663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( imm8_mask, mkV128( imm8_mask_16 ) );
10459663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10460663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp res = newTemp(Ity_V128);
10461663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign ( res, binop( Iop_OrV128,
10462663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        binop( Iop_AndV128, mkexpr(sV),
10463663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                            mkexpr(imm8_mask) ),
10464663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        binop( Iop_AndV128, mkexpr(dV),
10465663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               unop( Iop_NotV128, mkexpr(imm8_mask) ) ) ) );
10466663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return res;
10467663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
10468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10470663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRTemp math_BLENDPD_256 ( IRTemp sV, IRTemp dV, UInt imm8 )
10471663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
10472663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp sVhi = IRTemp_INVALID, sVlo = IRTemp_INVALID;
10473663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp dVhi = IRTemp_INVALID, dVlo = IRTemp_INVALID;
10474663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV256toV128s( sV, &sVhi, &sVlo );
10475663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV256toV128s( dV, &dVhi, &dVlo );
10476663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp rVhi = math_BLENDPD_128(sVhi, dVhi, (imm8 >> 2) & 3);
10477663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp rVlo = math_BLENDPD_128(sVlo, dVlo, imm8 & 3);
10478663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp rV   = newTemp(Ity_V256);
10479663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(rV, binop(Iop_V128HLtoV256, mkexpr(rVhi), mkexpr(rVlo)));
10480663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return rV;
10481663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
10482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10484663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRTemp math_BLENDPS_128 ( IRTemp sV, IRTemp dV, UInt imm8 )
10485663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
10486663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UShort imm8_perms[16] = { 0x0000, 0x000F, 0x00F0, 0x00FF, 0x0F00,
10487663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             0x0F0F, 0x0FF0, 0x0FFF, 0xF000, 0xF00F,
10488663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             0xF0F0, 0xF0FF, 0xFF00, 0xFF0F, 0xFFF0,
10489663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             0xFFFF };
10490663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp imm8_mask = newTemp(Ity_V128);
10491663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( imm8_mask, mkV128( imm8_perms[ (imm8 & 15) ] ) );
10492663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10493663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp res = newTemp(Ity_V128);
10494663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign ( res, binop( Iop_OrV128,
10495663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        binop( Iop_AndV128, mkexpr(sV),
10496663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                            mkexpr(imm8_mask) ),
10497663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        binop( Iop_AndV128, mkexpr(dV),
10498663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               unop( Iop_NotV128, mkexpr(imm8_mask) ) ) ) );
10499663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return res;
10500663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
10501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10503663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRTemp math_BLENDPS_256 ( IRTemp sV, IRTemp dV, UInt imm8 )
10504663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
10505663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp sVhi = IRTemp_INVALID, sVlo = IRTemp_INVALID;
10506663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp dVhi = IRTemp_INVALID, dVlo = IRTemp_INVALID;
10507663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV256toV128s( sV, &sVhi, &sVlo );
10508663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV256toV128s( dV, &dVhi, &dVlo );
10509663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp rVhi = math_BLENDPS_128(sVhi, dVhi, (imm8 >> 4) & 15);
10510663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp rVlo = math_BLENDPS_128(sVlo, dVlo, imm8 & 15);
10511663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp rV   = newTemp(Ity_V256);
10512663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(rV, binop(Iop_V128HLtoV256, mkexpr(rVhi), mkexpr(rVlo)));
10513663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return rV;
10514663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
10515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10517663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRTemp math_PBLENDW_128 ( IRTemp sV, IRTemp dV, UInt imm8 )
10518663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
10519663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Make w be a 16-bit version of imm8, formed by duplicating each
10520663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      bit in imm8. */
10521663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int i;
10522663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UShort imm16 = 0;
10523663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   for (i = 0; i < 8; i++) {
10524663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (imm8 & (1 << i))
10525663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         imm16 |= (3 << (2*i));
10526663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
10527663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp imm16_mask = newTemp(Ity_V128);
10528663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( imm16_mask, mkV128( imm16 ));
10529663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10530663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp res = newTemp(Ity_V128);
10531663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign ( res, binop( Iop_OrV128,
10532663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        binop( Iop_AndV128, mkexpr(sV),
10533663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                            mkexpr(imm16_mask) ),
10534663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        binop( Iop_AndV128, mkexpr(dV),
10535663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               unop( Iop_NotV128, mkexpr(imm16_mask) ) ) ) );
10536663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return res;
10537663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
10538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10540663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRTemp math_PMULUDQ_128 ( IRTemp sV, IRTemp dV )
10541663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
10542663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* This is a really poor translation -- could be improved if
10543663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      performance critical */
10544663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp s3, s2, s1, s0, d3, d2, d1, d0;
10545663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   s3 = s2 = s1 = s0 = d3 = d2 = d1 = d0 = IRTemp_INVALID;
10546663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV128to32s( dV, &d3, &d2, &d1, &d0 );
10547663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV128to32s( sV, &s3, &s2, &s1, &s0 );
10548663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp res = newTemp(Ity_V128);
10549663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(res, binop(Iop_64HLtoV128,
10550663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     binop( Iop_MullU32, mkexpr(d2), mkexpr(s2)),
10551663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     binop( Iop_MullU32, mkexpr(d0), mkexpr(s0)) ));
10552663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return res;
10553663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
10554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10556663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRTemp math_PMULDQ_128 ( IRTemp dV, IRTemp sV )
10557663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
10558663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* This is a really poor translation -- could be improved if
10559663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      performance critical */
10560663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp s3, s2, s1, s0, d3, d2, d1, d0;
10561663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   s3 = s2 = s1 = s0 = d3 = d2 = d1 = d0 = IRTemp_INVALID;
10562663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV128to32s( dV, &d3, &d2, &d1, &d0 );
10563663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV128to32s( sV, &s3, &s2, &s1, &s0 );
10564663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp res = newTemp(Ity_V128);
10565663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(res, binop(Iop_64HLtoV128,
10566663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     binop( Iop_MullS32, mkexpr(d2), mkexpr(s2)),
10567663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     binop( Iop_MullS32, mkexpr(d0), mkexpr(s0)) ));
10568663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return res;
10569663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
10570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10572663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRTemp math_PMADDWD_128 ( IRTemp dV, IRTemp sV )
10573663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
10574663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp sVhi, sVlo, dVhi, dVlo;
10575663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp resHi = newTemp(Ity_I64);
10576663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp resLo = newTemp(Ity_I64);
10577663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   sVhi = sVlo = dVhi = dVlo = IRTemp_INVALID;
10578663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV128to64s( sV, &sVhi, &sVlo );
10579663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV128to64s( dV, &dVhi, &dVlo );
10580663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( resHi, mkIRExprCCall(Ity_I64, 0/*regparms*/,
10581663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                "amd64g_calculate_mmx_pmaddwd",
10582663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                &amd64g_calculate_mmx_pmaddwd,
10583663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                mkIRExprVec_2( mkexpr(sVhi), mkexpr(dVhi))));
10584663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( resLo, mkIRExprCCall(Ity_I64, 0/*regparms*/,
10585663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                "amd64g_calculate_mmx_pmaddwd",
10586663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                &amd64g_calculate_mmx_pmaddwd,
10587663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                mkIRExprVec_2( mkexpr(sVlo), mkexpr(dVlo))));
10588663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp res = newTemp(Ity_V128);
10589663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( res, binop(Iop_64HLtoV128, mkexpr(resHi), mkexpr(resLo))) ;
10590663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return res;
10591663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
10592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10594663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRTemp math_ADDSUBPD_128 ( IRTemp dV, IRTemp sV )
10595663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
10596663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addV = newTemp(Ity_V128);
10597663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp subV = newTemp(Ity_V128);
10598663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp a1   = newTemp(Ity_I64);
10599663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp s0   = newTemp(Ity_I64);
10600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10601663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( addV, binop(Iop_Add64Fx2, mkexpr(dV), mkexpr(sV)) );
10602663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( subV, binop(Iop_Sub64Fx2, mkexpr(dV), mkexpr(sV)) );
10603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10604663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( a1, unop(Iop_V128HIto64, mkexpr(addV) ));
10605663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( s0, unop(Iop_V128to64,   mkexpr(subV) ));
10606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10607663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp res = newTemp(Ity_V128);
10608663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( res, binop(Iop_64HLtoV128, mkexpr(a1), mkexpr(s0)) );
10609663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return res;
10610663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
10611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10613663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRTemp math_ADDSUBPD_256 ( IRTemp dV, IRTemp sV )
10614663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
10615663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp a3, a2, a1, a0, s3, s2, s1, s0;
10616663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addV = newTemp(Ity_V256);
10617663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp subV = newTemp(Ity_V256);
10618663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   a3 = a2 = a1 = a0 = s3 = s2 = s1 = s0 = IRTemp_INVALID;
10619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10620663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( addV, binop(Iop_Add64Fx4, mkexpr(dV), mkexpr(sV)) );
10621663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( subV, binop(Iop_Sub64Fx4, mkexpr(dV), mkexpr(sV)) );
10622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10623663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV256to64s( addV, &a3, &a2, &a1, &a0 );
10624663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV256to64s( subV, &s3, &s2, &s1, &s0 );
10625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10626663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp res = newTemp(Ity_V256);
10627663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( res, mkV256from64s( a3, s2, a1, s0 ) );
10628663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return res;
10629663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
10630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10632663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRTemp math_ADDSUBPS_128 ( IRTemp dV, IRTemp sV )
10633663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
10634663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp a3, a2, a1, a0, s3, s2, s1, s0;
10635663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addV = newTemp(Ity_V128);
10636663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp subV = newTemp(Ity_V128);
10637663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   a3 = a2 = a1 = a0 = s3 = s2 = s1 = s0 = IRTemp_INVALID;
10638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10639663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( addV, binop(Iop_Add32Fx4, mkexpr(dV), mkexpr(sV)) );
10640663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( subV, binop(Iop_Sub32Fx4, mkexpr(dV), mkexpr(sV)) );
10641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10642663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV128to32s( addV, &a3, &a2, &a1, &a0 );
10643663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV128to32s( subV, &s3, &s2, &s1, &s0 );
10644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10645663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp res = newTemp(Ity_V128);
10646663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( res, mkV128from32s( a3, s2, a1, s0 ) );
10647663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return res;
10648663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
10649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10651663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRTemp math_ADDSUBPS_256 ( IRTemp dV, IRTemp sV )
10652663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
10653663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp a7, a6, a5, a4, a3, a2, a1, a0;
10654663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp s7, s6, s5, s4, s3, s2, s1, s0;
10655663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addV = newTemp(Ity_V256);
10656663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp subV = newTemp(Ity_V256);
10657663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   a7 = a6 = a5 = a4 = a3 = a2 = a1 = a0 = IRTemp_INVALID;
10658663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   s7 = s6 = s5 = s4 = s3 = s2 = s1 = s0 = IRTemp_INVALID;
10659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10660663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( addV, binop(Iop_Add32Fx8, mkexpr(dV), mkexpr(sV)) );
10661663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( subV, binop(Iop_Sub32Fx8, mkexpr(dV), mkexpr(sV)) );
10662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10663663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV256to32s( addV, &a7, &a6, &a5, &a4, &a3, &a2, &a1, &a0 );
10664663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV256to32s( subV, &s7, &s6, &s5, &s4, &s3, &s2, &s1, &s0 );
10665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10666663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp res = newTemp(Ity_V256);
10667663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( res, mkV256from32s( a7, s6, a5, s4, a3, s2, a1, s0 ) );
10668663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return res;
10669663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
10670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10671663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10672663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Handle 128 bit PSHUFLW and PSHUFHW. */
10673663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_PSHUFxW_128 ( VexAbiInfo* vbi, Prefix pfx,
10674663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              Long delta, Bool isAvx, Bool xIsH )
10675663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
10676663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr  = IRTemp_INVALID;
10677663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen  = 0;
10678663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
10679663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm = getUChar(delta);
10680663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rG = gregOfRexRM(pfx,modrm);
10681663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   imm8;
10682663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp sVmut, dVmut, sVcon, sV, dV, s3, s2, s1, s0;
10683663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   s3 = s2 = s1 = s0 = IRTemp_INVALID;
10684663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   sV    = newTemp(Ity_V128);
10685663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   dV    = newTemp(Ity_V128);
10686663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   sVmut = newTemp(Ity_I64);
10687663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   dVmut = newTemp(Ity_I64);
10688663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   sVcon = newTemp(Ity_I64);
10689663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (epartIsReg(modrm)) {
10690663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt rE = eregOfRexRM(pfx,modrm);
10691663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( sV, getXMMReg(rE) );
10692663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      imm8 = (UInt)getUChar(delta+1);
10693663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1+1;
10694663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%spshuf%cw $%u,%s,%s\n",
10695663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          isAvx ? "v" : "", xIsH ? 'h' : 'l',
10696663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          imm8, nameXMMReg(rE), nameXMMReg(rG));
10697663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
10698663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 1 );
10699663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
10700663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      imm8 = (UInt)getUChar(delta+alen);
10701663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen+1;
10702663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%spshuf%cw $%u,%s,%s\n",
10703663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          isAvx ? "v" : "", xIsH ? 'h' : 'l',
10704663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          imm8, dis_buf, nameXMMReg(rG));
10705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
10706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10707663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Get the to-be-changed (mut) and unchanging (con) bits of the
10708663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      source. */
10709663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( sVmut, unop(xIsH ? Iop_V128HIto64 : Iop_V128to64,   mkexpr(sV)) );
10710663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( sVcon, unop(xIsH ? Iop_V128to64   : Iop_V128HIto64, mkexpr(sV)) );
10711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10712663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakup64to16s( sVmut, &s3, &s2, &s1, &s0 );
10713663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  define SEL(n) \
10714663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             ((n)==0 ? s0 : ((n)==1 ? s1 : ((n)==2 ? s2 : s3)))
10715663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(dVmut, mk64from16s( SEL((imm8>>6)&3), SEL((imm8>>4)&3),
10716663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              SEL((imm8>>2)&3), SEL((imm8>>0)&3) ));
10717663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  undef SEL
10718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10719663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(dV, xIsH ? binop(Iop_64HLtoV128, mkexpr(dVmut), mkexpr(sVcon))
10720663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   : binop(Iop_64HLtoV128, mkexpr(sVcon), mkexpr(dVmut)) );
10721663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10722663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   (isAvx ? putYMMRegLoAndZU : putXMMReg)(rG, mkexpr(dV));
10723663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
10724663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
10725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10727663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_PEXTRW_128_EregOnly_toG ( VexAbiInfo* vbi, Prefix pfx,
10728663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                          Long delta, Bool isAvx )
10729663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
10730663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Long   deltaIN = delta;
10731663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm   = getUChar(delta);
10732663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rG      = gregOfRexRM(pfx,modrm);
10733663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp sV      = newTemp(Ity_V128);
10734663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp d16     = newTemp(Ity_I16);
10735663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   imm8;
10736663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp s0, s1, s2, s3;
10737663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (epartIsReg(modrm)) {
10738663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt rE = eregOfRexRM(pfx,modrm);
10739663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(sV, getXMMReg(rE));
10740663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      imm8 = getUChar(delta+1) & 7;
10741663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1+1;
10742663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%spextrw $%d,%s,%s\n", isAvx ? "v" : "",
10743663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          (Int)imm8, nameXMMReg(rE), nameIReg32(rG));
10744663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
10745663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* The memory case is disallowed, apparently. */
10746663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return deltaIN; /* FAIL */
10747663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
10748663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   s3 = s2 = s1 = s0 = IRTemp_INVALID;
10749663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV128to32s( sV, &s3, &s2, &s1, &s0 );
10750663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (imm8) {
10751663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0:  assign(d16, unop(Iop_32to16,   mkexpr(s0))); break;
10752663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 1:  assign(d16, unop(Iop_32HIto16, mkexpr(s0))); break;
10753663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 2:  assign(d16, unop(Iop_32to16,   mkexpr(s1))); break;
10754663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 3:  assign(d16, unop(Iop_32HIto16, mkexpr(s1))); break;
10755663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 4:  assign(d16, unop(Iop_32to16,   mkexpr(s2))); break;
10756663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 5:  assign(d16, unop(Iop_32HIto16, mkexpr(s2))); break;
10757663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 6:  assign(d16, unop(Iop_32to16,   mkexpr(s3))); break;
10758663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 7:  assign(d16, unop(Iop_32HIto16, mkexpr(s3))); break;
10759663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default: vassert(0);
10760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
10761663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putIReg32(rG, unop(Iop_16Uto32, mkexpr(d16)));
10762663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
10763663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
10764663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10766663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_CVTDQ2PD_128 ( VexAbiInfo* vbi, Prefix pfx,
10767663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               Long delta, Bool isAvx )
10768663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
10769663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr  = IRTemp_INVALID;
10770663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen  = 0;
10771663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
10772663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm = getUChar(delta);
10773663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp arg64 = newTemp(Ity_I64);
10774663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rG    = gregOfRexRM(pfx,modrm);
10775663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar* mbV   = isAvx ? "v" : "";
10776663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (epartIsReg(modrm)) {
10777663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt rE = eregOfRexRM(pfx,modrm);
10778663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( arg64, getXMMRegLane64(rE, 0) );
10779663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1;
10780663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%scvtdq2pd %s,%s\n", mbV, nameXMMReg(rE), nameXMMReg(rG));
10781663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
10782663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
10783663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( arg64, loadLE(Ity_I64, mkexpr(addr)) );
10784663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen;
10785663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%scvtdq2pd %s,%s\n", mbV, dis_buf, nameXMMReg(rG) );
10786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
10787663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putXMMRegLane64F(
10788663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      rG, 0,
10789663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      unop(Iop_I32StoF64, unop(Iop_64to32, mkexpr(arg64)))
10790663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   );
10791663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putXMMRegLane64F(
10792663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      rG, 1,
10793663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      unop(Iop_I32StoF64, unop(Iop_64HIto32, mkexpr(arg64)))
10794663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   );
10795663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (isAvx)
10796663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      putYMMRegLane128(rG, 1, mkV128(0));
10797663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
10798663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
10799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10801663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_STMXCSR ( VexAbiInfo* vbi, Prefix pfx,
10802663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          Long delta, Bool isAvx )
10803663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
10804663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr  = IRTemp_INVALID;
10805663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen  = 0;
10806663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
10807663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm = getUChar(delta);
10808663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(!epartIsReg(modrm)); /* ensured by caller */
10809663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(gregOfRexRM(pfx,modrm) == 3); /* ditto */
10810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10811663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
10812663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   delta += alen;
10813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10814663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Fake up a native SSE mxcsr word.  The only thing it depends on
10815663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      is SSEROUND[1:0], so call a clean helper to cook it up.
10816663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   */
10817663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ULong amd64h_create_mxcsr ( ULong sseround ) */
10818663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   DIP("%sstmxcsr %s\n",  isAvx ? "v" : "", dis_buf);
10819663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   storeLE(
10820663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      mkexpr(addr),
10821663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      unop(Iop_64to32,
10822663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           mkIRExprCCall(
10823663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              Ity_I64, 0/*regp*/,
10824663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              "amd64g_create_mxcsr", &amd64g_create_mxcsr,
10825663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              mkIRExprVec_1( unop(Iop_32Uto64,get_sse_roundingmode()) )
10826663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           )
10827663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      )
10828663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   );
10829663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
10830663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
10831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10833663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_LDMXCSR ( VexAbiInfo* vbi, Prefix pfx,
10834663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          Long delta, Bool isAvx )
10835663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
10836663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr  = IRTemp_INVALID;
10837663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen  = 0;
10838663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
10839663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm = getUChar(delta);
10840663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(!epartIsReg(modrm)); /* ensured by caller */
10841663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(gregOfRexRM(pfx,modrm) == 2); /* ditto */
10842663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10843663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t64 = newTemp(Ity_I64);
10844663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp ew  = newTemp(Ity_I32);
10845663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10846663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
10847663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   delta += alen;
10848663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   DIP("%sldmxcsr %s\n",  isAvx ? "v" : "", dis_buf);
10849663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10850663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* The only thing we observe in %mxcsr is the rounding mode.
10851663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Therefore, pass the 32-bit value (SSE native-format control
10852663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      word) to a clean helper, getting back a 64-bit value, the
10853663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      lower half of which is the SSEROUND value to store, and the
10854663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      upper half of which is the emulation-warning token which may
10855663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      be generated.
10856663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   */
10857663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ULong amd64h_check_ldmxcsr ( ULong ); */
10858663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( t64, mkIRExprCCall(
10859663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   Ity_I64, 0/*regparms*/,
10860663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   "amd64g_check_ldmxcsr",
10861663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   &amd64g_check_ldmxcsr,
10862663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   mkIRExprVec_1(
10863663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      unop(Iop_32Uto64,
10864663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           loadLE(Ity_I32, mkexpr(addr))
10865663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      )
10866663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   )
10867663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                )
10868663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         );
10869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10870663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   put_sse_roundingmode( unop(Iop_64to32, mkexpr(t64)) );
10871663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( ew, unop(Iop_64HIto32, mkexpr(t64) ) );
10872663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   put_emwarn( mkexpr(ew) );
10873663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Finally, if an emulation warning was reported, side-exit to
10874663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      the next insn, reporting the warning, so that Valgrind's
10875663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      dispatcher sees the warning. */
10876663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   stmt(
10877663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRStmt_Exit(
10878663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         binop(Iop_CmpNE64, unop(Iop_32Uto64,mkexpr(ew)), mkU64(0)),
10879663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Ijk_EmWarn,
10880663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRConst_U64(guest_RIP_bbstart+delta),
10881663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         OFFB_RIP
10882663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      )
10883663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   );
10884663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
10885663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
10886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10888663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRTemp math_PINSRW_128 ( IRTemp v128, IRTemp u16, UInt imm8 )
10889663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
10890663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(imm8 >= 0 && imm8 <= 7);
10891663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10892663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // Create a V128 value which has the selected word in the
10893663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // specified lane, and zeroes everywhere else.
10894663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp tmp128    = newTemp(Ity_V128);
10895663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp halfshift = newTemp(Ity_I64);
10896663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(halfshift, binop(Iop_Shl64,
10897663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           unop(Iop_16Uto64, mkexpr(u16)),
10898663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           mkU8(16 * (imm8 & 3))));
10899663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (imm8 < 4) {
10900663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(tmp128, binop(Iop_64HLtoV128, mkU64(0), mkexpr(halfshift)));
10901663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
10902663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(tmp128, binop(Iop_64HLtoV128, mkexpr(halfshift), mkU64(0)));
10903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
10904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10905663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UShort mask = ~(3 << (imm8 * 2));
10906663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp res  = newTemp(Ity_V128);
10907663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( res, binop(Iop_OrV128,
10908663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      mkexpr(tmp128),
10909663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      binop(Iop_AndV128, mkexpr(v128), mkV128(mask))) );
10910663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return res;
10911663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
10912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10914663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRTemp math_PSADBW_128 ( IRTemp dV, IRTemp sV )
10915663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
10916663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp s1, s0, d1, d0;
10917663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   s1 = s0 = d1 = d0 = IRTemp_INVALID;
10918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10919663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV128to64s( sV, &s1, &s0 );
10920663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV128to64s( dV, &d1, &d0 );
10921663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10922663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp res = newTemp(Ity_V128);
10923663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( res,
10924663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           binop(Iop_64HLtoV128,
10925663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 mkIRExprCCall(Ity_I64, 0/*regparms*/,
10926663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               "amd64g_calculate_mmx_psadbw",
10927663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               &amd64g_calculate_mmx_psadbw,
10928663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               mkIRExprVec_2( mkexpr(s1), mkexpr(d1))),
10929663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 mkIRExprCCall(Ity_I64, 0/*regparms*/,
10930663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               "amd64g_calculate_mmx_psadbw",
10931663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               &amd64g_calculate_mmx_psadbw,
10932663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               mkIRExprVec_2( mkexpr(s0), mkexpr(d0)))) );
10933663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return res;
10934663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
10935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10937663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_MASKMOVDQU ( VexAbiInfo* vbi, Prefix pfx,
10938663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             Long delta, Bool isAvx )
10939663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
10940663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp regD    = newTemp(Ity_V128);
10941663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp mask    = newTemp(Ity_V128);
10942663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp olddata = newTemp(Ity_V128);
10943663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp newdata = newTemp(Ity_V128);
10944663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr    = newTemp(Ity_I64);
10945663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm   = getUChar(delta);
10946663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rG      = gregOfRexRM(pfx,modrm);
10947663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rE      = eregOfRexRM(pfx,modrm);
10948663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10949663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( addr, handleAddrOverrides( vbi, pfx, getIReg64(R_RDI) ));
10950663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( regD, getXMMReg( rG ));
10951663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10952663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Unfortunately can't do the obvious thing with SarN8x16
10953663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      here since that can't be re-emitted as SSE2 code - no such
10954663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      insn. */
10955663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( mask,
10956663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           binop(Iop_64HLtoV128,
10957663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 binop(Iop_SarN8x8,
10958663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       getXMMRegLane64( eregOfRexRM(pfx,modrm), 1 ),
10959663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       mkU8(7) ),
10960663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 binop(Iop_SarN8x8,
10961663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       getXMMRegLane64( eregOfRexRM(pfx,modrm), 0 ),
10962663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       mkU8(7) ) ));
10963663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( olddata, loadLE( Ity_V128, mkexpr(addr) ));
10964663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( newdata, binop(Iop_OrV128,
10965663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          binop(Iop_AndV128,
10966663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                mkexpr(regD),
10967663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                mkexpr(mask) ),
10968663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          binop(Iop_AndV128,
10969663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                mkexpr(olddata),
10970663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                unop(Iop_NotV128, mkexpr(mask)))) );
10971663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   storeLE( mkexpr(addr), mkexpr(newdata) );
10972663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10973663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   delta += 1;
10974663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   DIP("%smaskmovdqu %s,%s\n", isAvx ? "v" : "",
10975663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       nameXMMReg(rE), nameXMMReg(rG) );
10976663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
10977663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
10978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10980663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_MOVMSKPS_128 ( VexAbiInfo* vbi, Prefix pfx,
10981663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               Long delta, Bool isAvx )
10982663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
10983663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar modrm = getUChar(delta);
10984663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rG   = gregOfRexRM(pfx,modrm);
10985663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rE   = eregOfRexRM(pfx,modrm);
10986663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t0   = newTemp(Ity_I32);
10987663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t1   = newTemp(Ity_I32);
10988663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t2   = newTemp(Ity_I32);
10989663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t3   = newTemp(Ity_I32);
10990663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   delta += 1;
10991663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( t0, binop( Iop_And32,
10992663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      binop(Iop_Shr32, getXMMRegLane32(rE,0), mkU8(31)),
10993663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      mkU32(1) ));
10994663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( t1, binop( Iop_And32,
10995663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      binop(Iop_Shr32, getXMMRegLane32(rE,1), mkU8(30)),
10996663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      mkU32(2) ));
10997663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( t2, binop( Iop_And32,
10998663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      binop(Iop_Shr32, getXMMRegLane32(rE,2), mkU8(29)),
10999663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      mkU32(4) ));
11000663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( t3, binop( Iop_And32,
11001663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      binop(Iop_Shr32, getXMMRegLane32(rE,3), mkU8(28)),
11002663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      mkU32(8) ));
11003663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putIReg32( rG, binop(Iop_Or32,
11004663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
11005663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        binop(Iop_Or32, mkexpr(t2), mkexpr(t3)) ) );
11006663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   DIP("%smovmskps %s,%s\n", isAvx ? "v" : "",
11007663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       nameXMMReg(rE), nameIReg32(rG));
11008663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
11009663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
11010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11012663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_MOVMSKPS_256 ( VexAbiInfo* vbi, Prefix pfx, Long delta )
11013663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
11014663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar modrm = getUChar(delta);
11015663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rG   = gregOfRexRM(pfx,modrm);
11016663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rE   = eregOfRexRM(pfx,modrm);
11017663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t0   = newTemp(Ity_I32);
11018663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t1   = newTemp(Ity_I32);
11019663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t2   = newTemp(Ity_I32);
11020663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t3   = newTemp(Ity_I32);
11021663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t4   = newTemp(Ity_I32);
11022663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t5   = newTemp(Ity_I32);
11023663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t6   = newTemp(Ity_I32);
11024663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t7   = newTemp(Ity_I32);
11025663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   delta += 1;
11026663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( t0, binop( Iop_And32,
11027663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      binop(Iop_Shr32, getYMMRegLane32(rE,0), mkU8(31)),
11028663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      mkU32(1) ));
11029663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( t1, binop( Iop_And32,
11030663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      binop(Iop_Shr32, getYMMRegLane32(rE,1), mkU8(30)),
11031663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      mkU32(2) ));
11032663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( t2, binop( Iop_And32,
11033663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      binop(Iop_Shr32, getYMMRegLane32(rE,2), mkU8(29)),
11034663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      mkU32(4) ));
11035663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( t3, binop( Iop_And32,
11036663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      binop(Iop_Shr32, getYMMRegLane32(rE,3), mkU8(28)),
11037663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      mkU32(8) ));
11038663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( t4, binop( Iop_And32,
11039663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      binop(Iop_Shr32, getYMMRegLane32(rE,4), mkU8(27)),
11040663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      mkU32(16) ));
11041663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( t5, binop( Iop_And32,
11042663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      binop(Iop_Shr32, getYMMRegLane32(rE,5), mkU8(26)),
11043663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      mkU32(32) ));
11044663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( t6, binop( Iop_And32,
11045663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      binop(Iop_Shr32, getYMMRegLane32(rE,6), mkU8(25)),
11046663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      mkU32(64) ));
11047663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( t7, binop( Iop_And32,
11048663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      binop(Iop_Shr32, getYMMRegLane32(rE,7), mkU8(24)),
11049663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      mkU32(128) ));
11050663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putIReg32( rG, binop(Iop_Or32,
11051663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        binop(Iop_Or32,
11052663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
11053663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              binop(Iop_Or32, mkexpr(t2), mkexpr(t3)) ),
11054663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        binop(Iop_Or32,
11055663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              binop(Iop_Or32, mkexpr(t4), mkexpr(t5)),
11056663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              binop(Iop_Or32, mkexpr(t6), mkexpr(t7)) ) ) );
11057663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   DIP("vmovmskps %s,%s\n", nameYMMReg(rE), nameIReg32(rG));
11058663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
11059663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
11060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11062663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_MOVMSKPD_128 ( VexAbiInfo* vbi, Prefix pfx,
11063663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               Long delta, Bool isAvx )
11064663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
11065663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar modrm = getUChar(delta);
11066663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rG   = gregOfRexRM(pfx,modrm);
11067663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rE   = eregOfRexRM(pfx,modrm);
11068663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t0   = newTemp(Ity_I32);
11069663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t1   = newTemp(Ity_I32);
11070663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   delta += 1;
11071663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( t0, binop( Iop_And32,
11072663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      binop(Iop_Shr32, getXMMRegLane32(rE,1), mkU8(31)),
11073663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      mkU32(1) ));
11074663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( t1, binop( Iop_And32,
11075663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      binop(Iop_Shr32, getXMMRegLane32(rE,3), mkU8(30)),
11076663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      mkU32(2) ));
11077663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putIReg32( rG, binop(Iop_Or32, mkexpr(t0), mkexpr(t1) ) );
11078663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   DIP("%smovmskpd %s,%s\n", isAvx ? "v" : "",
11079663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       nameXMMReg(rE), nameIReg32(rG));
11080663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
11081663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
11082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11084663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_MOVMSKPD_256 ( VexAbiInfo* vbi, Prefix pfx, Long delta )
11085663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
11086663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar modrm = getUChar(delta);
11087663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rG   = gregOfRexRM(pfx,modrm);
11088663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rE   = eregOfRexRM(pfx,modrm);
11089663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t0   = newTemp(Ity_I32);
11090663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t1   = newTemp(Ity_I32);
11091663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t2   = newTemp(Ity_I32);
11092663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t3   = newTemp(Ity_I32);
11093663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   delta += 1;
11094663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( t0, binop( Iop_And32,
11095663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      binop(Iop_Shr32, getYMMRegLane32(rE,1), mkU8(31)),
11096663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      mkU32(1) ));
11097663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( t1, binop( Iop_And32,
11098663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      binop(Iop_Shr32, getYMMRegLane32(rE,3), mkU8(30)),
11099663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      mkU32(2) ));
11100663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( t2, binop( Iop_And32,
11101663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      binop(Iop_Shr32, getYMMRegLane32(rE,5), mkU8(29)),
11102663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      mkU32(4) ));
11103663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( t3, binop( Iop_And32,
11104663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      binop(Iop_Shr32, getYMMRegLane32(rE,7), mkU8(28)),
11105663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      mkU32(8) ));
11106663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putIReg32( rG, binop(Iop_Or32,
11107663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
11108663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        binop(Iop_Or32, mkexpr(t2), mkexpr(t3)) ) );
11109663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   DIP("vmovmskps %s,%s\n", nameYMMReg(rE), nameIReg32(rG));
11110663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
11111663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
11112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11114663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Note, this also handles SSE(1) insns. */
11115663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng__attribute__((noinline))
11116663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic
11117663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengLong dis_ESC_0F__SSE2 ( Bool* decode_OK,
11118663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        VexAbiInfo* vbi,
11119663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        Prefix pfx, Int sz, Long deltaIN,
11120663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        DisResult* dres )
11121663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
11122663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr  = IRTemp_INVALID;
11123663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t0    = IRTemp_INVALID;
11124663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t1    = IRTemp_INVALID;
11125663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t2    = IRTemp_INVALID;
11126663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t3    = IRTemp_INVALID;
11127663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t4    = IRTemp_INVALID;
11128663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t5    = IRTemp_INVALID;
11129663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t6    = IRTemp_INVALID;
11130663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm = 0;
11131663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen  = 0;
11132663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
11133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11134663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *decode_OK = False;
11135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11136663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Long   delta = deltaIN;
11137663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  opc   = getUChar(delta);
11138663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   delta++;
11139663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (opc) {
11140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11141663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x10:
11142663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
11143663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (sz == 2 || /* ignore redundant REX.W */ sz == 8)) {
11144663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* 66 0F 10 = MOVUPD -- move from E (mem or xmm) to G (xmm). */
11145663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
11146663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
11147663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putXMMReg( gregOfRexRM(pfx,modrm),
11148663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       getXMMReg( eregOfRexRM(pfx,modrm) ));
11149663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movupd %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)),
11150663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  nameXMMReg(gregOfRexRM(pfx,modrm)));
11151663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
11152663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
11153663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
11154663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putXMMReg( gregOfRexRM(pfx,modrm),
11155663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       loadLE(Ity_V128, mkexpr(addr)) );
11156663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movupd %s,%s\n", dis_buf,
11157663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  nameXMMReg(gregOfRexRM(pfx,modrm)));
11158663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
11159663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
11160663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
11161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11162663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F2 0F 10 = MOVSD -- move 64 bits from E (mem or lo half xmm) to
11163663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         G (lo half xmm).  If E is mem, upper half of G is zeroed out.
11164663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         If E is reg, upper half of G is unchanged. */
11165663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2no66noF3(pfx)
11166663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (sz == 4 || /* ignore redundant REX.W */ sz == 8) ) {
11167663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
11168663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
11169663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putXMMRegLane64( gregOfRexRM(pfx,modrm), 0,
11170663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             getXMMRegLane64( eregOfRexRM(pfx,modrm), 0 ));
11171663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movsd %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)),
11172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 nameXMMReg(gregOfRexRM(pfx,modrm)));
11173663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
11174663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
11175663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
11176663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putXMMReg( gregOfRexRM(pfx,modrm), mkV128(0) );
11177663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putXMMRegLane64( gregOfRexRM(pfx,modrm), 0,
11178663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             loadLE(Ity_I64, mkexpr(addr)) );
11179663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movsd %s,%s\n", dis_buf,
11180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 nameXMMReg(gregOfRexRM(pfx,modrm)));
11181663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
11182663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
11183663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
11184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11185663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F3 0F 10 = MOVSS -- move 32 bits from E (mem or lo 1/4 xmm) to G
11186663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         (lo 1/4 xmm).  If E is mem, upper 3/4 of G is zeroed out. */
11187663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx)
11188663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (sz == 4 || /* ignore redundant REX.W */ sz == 8)) {
11189663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
11190663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
11191663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putXMMRegLane32( gregOfRexRM(pfx,modrm), 0,
11192663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             getXMMRegLane32( eregOfRexRM(pfx,modrm), 0 ));
11193663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movss %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)),
11194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 nameXMMReg(gregOfRexRM(pfx,modrm)));
11195663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
11196663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
11197663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
11198663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putXMMReg( gregOfRexRM(pfx,modrm), mkV128(0) );
11199663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putXMMRegLane32( gregOfRexRM(pfx,modrm), 0,
11200663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             loadLE(Ity_I32, mkexpr(addr)) );
11201663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movss %s,%s\n", dis_buf,
11202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 nameXMMReg(gregOfRexRM(pfx,modrm)));
11203663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
11204663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
11205663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
11206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11207663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 10 = MOVUPS -- move from E (mem or xmm) to G (xmm). */
11208663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx)
11209663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (sz == 4 || /* ignore redundant REX.W */ sz == 8)) {
11210663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
11211663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
11212663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putXMMReg( gregOfRexRM(pfx,modrm),
11213663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       getXMMReg( eregOfRexRM(pfx,modrm) ));
11214663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movups %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)),
11215663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  nameXMMReg(gregOfRexRM(pfx,modrm)));
11216663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
11217663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
11218663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
11219663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putXMMReg( gregOfRexRM(pfx,modrm),
11220663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       loadLE(Ity_V128, mkexpr(addr)) );
11221663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movups %s,%s\n", dis_buf,
11222663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                     nameXMMReg(gregOfRexRM(pfx,modrm)));
11223663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
11224663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
11225663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
11226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11227663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
11228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11229663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x11:
11230663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F2 0F 11 = MOVSD -- move 64 bits from G (lo half xmm) to E (mem
11231663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         or lo half xmm). */
11232663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2no66noF3(pfx)
11233663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (sz == 4 || /* ignore redundant REX.W */ sz == 8)) {
11234663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
11235663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
11236663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putXMMRegLane64( eregOfRexRM(pfx,modrm), 0,
11237663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             getXMMRegLane64( gregOfRexRM(pfx,modrm), 0 ));
11238663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movsd %s,%s\n", nameXMMReg(gregOfRexRM(pfx,modrm)),
11239663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                 nameXMMReg(eregOfRexRM(pfx,modrm)));
11240663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
11241663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
11242663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
11243663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            storeLE( mkexpr(addr),
11244663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     getXMMRegLane64(gregOfRexRM(pfx,modrm), 0) );
11245663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movsd %s,%s\n", nameXMMReg(gregOfRexRM(pfx,modrm)),
11246663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                 dis_buf);
11247663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
11248663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
11249663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
11250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11251663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F3 0F 11 = MOVSS -- move 32 bits from G (lo 1/4 xmm) to E (mem
11252663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         or lo 1/4 xmm). */
11253663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx) && sz == 4) {
11254663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
11255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (epartIsReg(modrm)) {
11256663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* fall through, we don't yet have a test case */
11257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
11258663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
11259663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            storeLE( mkexpr(addr),
11260663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     getXMMRegLane32(gregOfRexRM(pfx,modrm), 0) );
11261663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movss %s,%s\n", nameXMMReg(gregOfRexRM(pfx,modrm)),
11262663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                 dis_buf);
11263663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
11264663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            goto decode_success;
11265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
11266663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
11267663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 11 = MOVUPD -- move from G (xmm) to E (mem or xmm). */
11268663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
11269663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (sz == 2 || /* ignore redundant REX.W */ sz == 8)) {
11270663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
11271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (epartIsReg(modrm)) {
11272663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putXMMReg( eregOfRexRM(pfx,modrm),
11273663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   		    getXMMReg( gregOfRexRM(pfx,modrm) ) );
11274663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movupd %s,%s\n", nameXMMReg(gregOfRexRM(pfx,modrm)),
11275663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   	                       nameXMMReg(eregOfRexRM(pfx,modrm)));
11276663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
11277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
11278663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
11279663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            storeLE( mkexpr(addr), getXMMReg(gregOfRexRM(pfx,modrm)) );
11280663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movupd %s,%s\n", nameXMMReg(gregOfRexRM(pfx,modrm)),
11281663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  dis_buf );
11282663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
11283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
11284663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
11285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11286663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 11 = MOVUPS -- move from G (xmm) to E (mem or xmm). */
11287663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx)
11288663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (sz == 4 || /* ignore redundant REX.W */ sz == 8)) {
11289663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
11290663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
11291663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* fall through; awaiting test case */
11292663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
11293663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
11294663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            storeLE( mkexpr(addr), getXMMReg(gregOfRexRM(pfx,modrm)) );
11295663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movups %s,%s\n", nameXMMReg(gregOfRexRM(pfx,modrm)),
11296663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  dis_buf );
11297663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
11298663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            goto decode_success;
11299663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
11300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11301663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
11302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11303663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x12:
11304663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 12 = MOVLPD -- move from mem to low half of XMM. */
11305663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Identical to MOVLPS ? */
11306663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
11307663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (sz == 2 || /* ignore redundant REX.W */ sz == 8)) {
11308663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
11309663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
11310663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* fall through; apparently reg-reg is not possible */
11311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
11312663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
11313663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
11314663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putXMMRegLane64( gregOfRexRM(pfx,modrm),
11315663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             0/*lower lane*/,
11316663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             loadLE(Ity_I64, mkexpr(addr)) );
11317663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movlpd %s, %s\n",
11318663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                dis_buf, nameXMMReg( gregOfRexRM(pfx,modrm) ));
11319663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            goto decode_success;
11320663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
11321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11322663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 12 = MOVLPS -- move from mem to low half of XMM. */
11323663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* OF 12 = MOVHLPS -- from from hi half to lo half of XMM. */
11324663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx)
11325663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (sz == 4 || /* ignore redundant REX.W */ sz == 8)) {
11326663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
11327663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
11328663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
11329663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putXMMRegLane64( gregOfRexRM(pfx,modrm),
11330663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             0/*lower lane*/,
11331663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             getXMMRegLane64( eregOfRexRM(pfx,modrm), 1 ));
11332663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movhlps %s, %s\n", nameXMMReg(eregOfRexRM(pfx,modrm)),
11333663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    nameXMMReg(gregOfRexRM(pfx,modrm)));
11334663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
11335663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
11336663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
11337663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putXMMRegLane64( gregOfRexRM(pfx,modrm),  0/*lower lane*/,
11338663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             loadLE(Ity_I64, mkexpr(addr)) );
11339663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movlps %s, %s\n",
11340663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                dis_buf, nameXMMReg( gregOfRexRM(pfx,modrm) ));
11341663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
11342663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
11343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11344663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
11345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11346663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x13:
11347663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 13 = MOVLPS -- move from low half of XMM to mem. */
11348663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx)
11349663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (sz == 4 || /* ignore redundant REX.W */ sz == 8)) {
11350663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
11351663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (!epartIsReg(modrm)) {
11352663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
11353663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
11354663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            storeLE( mkexpr(addr),
11355663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     getXMMRegLane64( gregOfRexRM(pfx,modrm),
11356663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                      0/*lower lane*/ ) );
11357663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movlps %s, %s\n", nameXMMReg( gregOfRexRM(pfx,modrm) ),
11358663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   dis_buf);
11359663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            goto decode_success;
11360663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
11361663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* else fall through */
11362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11363663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 13 = MOVLPD -- move from low half of XMM to mem. */
11364663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Identical to MOVLPS ? */
11365663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
11366663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (sz == 2 || /* ignore redundant REX.W */ sz == 8)) {
11367663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
11368663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (!epartIsReg(modrm)) {
11369663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
11370663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
11371663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            storeLE( mkexpr(addr),
11372663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     getXMMRegLane64( gregOfRexRM(pfx,modrm),
11373663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                      0/*lower lane*/ ) );
11374663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movlpd %s, %s\n", nameXMMReg( gregOfRexRM(pfx,modrm) ),
11375663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   dis_buf);
11376663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            goto decode_success;
11377663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
11378663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* else fall through */
11379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11380663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
11381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11382663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x14:
11383663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x15:
11384663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 14 = UNPCKLPS -- unpack and interleave low part F32s */
11385663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 15 = UNPCKHPS -- unpack and interleave high part F32s */
11386663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* These just appear to be special cases of SHUFPS */
11387663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && sz == 4) {
11388663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Bool   hi = toBool(opc == 0x15);
11389663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sV = newTemp(Ity_V128);
11390663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dV = newTemp(Ity_V128);
11391663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
11392663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG = gregOfRexRM(pfx,modrm);
11393663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( dV, getXMMReg(rG) );
11394663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
11395663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
11396663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, getXMMReg(rE) );
11397663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
11398663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("unpck%sps %s,%s\n", hi ? "h" : "l",
11399663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                nameXMMReg(rE), nameXMMReg(rG));
11400663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
11401663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
11402663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
11403663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
11404663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("unpck%sps %s,%s\n", hi ? "h" : "l",
11405663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                dis_buf, nameXMMReg(rG));
11406663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
11407663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp res = math_UNPCKxPS_128( sV, dV, hi );
11408663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMReg( rG, mkexpr(res) );
11409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
11410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11411663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 15 = UNPCKHPD -- unpack and interleave high part F64s */
11412663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 14 = UNPCKLPD -- unpack and interleave low part F64s */
11413663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* These just appear to be special cases of SHUFPS */
11414663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
11415663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && sz == 2 /* could be 8 if rex also present */) {
11416663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Bool   hi = toBool(opc == 0x15);
11417663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sV = newTemp(Ity_V128);
11418663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dV = newTemp(Ity_V128);
11419663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
11420663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG = gregOfRexRM(pfx,modrm);
11421663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( dV, getXMMReg(rG) );
11422663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
11423663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
11424663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, getXMMReg(rE) );
11425663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
11426663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("unpck%sps %s,%s\n", hi ? "h" : "l",
11427663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                nameXMMReg(rE), nameXMMReg(rG));
11428663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
11429663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
11430663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
11431663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
11432663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("unpck%sps %s,%s\n", hi ? "h" : "l",
11433663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                dis_buf, nameXMMReg(rG));
11434663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
11435663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp res = math_UNPCKxPD_128( sV, dV, hi );
11436663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMReg( rG, mkexpr(res) );
11437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
11438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11439663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
11440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11441663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x16:
11442663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 16 = MOVHPD -- move from mem to high half of XMM. */
11443663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* These seems identical to MOVHPS.  This instruction encoding is
11444663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         completely crazy. */
11445663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
11446663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (sz == 2 || /* ignore redundant REX.W */ sz == 8)) {
11447663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
11448663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
11449663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* fall through; apparently reg-reg is not possible */
11450663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
11451663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
11452663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
11453663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putXMMRegLane64( gregOfRexRM(pfx,modrm), 1/*upper lane*/,
11454663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             loadLE(Ity_I64, mkexpr(addr)) );
11455663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movhpd %s,%s\n", dis_buf,
11456663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  nameXMMReg( gregOfRexRM(pfx,modrm) ));
11457663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            goto decode_success;
11458663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
11459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11460663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 16 = MOVHPS -- move from mem to high half of XMM. */
11461663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 16 = MOVLHPS -- move from lo half to hi half of XMM. */
11462663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx)
11463663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (sz == 4 || /* ignore redundant REX.W */ sz == 8)) {
11464663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
11465663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
11466663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
11467663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putXMMRegLane64( gregOfRexRM(pfx,modrm), 1/*upper lane*/,
11468663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             getXMMRegLane64( eregOfRexRM(pfx,modrm), 0 ) );
11469663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movhps %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)),
11470663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  nameXMMReg(gregOfRexRM(pfx,modrm)));
11471663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
11472663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
11473663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
11474663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putXMMRegLane64( gregOfRexRM(pfx,modrm), 1/*upper lane*/,
11475663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             loadLE(Ity_I64, mkexpr(addr)) );
11476663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movhps %s,%s\n", dis_buf,
11477663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  nameXMMReg( gregOfRexRM(pfx,modrm) ));
11478663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
11479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
11480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11481663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
11482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11483663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x17:
11484663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 17 = MOVHPS -- move from high half of XMM to mem. */
11485663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx)
11486663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (sz == 4 || /* ignore redundant REX.W */ sz == 8)) {
11487663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
11488663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (!epartIsReg(modrm)) {
11489663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
11490663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
11491663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            storeLE( mkexpr(addr),
11492663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     getXMMRegLane64( gregOfRexRM(pfx,modrm),
11493663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                      1/*upper lane*/ ) );
11494663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movhps %s,%s\n", nameXMMReg( gregOfRexRM(pfx,modrm) ),
11495663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  dis_buf);
11496663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            goto decode_success;
11497663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
11498663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* else fall through */
11499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11500663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 17 = MOVHPD -- move from high half of XMM to mem. */
11501663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Again, this seems identical to MOVHPS. */
11502663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
11503663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (sz == 2 || /* ignore redundant REX.W */ sz == 8)) {
11504663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
11505663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (!epartIsReg(modrm)) {
11506663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
11507663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
11508663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            storeLE( mkexpr(addr),
11509663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     getXMMRegLane64( gregOfRexRM(pfx,modrm),
11510663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                      1/*upper lane*/ ) );
11511663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movhpd %s,%s\n", nameXMMReg( gregOfRexRM(pfx,modrm) ),
11512663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  dis_buf);
11513663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            goto decode_success;
11514663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
11515663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* else fall through */
11516663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
11517663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
11518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11519663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x18:
11520663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 18 /0 = PREFETCHNTA -- prefetch into caches, */
11521663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 18 /1 = PREFETCH0   -- with various different hints */
11522663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 18 /2 = PREFETCH1 */
11523663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 18 /3 = PREFETCH2 */
11524663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx)
11525663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && !epartIsReg(getUChar(delta))
11526663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && gregLO3ofRM(getUChar(delta)) >= 0
11527663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && gregLO3ofRM(getUChar(delta)) <= 3) {
11528663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HChar* hintstr = "??";
11529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11530663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
11531663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(!epartIsReg(modrm));
11532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11533663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
11534663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta += alen;
11535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11536663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         switch (gregLO3ofRM(modrm)) {
11537663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 0: hintstr = "nta"; break;
11538663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 1: hintstr = "t0"; break;
11539663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 2: hintstr = "t1"; break;
11540663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 3: hintstr = "t2"; break;
11541663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            default: vassert(0);
11542663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
11543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11544663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("prefetch%s %s\n", hintstr, dis_buf);
11545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
11546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11547663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
11548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11549663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x28:
11550663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 28 = MOVAPD -- move from E (mem or xmm) to G (xmm). */
11551663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
11552663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (sz == 2 || /* ignore redundant REX.W */ sz == 8)) {
11553663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
11554663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
11555663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putXMMReg( gregOfRexRM(pfx,modrm),
11556663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       getXMMReg( eregOfRexRM(pfx,modrm) ));
11557663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movapd %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)),
11558663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  nameXMMReg(gregOfRexRM(pfx,modrm)));
11559663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
11560663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
11561663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
11562663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gen_SEGV_if_not_16_aligned( addr );
11563663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putXMMReg( gregOfRexRM(pfx,modrm),
11564663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       loadLE(Ity_V128, mkexpr(addr)) );
11565663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movapd %s,%s\n", dis_buf,
11566663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  nameXMMReg(gregOfRexRM(pfx,modrm)));
11567663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
11568663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
11569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
11570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11571663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 28 = MOVAPS -- move from E (mem or xmm) to G (xmm). */
11572663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx)
11573663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (sz == 4 || /* ignore redundant REX.W */ sz == 8)) {
11574663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
11575663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
11576663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putXMMReg( gregOfRexRM(pfx,modrm),
11577663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       getXMMReg( eregOfRexRM(pfx,modrm) ));
11578663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movaps %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)),
11579663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  nameXMMReg(gregOfRexRM(pfx,modrm)));
11580663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
11581663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
11582663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
11583663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gen_SEGV_if_not_16_aligned( addr );
11584663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putXMMReg( gregOfRexRM(pfx,modrm),
11585663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       loadLE(Ity_V128, mkexpr(addr)) );
11586663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movaps %s,%s\n", dis_buf,
11587663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  nameXMMReg(gregOfRexRM(pfx,modrm)));
11588663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
11589663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
11590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
11591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11592663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
11593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11594663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x29:
11595663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 29 = MOVAPS -- move from G (xmm) to E (mem or xmm). */
11596663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx)
11597663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (sz == 4 || /* ignore redundant REX.W */ sz == 8)) {
11598663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
11599663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
11600663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* fall through; awaiting test case */
11601663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putXMMReg( eregOfRexRM(pfx,modrm),
11602663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       getXMMReg( gregOfRexRM(pfx,modrm) ));
11603663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movaps %s,%s\n", nameXMMReg(gregOfRexRM(pfx,modrm)),
11604663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  nameXMMReg(eregOfRexRM(pfx,modrm)));
11605663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
11606663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
11607663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
11608663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gen_SEGV_if_not_16_aligned( addr );
11609663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            storeLE( mkexpr(addr), getXMMReg(gregOfRexRM(pfx,modrm)) );
11610663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movaps %s,%s\n", nameXMMReg(gregOfRexRM(pfx,modrm)),
11611663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  dis_buf );
11612663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
11613663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
11614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
11615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11616663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 29 = MOVAPD -- move from G (xmm) to E (mem or xmm). */
11617663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
11618663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (sz == 2 || /* ignore redundant REX.W */ sz == 8)) {
11619663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
11620663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
11621663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putXMMReg( eregOfRexRM(pfx,modrm),
11622663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   		    getXMMReg( gregOfRexRM(pfx,modrm) ) );
11623663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movapd %s,%s\n", nameXMMReg(gregOfRexRM(pfx,modrm)),
11624663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   	                       nameXMMReg(eregOfRexRM(pfx,modrm)));
11625663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
11626663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
11627663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
11628663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gen_SEGV_if_not_16_aligned( addr );
11629663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            storeLE( mkexpr(addr), getXMMReg(gregOfRexRM(pfx,modrm)) );
11630663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movapd %s,%s\n", nameXMMReg(gregOfRexRM(pfx,modrm)),
11631663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  dis_buf );
11632663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
11633663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
11634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
11635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11636663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
11637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11638663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x2A:
11639663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 2A = CVTPI2PS -- convert 2 x I32 in mem/mmx to 2 x F32 in low
11640663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         half xmm */
11641663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && sz == 4) {
11642663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp arg64 = newTemp(Ity_I64);
11643663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp rmode = newTemp(Ity_I32);
11644663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
11645663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
11646663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         do_MMX_preamble();
11647663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
11648663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( arg64, getMMXReg(eregLO3ofRM(modrm)) );
11649663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
11650663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("cvtpi2ps %s,%s\n", nameMMXReg(eregLO3ofRM(modrm)),
11651663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    nameXMMReg(gregOfRexRM(pfx,modrm)));
11652663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
11653663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
11654663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( arg64, loadLE(Ity_I64, mkexpr(addr)) );
11655663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
11656663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("cvtpi2ps %s,%s\n", dis_buf,
11657663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    nameXMMReg(gregOfRexRM(pfx,modrm)) );
11658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
11659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11660663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( rmode, get_sse_roundingmode() );
11661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11662663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMRegLane32F(
11663663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gregOfRexRM(pfx,modrm), 0,
11664663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            binop(Iop_F64toF32,
11665663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  mkexpr(rmode),
11666663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  unop(Iop_I32StoF64,
11667663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       unop(Iop_64to32, mkexpr(arg64)) )) );
11668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11669663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMRegLane32F(
11670663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gregOfRexRM(pfx,modrm), 1,
11671663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            binop(Iop_F64toF32,
11672663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  mkexpr(rmode),
11673663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  unop(Iop_I32StoF64,
11674663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       unop(Iop_64HIto32, mkexpr(arg64)) )) );
11675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11676663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
11677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11678663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F3 0F 2A = CVTSI2SS
11679663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         -- sz==4: convert I32 in mem/ireg to F32 in low quarter xmm
11680663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         -- sz==8: convert I64 in mem/ireg to F32 in low quarter xmm */
11681663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx) && (sz == 4 || sz == 8)) {
11682663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp rmode = newTemp(Ity_I32);
11683663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( rmode, get_sse_roundingmode() );
11684663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
11685663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (sz == 4) {
11686663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            IRTemp arg32 = newTemp(Ity_I32);
11687663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (epartIsReg(modrm)) {
11688663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               assign( arg32, getIReg32(eregOfRexRM(pfx,modrm)) );
11689663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               delta += 1;
11690663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               DIP("cvtsi2ss %s,%s\n", nameIReg32(eregOfRexRM(pfx,modrm)),
11691663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                       nameXMMReg(gregOfRexRM(pfx,modrm)));
11692663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            } else {
11693663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
11694663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               assign( arg32, loadLE(Ity_I32, mkexpr(addr)) );
11695663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               delta += alen;
11696663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               DIP("cvtsi2ss %s,%s\n", dis_buf,
11697663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                       nameXMMReg(gregOfRexRM(pfx,modrm)) );
11698663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            }
11699663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putXMMRegLane32F(
11700663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               gregOfRexRM(pfx,modrm), 0,
11701663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               binop(Iop_F64toF32,
11702663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     mkexpr(rmode),
11703663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     unop(Iop_I32StoF64, mkexpr(arg32)) ) );
11704663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
11705663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* sz == 8 */
11706663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            IRTemp arg64 = newTemp(Ity_I64);
11707663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (epartIsReg(modrm)) {
11708663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               assign( arg64, getIReg64(eregOfRexRM(pfx,modrm)) );
11709663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               delta += 1;
11710663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               DIP("cvtsi2ssq %s,%s\n", nameIReg64(eregOfRexRM(pfx,modrm)),
11711663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        nameXMMReg(gregOfRexRM(pfx,modrm)));
11712663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            } else {
11713663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
11714663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               assign( arg64, loadLE(Ity_I64, mkexpr(addr)) );
11715663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               delta += alen;
11716663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               DIP("cvtsi2ssq %s,%s\n", dis_buf,
11717663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        nameXMMReg(gregOfRexRM(pfx,modrm)) );
11718663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            }
11719663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putXMMRegLane32F(
11720663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               gregOfRexRM(pfx,modrm), 0,
11721663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               binop(Iop_F64toF32,
11722663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     mkexpr(rmode),
11723663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     binop(Iop_I64StoF64, mkexpr(rmode), mkexpr(arg64)) ) );
11724663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
11725663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
11726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11727663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F2 0F 2A = CVTSI2SD
11728663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         when sz==4 -- convert I32 in mem/ireg to F64 in low half xmm
11729663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         when sz==8 -- convert I64 in mem/ireg to F64 in low half xmm
11730663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      */
11731663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2no66noF3(pfx) && (sz == 4 || sz == 8)) {
11732663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
11733663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (sz == 4) {
11734663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            IRTemp arg32 = newTemp(Ity_I32);
11735663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (epartIsReg(modrm)) {
11736663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               assign( arg32, getIReg32(eregOfRexRM(pfx,modrm)) );
11737663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               delta += 1;
11738663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               DIP("cvtsi2sdl %s,%s\n", nameIReg32(eregOfRexRM(pfx,modrm)),
11739663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        nameXMMReg(gregOfRexRM(pfx,modrm)));
11740663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            } else {
11741663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
11742663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               assign( arg32, loadLE(Ity_I32, mkexpr(addr)) );
11743663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               delta += alen;
11744663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               DIP("cvtsi2sdl %s,%s\n", dis_buf,
11745663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        nameXMMReg(gregOfRexRM(pfx,modrm)) );
11746663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            }
11747663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putXMMRegLane64F( gregOfRexRM(pfx,modrm), 0,
11748663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              unop(Iop_I32StoF64, mkexpr(arg32))
11749663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            );
11750663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
11751663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* sz == 8 */
11752663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            IRTemp arg64 = newTemp(Ity_I64);
11753663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (epartIsReg(modrm)) {
11754663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               assign( arg64, getIReg64(eregOfRexRM(pfx,modrm)) );
11755663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               delta += 1;
11756663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               DIP("cvtsi2sdq %s,%s\n", nameIReg64(eregOfRexRM(pfx,modrm)),
11757663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        nameXMMReg(gregOfRexRM(pfx,modrm)));
11758663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            } else {
11759663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
11760663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               assign( arg64, loadLE(Ity_I64, mkexpr(addr)) );
11761663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               delta += alen;
11762663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               DIP("cvtsi2sdq %s,%s\n", dis_buf,
11763663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        nameXMMReg(gregOfRexRM(pfx,modrm)) );
11764663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            }
11765663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putXMMRegLane64F(
11766663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               gregOfRexRM(pfx,modrm),
11767663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               0,
11768663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               binop( Iop_I64StoF64,
11769663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      get_sse_roundingmode(),
11770663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      mkexpr(arg64)
11771663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               )
11772663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            );
11773663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
11774663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
11775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11776663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 2A = CVTPI2PD -- convert 2 x I32 in mem/mmx to 2 x F64 in
11777663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         xmm(G) */
11778663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
11779663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp arg64 = newTemp(Ity_I64);
11780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11781663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
11782663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
11783663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* Only switch to MMX mode if the source is a MMX register.
11784663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               This is inconsistent with all other instructions which
11785663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               convert between XMM and (M64 or MMX), which always switch
11786663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               to MMX mode even if 64-bit operand is M64 and not MMX.  At
11787663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               least, that's what the Intel docs seem to me to say.
11788663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               Fixes #210264. */
11789663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            do_MMX_preamble();
11790663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( arg64, getMMXReg(eregLO3ofRM(modrm)) );
11791663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
11792663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("cvtpi2pd %s,%s\n", nameMMXReg(eregLO3ofRM(modrm)),
11793663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    nameXMMReg(gregOfRexRM(pfx,modrm)));
11794663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
11795663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
11796663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( arg64, loadLE(Ity_I64, mkexpr(addr)) );
11797663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
11798663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("cvtpi2pd %s,%s\n", dis_buf,
11799663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    nameXMMReg(gregOfRexRM(pfx,modrm)) );
11800663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
11801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11802663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMRegLane64F(
11803663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gregOfRexRM(pfx,modrm), 0,
11804663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            unop(Iop_I32StoF64, unop(Iop_64to32, mkexpr(arg64)) )
11805663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         );
11806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11807663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMRegLane64F(
11808663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gregOfRexRM(pfx,modrm), 1,
11809663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            unop(Iop_I32StoF64, unop(Iop_64HIto32, mkexpr(arg64)) )
11810663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         );
11811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11812663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
11813663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
11814663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
11815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11816663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x2B:
11817663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 2B = MOVNTPD -- for us, just a plain SSE store. */
11818663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 2B = MOVNTPS -- for us, just a plain SSE store. */
11819663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if ( (haveNo66noF2noF3(pfx) && sz == 4)
11820663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           || (have66noF2noF3(pfx) && sz == 2) ) {
11821663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
11822663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (!epartIsReg(modrm)) {
11823663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
11824663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gen_SEGV_if_not_16_aligned( addr );
11825663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            storeLE( mkexpr(addr), getXMMReg(gregOfRexRM(pfx,modrm)) );
11826663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movntp%s %s,%s\n", sz==2 ? "d" : "s",
11827663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    dis_buf,
11828663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    nameXMMReg(gregOfRexRM(pfx,modrm)));
11829663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
11830663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            goto decode_success;
11831663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
11832663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* else fall through */
11833663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
11834663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
11835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11836663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x2C:
11837663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x2D:
11838663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 2D = CVTPS2PI -- convert 2 x F32 in mem/low half xmm to 2 x
11839663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         I32 in mmx, according to prevailing SSE rounding mode */
11840663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 2C = CVTTPS2PI -- convert 2 x F32 in mem/low half xmm to 2 x
11841663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         I32 in mmx, rounding towards zero */
11842663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && sz == 4) {
11843663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dst64  = newTemp(Ity_I64);
11844663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp rmode  = newTemp(Ity_I32);
11845663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp f32lo  = newTemp(Ity_F32);
11846663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp f32hi  = newTemp(Ity_F32);
11847663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Bool   r2zero = toBool(opc == 0x2C);
11848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11849663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         do_MMX_preamble();
11850663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
11851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11852663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
11853663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
11854663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(f32lo, getXMMRegLane32F(eregOfRexRM(pfx,modrm), 0));
11855663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(f32hi, getXMMRegLane32F(eregOfRexRM(pfx,modrm), 1));
11856663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("cvt%sps2pi %s,%s\n", r2zero ? "t" : "",
11857663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                      nameXMMReg(eregOfRexRM(pfx,modrm)),
11858663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                      nameMMXReg(gregLO3ofRM(modrm)));
11859663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
11860663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
11861663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(f32lo, loadLE(Ity_F32, mkexpr(addr)));
11862663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(f32hi, loadLE(Ity_F32, binop( Iop_Add64,
11863663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                                 mkexpr(addr),
11864663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                                 mkU64(4) )));
11865663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
11866663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("cvt%sps2pi %s,%s\n", r2zero ? "t" : "",
11867663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                      dis_buf,
11868663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                      nameMMXReg(gregLO3ofRM(modrm)));
11869663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
11870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11871663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (r2zero) {
11872663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(rmode, mkU32((UInt)Irrm_ZERO) );
11873663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
11874663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( rmode, get_sse_roundingmode() );
11875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
11876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11877663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(
11878663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            dst64,
11879663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            binop( Iop_32HLto64,
11880663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   binop( Iop_F64toI32S,
11881663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          mkexpr(rmode),
11882663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          unop( Iop_F32toF64, mkexpr(f32hi) ) ),
11883663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   binop( Iop_F64toI32S,
11884663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          mkexpr(rmode),
11885663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          unop( Iop_F32toF64, mkexpr(f32lo) ) )
11886663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 )
11887663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         );
11888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11889663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putMMXReg(gregLO3ofRM(modrm), mkexpr(dst64));
11890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
11891663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
11892663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F3 0F 2D = CVTSS2SI
11893663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         when sz==4 -- convert F32 in mem/low quarter xmm to I32 in ireg,
11894663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       according to prevailing SSE rounding mode
11895663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         when sz==8 -- convert F32 in mem/low quarter xmm to I64 in ireg,
11896663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       according to prevailing SSE rounding mode
11897663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      */
11898663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F3 0F 2C = CVTTSS2SI
11899663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         when sz==4 -- convert F32 in mem/low quarter xmm to I32 in ireg,
11900663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       truncating towards zero
11901663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         when sz==8 -- convert F32 in mem/low quarter xmm to I64 in ireg,
11902663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       truncating towards zero
11903663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      */
11904663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx) && (sz == 4 || sz == 8)) {
11905663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_CVTxSS2SI( vbi, pfx, delta, False/*!isAvx*/, opc, sz);
11906663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
11907663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
11908663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F2 0F 2D = CVTSD2SI
11909663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         when sz==4 -- convert F64 in mem/low half xmm to I32 in ireg,
11910663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       according to prevailing SSE rounding mode
11911663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         when sz==8 -- convert F64 in mem/low half xmm to I64 in ireg,
11912663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       according to prevailing SSE rounding mode
11913663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      */
11914663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F2 0F 2C = CVTTSD2SI
11915663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         when sz==4 -- convert F64 in mem/low half xmm to I32 in ireg,
11916663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       truncating towards zero
11917663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         when sz==8 -- convert F64 in mem/low half xmm to I64 in ireg,
11918663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       truncating towards zero
11919663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      */
11920663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2no66noF3(pfx) && (sz == 4 || sz == 8)) {
11921663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_CVTxSD2SI( vbi, pfx, delta, False/*!isAvx*/, opc, sz);
11922663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
11923663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
11924663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 2D = CVTPD2PI -- convert 2 x F64 in mem/xmm to 2 x
11925663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         I32 in mmx, according to prevailing SSE rounding mode */
11926663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 2C = CVTTPD2PI -- convert 2 x F64 in mem/xmm to 2 x
11927663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         I32 in mmx, rounding towards zero */
11928663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
11929663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dst64  = newTemp(Ity_I64);
11930663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp rmode  = newTemp(Ity_I32);
11931663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp f64lo  = newTemp(Ity_F64);
11932663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp f64hi  = newTemp(Ity_F64);
11933663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Bool   r2zero = toBool(opc == 0x2C);
11934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11935663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         do_MMX_preamble();
11936663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
11937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11938663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
11939663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
11940663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(f64lo, getXMMRegLane64F(eregOfRexRM(pfx,modrm), 0));
11941663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(f64hi, getXMMRegLane64F(eregOfRexRM(pfx,modrm), 1));
11942663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("cvt%spd2pi %s,%s\n", r2zero ? "t" : "",
11943663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                      nameXMMReg(eregOfRexRM(pfx,modrm)),
11944663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                      nameMMXReg(gregLO3ofRM(modrm)));
11945663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
11946663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
11947663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(f64lo, loadLE(Ity_F64, mkexpr(addr)));
11948663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(f64hi, loadLE(Ity_F64, binop( Iop_Add64,
11949663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                                 mkexpr(addr),
11950663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                                 mkU64(8) )));
11951663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
11952663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("cvt%spf2pi %s,%s\n", r2zero ? "t" : "",
11953663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                      dis_buf,
11954663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                      nameMMXReg(gregLO3ofRM(modrm)));
11955663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
11956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11957663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (r2zero) {
11958663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(rmode, mkU32((UInt)Irrm_ZERO) );
11959663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
11960663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( rmode, get_sse_roundingmode() );
11961663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
11962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11963663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(
11964663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            dst64,
11965663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            binop( Iop_32HLto64,
11966663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   binop( Iop_F64toI32S, mkexpr(rmode), mkexpr(f64hi) ),
11967663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   binop( Iop_F64toI32S, mkexpr(rmode), mkexpr(f64lo) )
11968663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 )
11969663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         );
11970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11971663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putMMXReg(gregLO3ofRM(modrm), mkexpr(dst64));
11972663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
11973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11974663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
11975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11976663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x2E:
11977663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x2F:
11978663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 2E = UCOMISD -- 64F0x2 comparison G,E, and set ZCP */
11979663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 2F = COMISD  -- 64F0x2 comparison G,E, and set ZCP */
11980663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
11981663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_COMISD( vbi, pfx, delta, False/*!isAvx*/, opc );
11982663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
11983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11984663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 2E = UCOMISS -- 32F0x4 comparison G,E, and set ZCP */
11985663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 2F = COMISS  -- 32F0x4 comparison G,E, and set ZCP */
11986663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && sz == 4) {
11987663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_COMISS( vbi, pfx, delta, False/*!isAvx*/, opc );
11988663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
11989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11990663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
11991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11992663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x50:
11993663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 50 = MOVMSKPS - move 4 sign bits from 4 x F32 in xmm(E)
11994663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         to 4 lowest bits of ireg(G) */
11995663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && (sz == 4 || sz == 8)
11996663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && epartIsReg(getUChar(delta))) {
11997663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* sz == 8 is a kludge to handle insns with REX.W redundantly
11998663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            set to 1, which has been known to happen:
11999663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
12000663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            4c 0f 50 d9             rex64X movmskps %xmm1,%r11d
12001663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
12002663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            20071106: Intel docs say that REX.W isn't redundant: when
12003663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            present, a 64-bit register is written; when not present, only
12004663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            the 32-bit half is written.  However, testing on a Core2
12005663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            machine suggests the entire 64 bit register is written
12006663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            irrespective of the status of REX.W.  That could be because
12007663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            of the default rule that says "if the lower half of a 32-bit
12008663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            register is written, the upper half is zeroed".  By using
12009663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putIReg32 here we inadvertantly produce the same behaviour as
12010663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            the Core2, for the same reason -- putIReg32 implements said
12011663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            rule.
12012663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
12013663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            AMD docs give no indication that REX.W is even valid for this
12014663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            insn. */
12015663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_MOVMSKPS_128( vbi, pfx, delta, False/*!isAvx*/ );
12016663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12018663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 50 = MOVMSKPD - move 2 sign bits from 2 x F64 in xmm(E) to
12019663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         2 lowest bits of ireg(G) */
12020663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && (sz == 2 || sz == 8)) {
12021663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* sz == 8 is a kludge to handle insns with REX.W redundantly
12022663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            set to 1, which has been known to happen:
12023663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            66 4c 0f 50 d9          rex64X movmskpd %xmm1,%r11d
12024663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            20071106: see further comments on MOVMSKPS implementation above.
12025663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         */
12026663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_MOVMSKPD_128( vbi, pfx, delta, False/*!isAvx*/ );
12027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
12028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12029663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
12030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12031663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x51:
12032663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F3 0F 51 = SQRTSS -- approx sqrt 32F0x4 from R/M to R */
12033663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx) && sz == 4) {
12034663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_E_to_G_unary_lo32( vbi, pfx, delta,
12035663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                            "sqrtss", Iop_Sqrt32F0x4 );
12036663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12038663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 51 = SQRTPS -- approx sqrt 32Fx4 from R/M to R */
12039663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && sz == 4) {
12040663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_E_to_G_unary_all( vbi, pfx, delta,
12041663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                           "sqrtps", Iop_Sqrt32Fx4 );
12042663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12044663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F2 0F 51 = SQRTSD -- approx sqrt 64F0x2 from R/M to R */
12045663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2no66noF3(pfx) && sz == 4) {
12046663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_E_to_G_unary_lo64( vbi, pfx, delta,
12047663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                            "sqrtsd", Iop_Sqrt64F0x2 );
12048663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12050663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 51 = SQRTPD -- approx sqrt 64Fx2 from R/M to R */
12051663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
12052663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_E_to_G_unary_all( vbi, pfx, delta,
12053663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                           "sqrtpd", Iop_Sqrt64Fx2 );
12054663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12055663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
12056663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
12057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12058663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x52:
12059663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F3 0F 52 = RSQRTSS -- approx reciprocal sqrt 32F0x4 from R/M to R */
12060663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx) && sz == 4) {
12061663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_E_to_G_unary_lo32( vbi, pfx, delta,
12062663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                            "rsqrtss", Iop_RSqrt32F0x4 );
12063663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12064663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
12065663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 52 = RSQRTPS -- approx reciprocal sqrt 32Fx4 from R/M to R */
12066663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && sz == 4) {
12067663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_E_to_G_unary_all( vbi, pfx, delta,
12068663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                           "rsqrtps", Iop_RSqrt32Fx4 );
12069663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12070663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
12071663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
12072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12073663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x53:
12074663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F3 0F 53 = RCPSS -- approx reciprocal 32F0x4 from R/M to R */
12075663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx) && sz == 4) {
12076663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_E_to_G_unary_lo32( vbi, pfx, delta,
12077663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                            "rcpss", Iop_Recip32F0x4 );
12078663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12079663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
12080663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 53 = RCPPS -- approx reciprocal 32Fx4 from R/M to R */
12081663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && sz == 4) {
12082663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_E_to_G_unary_all( vbi, pfx, delta,
12083663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                           "rcpps", Iop_Recip32Fx4 );
12084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
12085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12086663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
12087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12088663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x54:
12089663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 54 = ANDPS -- G = G and E */
12090663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && sz == 4) {
12091663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_E_to_G_all( vbi, pfx, delta, "andps", Iop_AndV128 );
12092663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12093663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
12094663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 54 = ANDPD -- G = G and E */
12095663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
12096663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_E_to_G_all( vbi, pfx, delta, "andpd", Iop_AndV128 );
12097663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12098663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
12099663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
12100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12101663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x55:
12102663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 55 = ANDNPS -- G = (not G) and E */
12103663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && sz == 4) {
12104663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_E_to_G_all_invG( vbi, pfx, delta, "andnps",
12105663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                                           Iop_AndV128 );
12106663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12108663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 55 = ANDNPD -- G = (not G) and E */
12109663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
12110663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_E_to_G_all_invG( vbi, pfx, delta, "andnpd",
12111663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                                           Iop_AndV128 );
12112663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12114663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
12115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12116663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x56:
12117663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 56 = ORPS -- G = G and E */
12118663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && sz == 4) {
12119663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_E_to_G_all( vbi, pfx, delta, "orps", Iop_OrV128 );
12120663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12122663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 56 = ORPD -- G = G and E */
12123663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
12124663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_E_to_G_all( vbi, pfx, delta, "orpd", Iop_OrV128 );
12125663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12127663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
12128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12129663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x57:
12130663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 57 = XORPD -- G = G xor E */
12131663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
12132663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_E_to_G_all( vbi, pfx, delta, "xorpd", Iop_XorV128 );
12133663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12135663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 57 = XORPS -- G = G xor E */
12136663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && sz == 4) {
12137663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_E_to_G_all( vbi, pfx, delta, "xorps", Iop_XorV128 );
12138663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12140663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
12141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12142663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x58:
12143663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 58 = ADDPS -- add 32Fx4 from R/M to R */
12144663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && sz == 4) {
12145663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_E_to_G_all( vbi, pfx, delta, "addps", Iop_Add32Fx4 );
12146663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12148663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F3 0F 58 = ADDSS -- add 32F0x4 from R/M to R */
12149663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx) && sz == 4) {
12150663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_E_to_G_lo32( vbi, pfx, delta, "addss", Iop_Add32F0x4 );
12151663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12153663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F2 0F 58 = ADDSD -- add 64F0x2 from R/M to R */
12154663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2no66noF3(pfx)
12155663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (sz == 4 || /* ignore redundant REX.W */ sz == 8)) {
12156663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_E_to_G_lo64( vbi, pfx, delta, "addsd", Iop_Add64F0x2 );
12157663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12158663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
12159663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 58 = ADDPD -- add 32Fx4 from R/M to R */
12160663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
12161663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (sz == 2 || /* ignore redundant REX.W */ sz == 8)) {
12162663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_E_to_G_all( vbi, pfx, delta, "addpd", Iop_Add64Fx2 );
12163663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12164663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
12165663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
12166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12167663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x59:
12168663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F2 0F 59 = MULSD -- mul 64F0x2 from R/M to R */
12169663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2no66noF3(pfx)
12170663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (sz == 4 || /* ignore redundant REX.W */ sz == 8)) {
12171663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_E_to_G_lo64( vbi, pfx, delta, "mulsd", Iop_Mul64F0x2 );
12172663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12174663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F3 0F 59 = MULSS -- mul 32F0x4 from R/M to R */
12175663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx) && sz == 4) {
12176663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_E_to_G_lo32( vbi, pfx, delta, "mulss", Iop_Mul32F0x4 );
12177663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12178663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
12179663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 59 = MULPS -- mul 32Fx4 from R/M to R */
12180663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && sz == 4) {
12181663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_E_to_G_all( vbi, pfx, delta, "mulps", Iop_Mul32Fx4 );
12182663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12183663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
12184663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 59 = MULPD -- mul 64Fx2 from R/M to R */
12185663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
12186663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (sz == 2 || /* ignore redundant REX.W */ sz == 8)) {
12187663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_E_to_G_all( vbi, pfx, delta, "mulpd", Iop_Mul64Fx2 );
12188663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12189663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
12190663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
12191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12192663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x5A:
12193663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 5A = CVTPS2PD -- convert 2 x F32 in low half mem/xmm to 2 x
12194663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         F64 in xmm(G). */
12195663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && sz == 4) {
12196663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_CVTPS2PD_128( vbi, pfx, delta, False/*!isAvx*/ );
12197663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12198663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
12199663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F3 0F 5A = CVTSS2SD -- convert F32 in mem/low 1/4 xmm to F64 in
12200663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         low half xmm(G) */
12201663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx) && sz == 4) {
12202663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp f32lo = newTemp(Ity_F32);
12203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12204663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
12205663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
12206663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
12207663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(f32lo, getXMMRegLane32F(eregOfRexRM(pfx,modrm), 0));
12208663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("cvtss2sd %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)),
12209663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    nameXMMReg(gregOfRexRM(pfx,modrm)));
12210663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
12211663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
12212663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(f32lo, loadLE(Ity_F32, mkexpr(addr)));
12213663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
12214663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("cvtss2sd %s,%s\n", dis_buf,
12215663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    nameXMMReg(gregOfRexRM(pfx,modrm)));
12216663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
12217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12218663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMRegLane64F( gregOfRexRM(pfx,modrm), 0,
12219663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           unop( Iop_F32toF64, mkexpr(f32lo) ) );
12220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12221663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12223663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F2 0F 5A = CVTSD2SS -- convert F64 in mem/low half xmm to F32 in
12224663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         low 1/4 xmm(G), according to prevailing SSE rounding mode */
12225663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2no66noF3(pfx) && sz == 4) {
12226663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp rmode = newTemp(Ity_I32);
12227663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp f64lo = newTemp(Ity_F64);
12228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12229663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
12230663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
12231663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
12232663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(f64lo, getXMMRegLane64F(eregOfRexRM(pfx,modrm), 0));
12233663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("cvtsd2ss %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)),
12234663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    nameXMMReg(gregOfRexRM(pfx,modrm)));
12235663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
12236663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
12237663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(f64lo, loadLE(Ity_F64, mkexpr(addr)));
12238663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
12239663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("cvtsd2ss %s,%s\n", dis_buf,
12240663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    nameXMMReg(gregOfRexRM(pfx,modrm)));
12241663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
12242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12243663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( rmode, get_sse_roundingmode() );
12244663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMRegLane32F(
12245663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gregOfRexRM(pfx,modrm), 0,
12246663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            binop( Iop_F64toF32, mkexpr(rmode), mkexpr(f64lo) )
12247663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         );
12248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12249663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12250663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
12251663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 5A = CVTPD2PS -- convert 2 x F64 in mem/xmm to 2 x F32 in
12252663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         lo half xmm(G), rounding according to prevailing SSE rounding
12253663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         mode, and zero upper half */
12254663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Note, this is practically identical to CVTPD2DQ.  It would have
12255663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         be nice to merge them together. */
12256663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
12257663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_CVTPD2PS_128( vbi, pfx, delta, False/*!isAvx*/ );
12258663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12260663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
12261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12262663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x5B:
12263663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F3 0F 5B = CVTTPS2DQ -- convert 4 x F32 in mem/xmm to 4 x I32 in
12264663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         xmm(G), rounding towards zero */
12265663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 5B = CVTPS2DQ -- convert 4 x F32 in mem/xmm to 4 x I32 in
12266663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         xmm(G), as per the prevailing rounding mode */
12267663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if ( (have66noF2noF3(pfx) && sz == 2)
12268663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           || (haveF3no66noF2(pfx) && sz == 4) ) {
12269663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Bool r2zero = toBool(sz == 4); // FIXME -- unreliable (???)
12270663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_CVTxPS2DQ_128( vbi, pfx, delta, False/*!isAvx*/, r2zero );
12271663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12273663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 5B = CVTDQ2PS -- convert 4 x I32 in mem/xmm to 4 x F32 in
12274663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         xmm(G) */
12275663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && sz == 4) {
12276663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_CVTDQ2PS_128( vbi, pfx, delta, False/*!isAvx*/ );
12277663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12279663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
12280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12281663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x5C:
12282663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F3 0F 5C = SUBSS -- sub 32F0x4 from R/M to R */
12283663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx) && sz == 4) {
12284663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_E_to_G_lo32( vbi, pfx, delta, "subss", Iop_Sub32F0x4 );
12285663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12287663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F2 0F 5C = SUBSD -- sub 64F0x2 from R/M to R */
12288663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2no66noF3(pfx)
12289663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (sz == 4 || /* ignore redundant REX.W */ sz == 8)) {
12290663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_E_to_G_lo64( vbi, pfx, delta, "subsd", Iop_Sub64F0x2 );
12291663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12292663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
12293663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 5C = SUBPS -- sub 32Fx4 from R/M to R */
12294663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && sz == 4) {
12295663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_E_to_G_all( vbi, pfx, delta, "subps", Iop_Sub32Fx4 );
12296663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12298663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 5C = SUBPD -- sub 64Fx2 from R/M to R */
12299663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
12300663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_E_to_G_all( vbi, pfx, delta, "subpd", Iop_Sub64Fx2 );
12301663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12303663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
12304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12305663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x5D:
12306663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 5D = MINPS -- min 32Fx4 from R/M to R */
12307663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && sz == 4) {
12308663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_E_to_G_all( vbi, pfx, delta, "minps", Iop_Min32Fx4 );
12309663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12310663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
12311663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F3 0F 5D = MINSS -- min 32F0x4 from R/M to R */
12312663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx) && sz == 4) {
12313663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_E_to_G_lo32( vbi, pfx, delta, "minss", Iop_Min32F0x4 );
12314663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12315663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
12316663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F2 0F 5D = MINSD -- min 64F0x2 from R/M to R */
12317663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2no66noF3(pfx) && sz == 4) {
12318663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_E_to_G_lo64( vbi, pfx, delta, "minsd", Iop_Min64F0x2 );
12319663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12320663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
12321663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 5D = MINPD -- min 64Fx2 from R/M to R */
12322663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
12323663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_E_to_G_all( vbi, pfx, delta, "minpd", Iop_Min64Fx2 );
12324663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12325663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
12326663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
12327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12328663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x5E:
12329663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F2 0F 5E = DIVSD -- div 64F0x2 from R/M to R */
12330663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2no66noF3(pfx) && sz == 4) {
12331663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_E_to_G_lo64( vbi, pfx, delta, "divsd", Iop_Div64F0x2 );
12332663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12333663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
12334663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 5E = DIVPS -- div 32Fx4 from R/M to R */
12335663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && sz == 4) {
12336663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_E_to_G_all( vbi, pfx, delta, "divps", Iop_Div32Fx4 );
12337663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12338663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
12339663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F3 0F 5E = DIVSS -- div 32F0x4 from R/M to R */
12340663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx) && sz == 4) {
12341663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_E_to_G_lo32( vbi, pfx, delta, "divss", Iop_Div32F0x4 );
12342663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12343663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
12344663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 5E = DIVPD -- div 64Fx2 from R/M to R */
12345663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
12346663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_E_to_G_all( vbi, pfx, delta, "divpd", Iop_Div64Fx2 );
12347663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12348663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
12349663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
12350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12351663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x5F:
12352663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 5F = MAXPS -- max 32Fx4 from R/M to R */
12353663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && sz == 4) {
12354663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_E_to_G_all( vbi, pfx, delta, "maxps", Iop_Max32Fx4 );
12355663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12356663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
12357663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F3 0F 5F = MAXSS -- max 32F0x4 from R/M to R */
12358663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx) && sz == 4) {
12359663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_E_to_G_lo32( vbi, pfx, delta, "maxss", Iop_Max32F0x4 );
12360663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12361663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
12362663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F2 0F 5F = MAXSD -- max 64F0x2 from R/M to R */
12363663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2no66noF3(pfx) && sz == 4) {
12364663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_E_to_G_lo64( vbi, pfx, delta, "maxsd", Iop_Max64F0x2 );
12365663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12366663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
12367663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 5F = MAXPD -- max 64Fx2 from R/M to R */
12368663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
12369663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_E_to_G_all( vbi, pfx, delta, "maxpd", Iop_Max64Fx2 );
12370663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12371663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
12372663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
12373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12374663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x60:
12375663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 60 = PUNPCKLBW */
12376663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
12377663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSEint_E_to_G( vbi, pfx, delta,
12378663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    "punpcklbw",
12379663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    Iop_InterleaveLO8x16, True );
12380663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12381663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
12382663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
12383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12384663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x61:
12385663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 61 = PUNPCKLWD */
12386663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
12387663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSEint_E_to_G( vbi, pfx, delta,
12388663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    "punpcklwd",
12389663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    Iop_InterleaveLO16x8, True );
12390663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12392663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
12393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12394663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x62:
12395663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 62 = PUNPCKLDQ */
12396663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
12397663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSEint_E_to_G( vbi, pfx, delta,
12398663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    "punpckldq",
12399663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    Iop_InterleaveLO32x4, True );
12400663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12401663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
12402663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
12403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12404663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x63:
12405663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 63 = PACKSSWB */
12406663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
12407663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSEint_E_to_G( vbi, pfx, delta,
12408663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    "packsswb",
12409663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    Iop_QNarrowBin16Sto8Sx16, True );
12410663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12411663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
12412663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
12413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12414663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x64:
12415663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 64 = PCMPGTB */
12416663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
12417663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSEint_E_to_G( vbi, pfx, delta,
12418663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    "pcmpgtb", Iop_CmpGT8Sx16, False );
12419663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12420663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
12421663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
12422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12423663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x65:
12424663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 65 = PCMPGTW */
12425663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
12426663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSEint_E_to_G( vbi, pfx, delta,
12427663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    "pcmpgtw", Iop_CmpGT16Sx8, False );
12428663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12430663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
12431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12432663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x66:
12433663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 66 = PCMPGTD */
12434663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
12435663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSEint_E_to_G( vbi, pfx, delta,
12436663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    "pcmpgtd", Iop_CmpGT32Sx4, False );
12437663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12438663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
12439663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
12440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12441663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x67:
12442663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 67 = PACKUSWB */
12443663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
12444663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSEint_E_to_G( vbi, pfx, delta,
12445663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    "packuswb",
12446663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    Iop_QNarrowBin16Sto8Ux16, True );
12447663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12449663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
12450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12451663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x68:
12452663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 68 = PUNPCKHBW */
12453663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
12454663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSEint_E_to_G( vbi, pfx, delta,
12455663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    "punpckhbw",
12456663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    Iop_InterleaveHI8x16, True );
12457663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12458663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
12459663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
12460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12461663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x69:
12462663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 69 = PUNPCKHWD */
12463663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
12464663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSEint_E_to_G( vbi, pfx, delta,
12465663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    "punpckhwd",
12466663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    Iop_InterleaveHI16x8, True );
12467663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12469663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
12470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12471663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x6A:
12472663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 6A = PUNPCKHDQ */
12473663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
12474663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSEint_E_to_G( vbi, pfx, delta,
12475663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    "punpckhdq",
12476663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    Iop_InterleaveHI32x4, True );
12477663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12479663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
12480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12481663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x6B:
12482663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 6B = PACKSSDW */
12483663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
12484663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSEint_E_to_G( vbi, pfx, delta,
12485663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    "packssdw",
12486663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    Iop_QNarrowBin32Sto16Sx8, True );
12487663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12489663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
12490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12491663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x6C:
12492663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 6C = PUNPCKLQDQ */
12493663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
12494663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSEint_E_to_G( vbi, pfx, delta,
12495663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    "punpcklqdq",
12496663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    Iop_InterleaveLO64x2, True );
12497663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12499663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
12500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12501663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x6D:
12502663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 6D = PUNPCKHQDQ */
12503663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
12504663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSEint_E_to_G( vbi, pfx, delta,
12505663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    "punpckhqdq",
12506663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    Iop_InterleaveHI64x2, True );
12507663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12509663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
12510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12511663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x6E:
12512663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 6E = MOVD from ireg32/m32 to xmm lo 1/4,
12513663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    zeroing high 3/4 of xmm. */
12514663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /*              or from ireg64/m64 to xmm lo 1/2,
12515663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    zeroing high 1/2 of xmm. */
12516663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)) {
12517663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(sz == 2 || sz == 8);
12518663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (sz == 2) sz = 4;
12519663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
12520663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
12521663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
12522663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (sz == 4) {
12523663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               putXMMReg(
12524663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  gregOfRexRM(pfx,modrm),
12525663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  unop( Iop_32UtoV128, getIReg32(eregOfRexRM(pfx,modrm)) )
12526663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               );
12527663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               DIP("movd %s, %s\n", nameIReg32(eregOfRexRM(pfx,modrm)),
12528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    nameXMMReg(gregOfRexRM(pfx,modrm)));
12529663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            } else {
12530663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               putXMMReg(
12531663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  gregOfRexRM(pfx,modrm),
12532663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  unop( Iop_64UtoV128, getIReg64(eregOfRexRM(pfx,modrm)) )
12533663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               );
12534663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               DIP("movq %s, %s\n", nameIReg64(eregOfRexRM(pfx,modrm)),
12535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    nameXMMReg(gregOfRexRM(pfx,modrm)));
12536663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            }
12537663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
12538663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 0 );
12539663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
12540663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putXMMReg(
12541663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               gregOfRexRM(pfx,modrm),
12542663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               sz == 4
12543663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  ?  unop( Iop_32UtoV128,loadLE(Ity_I32, mkexpr(addr)) )
12544663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  :  unop( Iop_64UtoV128,loadLE(Ity_I64, mkexpr(addr)) )
12545663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            );
12546663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("mov%c %s, %s\n", sz == 4 ? 'd' : 'q', dis_buf,
12547663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  nameXMMReg(gregOfRexRM(pfx,modrm)));
12548663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
12549663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12551663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
12552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12553663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x6F:
12554663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
12555663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (sz == 2 || /* ignore redundant REX.W */ sz == 8)) {
12556663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* 66 0F 6F = MOVDQA -- move from E (mem or xmm) to G (xmm). */
12557663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
12558663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
12559663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putXMMReg( gregOfRexRM(pfx,modrm),
12560663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       getXMMReg( eregOfRexRM(pfx,modrm) ));
12561663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movdqa %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)),
12562663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  nameXMMReg(gregOfRexRM(pfx,modrm)));
12563663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
12564663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
12565663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
12566663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gen_SEGV_if_not_16_aligned( addr );
12567663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putXMMReg( gregOfRexRM(pfx,modrm),
12568663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       loadLE(Ity_V128, mkexpr(addr)) );
12569663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movdqa %s,%s\n", dis_buf,
12570663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  nameXMMReg(gregOfRexRM(pfx,modrm)));
12571663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
12572663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
12573663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12575663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx) && sz == 4) {
12576663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* F3 0F 6F = MOVDQU -- move from E (mem or xmm) to G (xmm). */
12577663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
12578663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
12579663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putXMMReg( gregOfRexRM(pfx,modrm),
12580663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       getXMMReg( eregOfRexRM(pfx,modrm) ));
12581663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movdqu %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)),
12582663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  nameXMMReg(gregOfRexRM(pfx,modrm)));
12583663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
12584663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
12585663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
12586663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putXMMReg( gregOfRexRM(pfx,modrm),
12587663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       loadLE(Ity_V128, mkexpr(addr)) );
12588663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movdqu %s,%s\n", dis_buf,
12589663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  nameXMMReg(gregOfRexRM(pfx,modrm)));
12590663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
12591663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
12592663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12594663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
12595663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
12596663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x70:
12597663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 70 = PSHUFD -- rearrange 4x32 from E(xmm or mem) to G(xmm) */
12598663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
12599663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_PSHUFD_32x4( vbi, pfx, delta, False/*!writesYmm*/);
12600663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12602663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
12603663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 70 = PSHUFW -- rearrange 4x16 from E(mmx or mem) to G(mmx) */
12604663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && sz == 4) {
12605663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int order;
12606663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sV, dV, s3, s2, s1, s0;
12607663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         s3 = s2 = s1 = s0 = IRTemp_INVALID;
12608663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         sV = newTemp(Ity_I64);
12609663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dV = newTemp(Ity_I64);
12610663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         do_MMX_preamble();
12611663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
12612663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
12613663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, getMMXReg(eregLO3ofRM(modrm)) );
12614663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            order = (Int)getUChar(delta+1);
12615663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1+1;
12616663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("pshufw $%d,%s,%s\n", order,
12617663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                      nameMMXReg(eregLO3ofRM(modrm)),
12618663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                      nameMMXReg(gregLO3ofRM(modrm)));
12619663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
12620663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf,
12621663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              1/*extra byte after amode*/ );
12622663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, loadLE(Ity_I64, mkexpr(addr)) );
12623663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            order = (Int)getUChar(delta+alen);
12624663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1+alen;
12625663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("pshufw $%d,%s,%s\n", order,
12626663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                      dis_buf,
12627663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                      nameMMXReg(gregLO3ofRM(modrm)));
12628663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
12629663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         breakup64to16s( sV, &s3, &s2, &s1, &s0 );
12630663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#        define SEL(n) \
12631663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   ((n)==0 ? s0 : ((n)==1 ? s1 : ((n)==2 ? s2 : s3)))
12632663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(dV,
12633663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   	     mk64from16s( SEL((order>>6)&3), SEL((order>>4)&3),
12634663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             SEL((order>>2)&3), SEL((order>>0)&3) )
12635663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         );
12636663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putMMXReg(gregLO3ofRM(modrm), mkexpr(dV));
12637663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#        undef SEL
12638663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12640663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F2 0F 70 = PSHUFLW -- rearrange lower half 4x16 from E(xmm or
12641663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         mem) to G(xmm), and copy upper half */
12642663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2no66noF3(pfx) && sz == 4) {
12643663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_PSHUFxW_128( vbi, pfx, delta,
12644663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  False/*!isAvx*/, False/*!xIsH*/ );
12645663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12647663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F3 0F 70 = PSHUFHW -- rearrange upper half 4x16 from E(xmm or
12648663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         mem) to G(xmm), and copy lower half */
12649663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx) && sz == 4) {
12650663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_PSHUFxW_128( vbi, pfx, delta,
12651663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  False/*!isAvx*/, True/*xIsH*/ );
12652663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12654663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
12655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12656663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x71:
12657663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 71 /2 ib = PSRLW by immediate */
12658663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2
12659663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && epartIsReg(getUChar(delta))
12660663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && gregLO3ofRM(getUChar(delta)) == 2) {
12661663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_shiftE_imm( pfx, delta, "psrlw", Iop_ShrN16x8 );
12662663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12664663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 71 /4 ib = PSRAW by immediate */
12665663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2
12666663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && epartIsReg(getUChar(delta))
12667663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && gregLO3ofRM(getUChar(delta)) == 4) {
12668663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_shiftE_imm( pfx, delta, "psraw", Iop_SarN16x8 );
12669663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12671663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 71 /6 ib = PSLLW by immediate */
12672663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2
12673663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && epartIsReg(getUChar(delta))
12674663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && gregLO3ofRM(getUChar(delta)) == 6) {
12675663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_shiftE_imm( pfx, delta, "psllw", Iop_ShlN16x8 );
12676663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12678663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
12679663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
12680663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x72:
12681663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 72 /2 ib = PSRLD by immediate */
12682663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2
12683663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && epartIsReg(getUChar(delta))
12684663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && gregLO3ofRM(getUChar(delta)) == 2) {
12685663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_shiftE_imm( pfx, delta, "psrld", Iop_ShrN32x4 );
12686663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12688663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 72 /4 ib = PSRAD by immediate */
12689663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2
12690663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && epartIsReg(getUChar(delta))
12691663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && gregLO3ofRM(getUChar(delta)) == 4) {
12692663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_shiftE_imm( pfx, delta, "psrad", Iop_SarN32x4 );
12693663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12695663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 72 /6 ib = PSLLD by immediate */
12696663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2
12697663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && epartIsReg(getUChar(delta))
12698663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && gregLO3ofRM(getUChar(delta)) == 6) {
12699663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_shiftE_imm( pfx, delta, "pslld", Iop_ShlN32x4 );
12700663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12702663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
12703663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
12704663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x73:
12705663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 73 /3 ib = PSRLDQ by immediate */
12706663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* note, if mem case ever filled in, 1 byte after amode */
12707663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2
12708663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && epartIsReg(getUChar(delta))
12709663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && gregLO3ofRM(getUChar(delta)) == 3) {
12710663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int imm = (Int)getUChar(delta+1);
12711663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int reg = eregOfRexRM(pfx,getUChar(delta));
12712663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("psrldq $%d,%s\n", imm, nameXMMReg(reg));
12713663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta += 2;
12714663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sV = newTemp(Ity_V128);
12715663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( sV, getXMMReg(reg) );
12716663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMReg(reg, mkexpr(math_PSRLDQ( sV, imm )));
12717663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12719663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 73 /7 ib = PSLLDQ by immediate */
12720663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* note, if mem case ever filled in, 1 byte after amode */
12721663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2
12722663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && epartIsReg(getUChar(delta))
12723663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && gregLO3ofRM(getUChar(delta)) == 7) {
12724663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int imm = (Int)getUChar(delta+1);
12725663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int reg = eregOfRexRM(pfx,getUChar(delta));
12726663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("pslldq $%d,%s\n", imm, nameXMMReg(reg));
12727663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(imm >= 0 && imm <= 255);
12728663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta += 2;
12729663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sV = newTemp(Ity_V128);
12730663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( sV, getXMMReg(reg) );
12731663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMReg(reg, mkexpr(math_PSLLDQ( sV, imm )));
12732663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12734663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 73 /2 ib = PSRLQ by immediate */
12735663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2
12736663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && epartIsReg(getUChar(delta))
12737663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && gregLO3ofRM(getUChar(delta)) == 2) {
12738663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_shiftE_imm( pfx, delta, "psrlq", Iop_ShrN64x2 );
12739663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12741663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 73 /6 ib = PSLLQ by immediate */
12742663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2
12743663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && epartIsReg(getUChar(delta))
12744663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && gregLO3ofRM(getUChar(delta)) == 6) {
12745663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_shiftE_imm( pfx, delta, "psllq", Iop_ShlN64x2 );
12746663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12748663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
12749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12750663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x74:
12751663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 74 = PCMPEQB */
12752663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
12753663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSEint_E_to_G( vbi, pfx, delta,
12754663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    "pcmpeqb", Iop_CmpEQ8x16, False );
12755663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12756663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
12757663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
12758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12759663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x75:
12760663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 75 = PCMPEQW */
12761663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
12762663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSEint_E_to_G( vbi, pfx, delta,
12763663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    "pcmpeqw", Iop_CmpEQ16x8, False );
12764663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12765663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
12766663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
12767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12768663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x76:
12769663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 76 = PCMPEQD */
12770663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
12771663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSEint_E_to_G( vbi, pfx, delta,
12772663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    "pcmpeqd", Iop_CmpEQ32x4, False );
12773663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12774663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
12775663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
12776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12777663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x7E:
12778663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F3 0F 7E = MOVQ -- move 64 bits from E (mem or lo half xmm) to
12779663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         G (lo half xmm).  Upper half of G is zeroed out. */
12780663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx)
12781663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (sz == 4 || /* ignore redundant REX.W */ sz == 8)) {
12782663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
12783663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
12784663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putXMMRegLane64( gregOfRexRM(pfx,modrm), 0,
12785663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             getXMMRegLane64( eregOfRexRM(pfx,modrm), 0 ));
12786663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* zero bits 127:64 */
12787663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               putXMMRegLane64( gregOfRexRM(pfx,modrm), 1, mkU64(0) );
12788663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movsd %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)),
12789663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                 nameXMMReg(gregOfRexRM(pfx,modrm)));
12790663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
12791663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
12792663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
12793663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putXMMReg( gregOfRexRM(pfx,modrm), mkV128(0) );
12794663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putXMMRegLane64( gregOfRexRM(pfx,modrm), 0,
12795663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             loadLE(Ity_I64, mkexpr(addr)) );
12796663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movsd %s,%s\n", dis_buf,
12797663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                 nameXMMReg(gregOfRexRM(pfx,modrm)));
12798663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
12799663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
12800663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12801663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
12802663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 7E = MOVD from xmm low 1/4 to ireg32 or m32. */
12803663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /*              or from xmm low 1/2 to ireg64 or m64. */
12804663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (have66noF2noF3(pfx) && (sz == 2 || sz == 8)) {
12805663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (sz == 2) sz = 4;
12806663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
12807663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
12808663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
12809663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (sz == 4) {
12810663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               putIReg32( eregOfRexRM(pfx,modrm),
12811663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          getXMMRegLane32(gregOfRexRM(pfx,modrm), 0) );
12812663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               DIP("movd %s, %s\n", nameXMMReg(gregOfRexRM(pfx,modrm)),
12813663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    nameIReg32(eregOfRexRM(pfx,modrm)));
12814663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   	 } else {
12815663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               putIReg64( eregOfRexRM(pfx,modrm),
12816663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          getXMMRegLane64(gregOfRexRM(pfx,modrm), 0) );
12817663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               DIP("movq %s, %s\n", nameXMMReg(gregOfRexRM(pfx,modrm)),
12818663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    nameIReg64(eregOfRexRM(pfx,modrm)));
12819663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   	 }
12820663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
12821663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 0 );
12822663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
12823663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            storeLE( mkexpr(addr),
12824663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     sz == 4
12825663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        ? getXMMRegLane32(gregOfRexRM(pfx,modrm),0)
12826663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        : getXMMRegLane64(gregOfRexRM(pfx,modrm),0) );
12827663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("mov%c %s, %s\n", sz == 4 ? 'd' : 'q',
12828663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  nameXMMReg(gregOfRexRM(pfx,modrm)), dis_buf);
12829663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
12830663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12832663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
12833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12834663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x7F:
12835663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F3 0F 7F = MOVDQU -- move from G (xmm) to E (mem or xmm). */
12836663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx) && sz == 4) {
12837663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
12838663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
12839663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            goto decode_failure; /* awaiting test case */
12840663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
12841663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putXMMReg( eregOfRexRM(pfx,modrm),
12842663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       getXMMReg(gregOfRexRM(pfx,modrm)) );
12843663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movdqu %s, %s\n", nameXMMReg(gregOfRexRM(pfx,modrm)),
12844663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   nameXMMReg(eregOfRexRM(pfx,modrm)));
12845663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
12846663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 0 );
12847663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
12848663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            storeLE( mkexpr(addr), getXMMReg(gregOfRexRM(pfx,modrm)) );
12849663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movdqu %s, %s\n", nameXMMReg(gregOfRexRM(pfx,modrm)), dis_buf);
12850663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
12851663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12852663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
12853663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 7F = MOVDQA -- move from G (xmm) to E (mem or xmm). */
12854663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
12855663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
12856663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
12857663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
12858663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putXMMReg( eregOfRexRM(pfx,modrm),
12859663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       getXMMReg(gregOfRexRM(pfx,modrm)) );
12860663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movdqa %s, %s\n", nameXMMReg(gregOfRexRM(pfx,modrm)),
12861663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   nameXMMReg(eregOfRexRM(pfx,modrm)));
12862663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
12863663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 0 );
12864663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gen_SEGV_if_not_16_aligned( addr );
12865663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
12866663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            storeLE( mkexpr(addr), getXMMReg(gregOfRexRM(pfx,modrm)) );
12867663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movdqa %s, %s\n", nameXMMReg(gregOfRexRM(pfx,modrm)), dis_buf);
12868663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
12869663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12870663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
12871663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
12872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12873663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xAE:
12874663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F AE /7 = SFENCE -- flush pending operations to memory */
12875663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx)
12876663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && epartIsReg(getUChar(delta)) && gregLO3ofRM(getUChar(delta)) == 7
12877663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && sz == 4) {
12878663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta += 1;
12879663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Insert a memory fence.  It's sometimes important that these
12880663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            are carried through to the generated code. */
12881663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         stmt( IRStmt_MBE(Imbe_Fence) );
12882663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("sfence\n");
12883663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12884663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
12885663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* mindless duplication follows .. */
12886663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F AE /5 = LFENCE -- flush pending operations to memory */
12887663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F AE /6 = MFENCE -- flush pending operations to memory */
12888663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx)
12889663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && epartIsReg(getUChar(delta))
12890663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (gregLO3ofRM(getUChar(delta)) == 5
12891663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              || gregLO3ofRM(getUChar(delta)) == 6)
12892663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && sz == 4) {
12893663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta += 1;
12894663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Insert a memory fence.  It's sometimes important that these
12895663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            are carried through to the generated code. */
12896663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         stmt( IRStmt_MBE(Imbe_Fence) );
12897663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("%sfence\n", gregLO3ofRM(getUChar(delta-1))==5 ? "l" : "m");
12898663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12901663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F AE /7 = CLFLUSH -- flush cache line */
12902663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx)
12903663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && !epartIsReg(getUChar(delta)) && gregLO3ofRM(getUChar(delta)) == 7
12904663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && sz == 4) {
12905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12906663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* This is something of a hack.  We need to know the size of
12907663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            the cache line containing addr.  Since we don't (easily),
12908663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assume 256 on the basis that no real cache would have a
12909663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            line that big.  It's safe to invalidate more stuff than we
12910663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            need, just inefficient. */
12911663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         ULong lineszB = 256ULL;
12912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12913663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
12914663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta += alen;
12915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12916663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Round addr down to the start of the containing block. */
12917663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         stmt( IRStmt_Put(
12918663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  OFFB_TISTART,
12919663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  binop( Iop_And64,
12920663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         mkexpr(addr),
12921663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         mkU64( ~(lineszB-1) ))) );
12922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12923663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         stmt( IRStmt_Put(OFFB_TILEN, mkU64(lineszB) ) );
12924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12925663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         jmp_lit(dres, Ijk_TInval, (Addr64)(guest_RIP_bbstart+delta));
12926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12927663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("clflush %s\n", dis_buf);
12928663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12929663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
12930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12931663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F AE /3 = STMXCSR m32 -- store %mxcsr */
12932663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx)
12933663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && !epartIsReg(getUChar(delta)) && gregLO3ofRM(getUChar(delta)) == 3
12934663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && sz == 4) {
12935663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_STMXCSR(vbi, pfx, delta, False/*!isAvx*/);
12936663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12937663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
12938663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F AE /2 = LDMXCSR m32 -- load %mxcsr */
12939663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx)
12940663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && !epartIsReg(getUChar(delta)) && gregLO3ofRM(getUChar(delta)) == 2
12941663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && sz == 4) {
12942663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_LDMXCSR(vbi, pfx, delta, False/*!isAvx*/);
12943663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
12944663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
12945663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F AE /0 = FXSAVE m512 -- write x87 and SSE state to memory.
12946663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Note that the presence or absence of REX.W slightly affects the
12947663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         written format: whether the saved FPU IP and DP pointers are 64
12948663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         or 32 bits.  But the helper function we call simply writes zero
12949663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         bits in the relevant fields (which are 64 bits regardless of
12950663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         what REX.W is) and so it's good enough (iow, equally broken) in
12951663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         both cases. */
12952663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && (sz == 4 || sz == 8)
12953663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && !epartIsReg(getUChar(delta))
12954663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && gregOfRexRM(pfx,getUChar(delta)) == 0) {
12955663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          IRDirty* d;
12956663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
12957663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(!epartIsReg(modrm));
12958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12959663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
12960663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta += alen;
12961663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         gen_SEGV_if_not_16_aligned(addr);
12962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12963663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("%sfxsave %s\n", sz==8 ? "rex64/" : "", dis_buf);
12964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12965663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Uses dirty helper:
12966663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               void amd64g_do_FXSAVE ( VexGuestAMD64State*, ULong ) */
12967663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d = unsafeIRDirty_0_N (
12968663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                0/*regparms*/,
12969663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                "amd64g_dirtyhelper_FXSAVE",
12970663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                &amd64g_dirtyhelper_FXSAVE,
12971663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                mkIRExprVec_1( mkexpr(addr) )
12972663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             );
12973663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->needsBBP = True;
12974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12975663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* declare we're writing memory */
12976663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->mFx   = Ifx_Write;
12977663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->mAddr = mkexpr(addr);
12978663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->mSize = 464; /* according to recent Intel docs */
12979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12980663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* declare we're reading guest state */
12981663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->nFxState = 7;
12982663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vex_bzero(&d->fxState, sizeof(d->fxState));
12983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12984663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->fxState[0].fx     = Ifx_Read;
12985663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->fxState[0].offset = OFFB_FTOP;
12986663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->fxState[0].size   = sizeof(UInt);
12987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12988663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->fxState[1].fx     = Ifx_Read;
12989663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->fxState[1].offset = OFFB_FPREGS;
12990663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->fxState[1].size   = 8 * sizeof(ULong);
12991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12992663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->fxState[2].fx     = Ifx_Read;
12993663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->fxState[2].offset = OFFB_FPTAGS;
12994663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->fxState[2].size   = 8 * sizeof(UChar);
12995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12996663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->fxState[3].fx     = Ifx_Read;
12997663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->fxState[3].offset = OFFB_FPROUND;
12998663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->fxState[3].size   = sizeof(ULong);
12999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13000663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->fxState[4].fx     = Ifx_Read;
13001663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->fxState[4].offset = OFFB_FC3210;
13002663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->fxState[4].size   = sizeof(ULong);
13003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13004663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->fxState[5].fx     = Ifx_Read;
13005663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->fxState[5].offset = OFFB_YMM0;
13006663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->fxState[5].size   = sizeof(U128);
13007663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* plus 15 more of the above, spaced out in YMM sized steps */
13008663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->fxState[5].nRepeats  = 15;
13009663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->fxState[5].repeatLen = sizeof(U256);
13010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13011663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->fxState[6].fx     = Ifx_Read;
13012663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->fxState[6].offset = OFFB_SSEROUND;
13013663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->fxState[6].size   = sizeof(ULong);
13014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13015663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Be paranoid ... this assertion tries to ensure the 16 %ymm
13016663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            images are packed back-to-back.  If not, the settings for
13017663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            d->fxState[5] are wrong. */
13018663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(32 == sizeof(U256));
13019663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(OFFB_YMM15 == (OFFB_YMM0 + 15 * 32));
13020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13021663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         stmt( IRStmt_Dirty(d) );
13022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13023663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13024663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13025663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F AE /1 = FXRSTOR m512 -- read x87 and SSE state from memory.
13026663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         As with FXSAVE above we ignore the value of REX.W since we're
13027663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         not bothering with the FPU DP and IP fields. */
13028663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && (sz == 4 || sz == 8)
13029663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && !epartIsReg(getUChar(delta))
13030663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && gregOfRexRM(pfx,getUChar(delta)) == 1) {
13031663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRDirty* d;
13032663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
13033663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(!epartIsReg(modrm));
13034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13035663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
13036663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta += alen;
13037663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         gen_SEGV_if_not_16_aligned(addr);
13038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13039663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("%sfxrstor %s\n", sz==8 ? "rex64/" : "", dis_buf);
13040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13041663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Uses dirty helper:
13042663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               VexEmWarn amd64g_do_FXRSTOR ( VexGuestAMD64State*, ULong )
13043663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            NOTE:
13044663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               the VexEmWarn value is simply ignored
13045663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         */
13046663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d = unsafeIRDirty_0_N (
13047663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                0/*regparms*/,
13048663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                "amd64g_dirtyhelper_FXRSTOR",
13049663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                &amd64g_dirtyhelper_FXRSTOR,
13050663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                mkIRExprVec_1( mkexpr(addr) )
13051663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             );
13052663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->needsBBP = True;
13053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13054663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* declare we're reading memory */
13055663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->mFx   = Ifx_Read;
13056663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->mAddr = mkexpr(addr);
13057663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->mSize = 464; /* according to recent Intel docs */
13058f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
13059663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* declare we're writing guest state */
13060663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->nFxState = 7;
13061663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vex_bzero(&d->fxState, sizeof(d->fxState));
13062f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
13063663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->fxState[0].fx     = Ifx_Write;
13064663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->fxState[0].offset = OFFB_FTOP;
13065663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->fxState[0].size   = sizeof(UInt);
13066f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
13067663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->fxState[1].fx     = Ifx_Write;
13068663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->fxState[1].offset = OFFB_FPREGS;
13069663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->fxState[1].size   = 8 * sizeof(ULong);
13070f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
13071663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->fxState[2].fx     = Ifx_Write;
13072663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->fxState[2].offset = OFFB_FPTAGS;
13073663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->fxState[2].size   = 8 * sizeof(UChar);
13074f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
13075663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->fxState[3].fx     = Ifx_Write;
13076663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->fxState[3].offset = OFFB_FPROUND;
13077663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->fxState[3].size   = sizeof(ULong);
13078663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
13079663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->fxState[4].fx     = Ifx_Write;
13080663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->fxState[4].offset = OFFB_FC3210;
13081663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->fxState[4].size   = sizeof(ULong);
13082663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
13083663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->fxState[5].fx     = Ifx_Write;
13084663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->fxState[5].offset = OFFB_YMM0;
13085663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->fxState[5].size   = sizeof(U128);
13086663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* plus 15 more of the above, spaced out in YMM sized steps */
13087663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->fxState[5].nRepeats  = 15;
13088663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->fxState[5].repeatLen = sizeof(U256);
13089663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
13090663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->fxState[6].fx     = Ifx_Write;
13091663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->fxState[6].offset = OFFB_SSEROUND;
13092663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->fxState[6].size   = sizeof(ULong);
13093663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
13094663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Be paranoid ... this assertion tries to ensure the 16 %ymm
13095663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            images are packed back-to-back.  If not, the settings for
13096663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            d->fxState[5] are wrong. */
13097663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(32 == sizeof(U256));
13098663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(OFFB_YMM15 == (OFFB_YMM0 + 15 * 32));
13099f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
13100663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         stmt( IRStmt_Dirty(d) );
13101f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
13102663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13103663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13104663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
13105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13106663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xC2:
13107663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F C2 = CMPPS -- 32Fx4 comparison from R/M to R */
13108663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && sz == 4) {
13109663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Long delta0 = delta;
13110663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_cmp_E_to_G( vbi, pfx, delta, "cmpps", True, 4 );
13111663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (delta > delta0) goto decode_success;
13112663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13113663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F3 0F C2 = CMPSS -- 32F0x4 comparison from R/M to R */
13114663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx) && sz == 4) {
13115663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Long delta0 = delta;
13116663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_cmp_E_to_G( vbi, pfx, delta, "cmpss", False, 4 );
13117663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (delta > delta0) goto decode_success;
13118663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13119663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F2 0F C2 = CMPSD -- 64F0x2 comparison from R/M to R */
13120663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2no66noF3(pfx) && sz == 4) {
13121663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Long delta0 = delta;
13122663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_cmp_E_to_G( vbi, pfx, delta, "cmpsd", False, 8 );
13123663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (delta > delta0) goto decode_success;
13124663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13125663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F C2 = CMPPD -- 64Fx2 comparison from R/M to R */
13126663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
13127663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Long delta0 = delta;
13128663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_cmp_E_to_G( vbi, pfx, delta, "cmppd", True, 8 );
13129663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (delta > delta0) goto decode_success;
13130663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13131663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
13132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13133663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xC3:
13134663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F C3 = MOVNTI -- for us, just a plain ireg store. */
13135663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && (sz == 4 || sz == 8)) {
13136663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
13137663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (!epartIsReg(modrm)) {
13138663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
13139663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            storeLE( mkexpr(addr), getIRegG(sz, pfx, modrm) );
13140663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movnti %s,%s\n", dis_buf,
13141663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  nameIRegG(sz, pfx, modrm));
13142663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
13143663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            goto decode_success;
13144663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
13145663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* else fall through */
13146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
13147663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
13148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13149663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xC4:
13150663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
13151663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F C4 = PINSRW -- get 16 bits from E(mem or low half ireg) and
13152663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         put it into the specified lane of mmx(G). */
13153663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx)
13154663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (sz == 4 || /* ignore redundant REX.W */ sz == 8)) {
13155663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Use t0 .. t3 to hold the 4 original 16-bit lanes of the
13156663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            mmx reg.  t4 is the new lane value.  t5 is the original
13157663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            mmx value. t6 is the new mmx value. */
13158663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int lane;
13159663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         t4 = newTemp(Ity_I16);
13160663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         t5 = newTemp(Ity_I64);
13161663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         t6 = newTemp(Ity_I64);
13162663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
13163663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         do_MMX_preamble();
13164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13165663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(t5, getMMXReg(gregLO3ofRM(modrm)));
13166663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         breakup64to16s( t5, &t3, &t2, &t1, &t0 );
13167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13168663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
13169663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(t4, getIReg16(eregOfRexRM(pfx,modrm)));
13170663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1+1;
13171663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            lane = getUChar(delta-1);
13172663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("pinsrw $%d,%s,%s\n", (Int)lane,
13173663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                      nameIReg16(eregOfRexRM(pfx,modrm)),
13174663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                      nameMMXReg(gregLO3ofRM(modrm)));
13175663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
13176663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 1 );
13177663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1+alen;
13178663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            lane = getUChar(delta-1);
13179663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(t4, loadLE(Ity_I16, mkexpr(addr)));
13180663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("pinsrw $%d,%s,%s\n", (Int)lane,
13181663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                      dis_buf,
13182663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                      nameMMXReg(gregLO3ofRM(modrm)));
13183663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
13184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13185663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         switch (lane & 3) {
13186663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 0:  assign(t6, mk64from16s(t3,t2,t1,t4)); break;
13187663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 1:  assign(t6, mk64from16s(t3,t2,t4,t0)); break;
13188663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 2:  assign(t6, mk64from16s(t3,t4,t1,t0)); break;
13189663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 3:  assign(t6, mk64from16s(t4,t2,t1,t0)); break;
13190663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            default: vassert(0);
13191663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
13192663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putMMXReg(gregLO3ofRM(modrm), mkexpr(t6));
13193663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13194663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13195663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F C4 = PINSRW -- get 16 bits from E(mem or low half ireg) and
13196663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         put it into the specified lane of xmm(G). */
13197663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
13198663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (sz == 2 || /* ignore redundant REX.W */ sz == 8)) {
13199663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int lane;
13200663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         t4 = newTemp(Ity_I16);
13201663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
13202663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt rG = gregOfRexRM(pfx,modrm);
13203663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
13204663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
13205663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(t4, getIReg16(rE));
13206663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1+1;
13207663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            lane = getUChar(delta-1);
13208663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("pinsrw $%d,%s,%s\n",
13209663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                (Int)lane, nameIReg16(rE), nameXMMReg(rG));
13210663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
13211663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf,
13212663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              1/*byte after the amode*/ );
13213663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1+alen;
13214663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            lane = getUChar(delta-1);
13215663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(t4, loadLE(Ity_I16, mkexpr(addr)));
13216663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("pinsrw $%d,%s,%s\n",
13217663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                (Int)lane, dis_buf, nameXMMReg(rG));
13218663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
13219663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp src_vec = newTemp(Ity_V128);
13220663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(src_vec, getXMMReg(rG));
13221663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp res_vec = math_PINSRW_128( src_vec, t4, lane & 7);
13222663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMReg(rG, mkexpr(res_vec));
13223663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
13225663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
13226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13227663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xC5:
13228663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
13229663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F C5 = PEXTRW -- extract 16-bit field from mmx(E) and put
13230663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         zero-extend of it in ireg(G). */
13231663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && (sz == 4 || sz == 8)) {
13232663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
13233663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
13234663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            IRTemp sV = newTemp(Ity_I64);
13235663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            t5 = newTemp(Ity_I16);
13236663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            do_MMX_preamble();
13237663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(sV, getMMXReg(eregLO3ofRM(modrm)));
13238663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            breakup64to16s( sV, &t3, &t2, &t1, &t0 );
13239663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            switch (getUChar(delta+1) & 3) {
13240663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               case 0:  assign(t5, mkexpr(t0)); break;
13241663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               case 1:  assign(t5, mkexpr(t1)); break;
13242663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               case 2:  assign(t5, mkexpr(t2)); break;
13243663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               case 3:  assign(t5, mkexpr(t3)); break;
13244663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               default: vassert(0);
13245663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            }
13246663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (sz == 8)
13247663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               putIReg64(gregOfRexRM(pfx,modrm), unop(Iop_16Uto64, mkexpr(t5)));
13248663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            else
13249663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               putIReg32(gregOfRexRM(pfx,modrm), unop(Iop_16Uto32, mkexpr(t5)));
13250663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("pextrw $%d,%s,%s\n",
13251663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                (Int)getUChar(delta+1),
13252663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                nameMMXReg(eregLO3ofRM(modrm)),
13253663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                sz==8 ? nameIReg64(gregOfRexRM(pfx,modrm))
13254663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      : nameIReg32(gregOfRexRM(pfx,modrm))
13255663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            );
13256663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 2;
13257663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            goto decode_success;
13258663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
13259663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* else fall through */
13260663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* note, for anyone filling in the mem case: this insn has one
13261663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            byte after the amode and therefore you must pass 1 as the
13262663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            last arg to disAMode */
13263663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13264663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F C5 = PEXTRW -- extract 16-bit field from xmm(E) and put
13265663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         zero-extend of it in ireg(G). */
13266663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
13267663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (sz == 2 || /* ignore redundant REX.W */ sz == 8)) {
13268663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Long delta0 = delta;
13269663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_PEXTRW_128_EregOnly_toG( vbi, pfx, delta,
13270663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                              False/*!isAvx*/ );
13271663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (delta > delta0) goto decode_success;
13272663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* else fall through -- decoding has failed */
13273663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13274663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
13275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13276663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xC6:
13277663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F C6 /r ib = SHUFPS -- shuffle packed F32s */
13278663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && sz == 4) {
13279663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int    imm8 = 0;
13280663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sV   = newTemp(Ity_V128);
13281663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dV   = newTemp(Ity_V128);
13282663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
13283663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt rG = gregOfRexRM(pfx,modrm);
13284663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( dV, getXMMReg(rG) );
13285663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
13286663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
13287663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, getXMMReg(rE) );
13288663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = (Int)getUChar(delta+1);
13289663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1+1;
13290663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("shufps $%d,%s,%s\n", imm8, nameXMMReg(rE), nameXMMReg(rG));
13291663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
13292663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 1 );
13293663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
13294663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = (Int)getUChar(delta+alen);
13295663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1+alen;
13296663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("shufps $%d,%s,%s\n", imm8, dis_buf, nameXMMReg(rG));
13297663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
13298663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp res = math_SHUFPS_128( sV, dV, imm8 );
13299663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMReg( gregOfRexRM(pfx,modrm), mkexpr(res) );
13300663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13301663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13302663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F C6 /r ib = SHUFPD -- shuffle packed F64s */
13303663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
13304663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int    select;
13305663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sV = newTemp(Ity_V128);
13306663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dV = newTemp(Ity_V128);
13307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13308663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
13309663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( dV, getXMMReg(gregOfRexRM(pfx,modrm)) );
13310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13311663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
13312663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, getXMMReg(eregOfRexRM(pfx,modrm)) );
13313663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            select = (Int)getUChar(delta+1);
13314663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1+1;
13315663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("shufpd $%d,%s,%s\n", select,
13316663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                      nameXMMReg(eregOfRexRM(pfx,modrm)),
13317663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                      nameXMMReg(gregOfRexRM(pfx,modrm)));
13318663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
13319663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 1 );
13320663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
13321663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            select = getUChar(delta+alen);
13322663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1+alen;
13323663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("shufpd $%d,%s,%s\n", select,
13324663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                      dis_buf,
13325663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                      nameXMMReg(gregOfRexRM(pfx,modrm)));
13326663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
13327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13328663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp res = math_SHUFPD_128( sV, dV, select );
13329663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMReg( gregOfRexRM(pfx,modrm), mkexpr(res) );
13330663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13331663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13332663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
13333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13334663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xD1:
13335663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F D1 = PSRLW by E */
13336663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
13337663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_shiftG_byE( vbi, pfx, delta, "psrlw", Iop_ShrN16x8 );
13338663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13339663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13340663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
13341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13342663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xD2:
13343663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F D2 = PSRLD by E */
13344663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
13345663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_shiftG_byE( vbi, pfx, delta, "psrld", Iop_ShrN32x4 );
13346663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13347663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13348663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
13349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13350663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xD3:
13351663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F D3 = PSRLQ by E */
13352663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
13353663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_shiftG_byE( vbi, pfx, delta, "psrlq", Iop_ShrN64x2 );
13354663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13355663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13356663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
13357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13358663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xD4:
13359663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F D4 = PADDQ */
13360663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
13361663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSEint_E_to_G( vbi, pfx, delta,
13362663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    "paddq", Iop_Add64x2, False );
13363663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13364663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13365663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* ***--- this is an MMX class insn introduced in SSE2 ---*** */
13366663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F D4 = PADDQ -- add 64x1 */
13367663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && sz == 4) {
13368663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         do_MMX_preamble();
13369663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_MMXop_regmem_to_reg (
13370663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   vbi, pfx, delta, opc, "paddq", False );
13371663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13372663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13373663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
13374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13375663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xD5:
13376663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F D5 = PMULLW -- 16x8 multiply */
13377663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
13378663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSEint_E_to_G( vbi, pfx, delta,
13379663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    "pmullw", Iop_Mul16x8, False );
13380663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13381663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13382663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
13383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13384663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xD6:
13385663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F3 0F D6 = MOVQ2DQ -- move from E (mmx) to G (lo half xmm, zero
13386663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         hi half). */
13387663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx) && sz == 4) {
13388663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
13389663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
13390663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            do_MMX_preamble();
13391663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putXMMReg( gregOfRexRM(pfx,modrm),
13392663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       unop(Iop_64UtoV128, getMMXReg( eregLO3ofRM(modrm) )) );
13393663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movq2dq %s,%s\n", nameMMXReg(eregLO3ofRM(modrm)),
13394663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   nameXMMReg(gregOfRexRM(pfx,modrm)));
13395663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
13396663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            goto decode_success;
13397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
13398663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* apparently no mem case for this insn */
13399663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13400663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F D6 = MOVQ -- move 64 bits from G (lo half xmm) to E (mem
13401663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         or lo half xmm).  */
13402663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
13403663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (sz == 2 || /* ignore redundant REX.W */ sz == 8)) {
13404663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
13405663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
13406663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* fall through, awaiting test case */
13407663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* dst: lo half copied, hi half zeroed */
13408663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
13409663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
13410663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            storeLE( mkexpr(addr),
13411663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     getXMMRegLane64( gregOfRexRM(pfx,modrm), 0 ));
13412663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movq %s,%s\n", nameXMMReg(gregOfRexRM(pfx,modrm)), dis_buf );
13413663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
13414663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            goto decode_success;
13415663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
13416663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13417663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F2 0F D6 = MOVDQ2Q -- move from E (lo half xmm, not mem) to G (mmx). */
13418663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2no66noF3(pfx) && sz == 4) {
13419663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
13420663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
13421663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            do_MMX_preamble();
13422663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putMMXReg( gregLO3ofRM(modrm),
13423663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       getXMMRegLane64( eregOfRexRM(pfx,modrm), 0 ));
13424663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movdq2q %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)),
13425663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   nameMMXReg(gregLO3ofRM(modrm)));
13426663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
13427663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            goto decode_success;
13428663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
13429663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* apparently no mem case for this insn */
13430663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13431663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
13432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13433663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xD7:
13434663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F D7 = PMOVMSKB -- extract sign bits from each of 16
13435663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         lanes in xmm(E), turn them into a byte, and put
13436663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         zero-extend of it in ireg(G).  Doing this directly is just
13437663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         too cumbersome; give up therefore and call a helper. */
13438663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
13439663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (sz == 2 || /* ignore redundant REX.W */ sz == 8)
13440663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && epartIsReg(getUChar(delta))) { /* no memory case, it seems */
13441663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_PMOVMSKB_128( vbi, pfx, delta, False/*!isAvx*/ );
13442663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13443663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13444663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
13445663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F D7 = PMOVMSKB -- extract sign bits from each of 8 lanes in
13446663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         mmx(G), turn them into a byte, and put zero-extend of it in
13447663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         ireg(G). */
13448663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx)
13449663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (sz == 4 || /* ignore redundant REX.W */ sz == 8)) {
13450663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
13451663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
13452663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            do_MMX_preamble();
13453663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            t0 = newTemp(Ity_I64);
13454663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            t1 = newTemp(Ity_I64);
13455663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(t0, getMMXReg(eregLO3ofRM(modrm)));
13456663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(t1, mkIRExprCCall(
13457663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          Ity_I64, 0/*regparms*/,
13458663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          "amd64g_calculate_mmx_pmovmskb",
13459663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          &amd64g_calculate_mmx_pmovmskb,
13460663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          mkIRExprVec_1(mkexpr(t0))));
13461663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putIReg32(gregOfRexRM(pfx,modrm), unop(Iop_64to32,mkexpr(t1)));
13462663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("pmovmskb %s,%s\n", nameMMXReg(eregLO3ofRM(modrm)),
13463663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    nameIReg32(gregOfRexRM(pfx,modrm)));
13464663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
13465663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            goto decode_success;
13466663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
13467663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* else fall through */
13468663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13469663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
13470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13471663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xD8:
13472663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F D8 = PSUBUSB */
13473663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
13474663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSEint_E_to_G( vbi, pfx, delta,
13475663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    "psubusb", Iop_QSub8Ux16, False );
13476663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
13478663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
13479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13480663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xD9:
13481663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F D9 = PSUBUSW */
13482663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
13483663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSEint_E_to_G( vbi, pfx, delta,
13484663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    "psubusw", Iop_QSub16Ux8, False );
13485663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
13487663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
13488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13489663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xDA:
13490663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
13491663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F DA = PMINUB -- 8x8 unsigned min */
13492663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && sz == 4) {
13493663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         do_MMX_preamble();
13494663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_MMXop_regmem_to_reg (
13495663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    vbi, pfx, delta, opc, "pminub", False );
13496663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
13498663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F DA = PMINUB -- 8x16 unsigned min */
13499663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
13500663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSEint_E_to_G( vbi, pfx, delta,
13501663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    "pminub", Iop_Min8Ux16, False );
13502663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13503663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13504663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
13505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13506663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xDB:
13507663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F DB = PAND */
13508663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
13509663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_E_to_G_all( vbi, pfx, delta, "pand", Iop_AndV128 );
13510663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13511663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13512663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
13513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13514663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xDC:
13515663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F DC = PADDUSB */
13516663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
13517663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSEint_E_to_G( vbi, pfx, delta,
13518663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    "paddusb", Iop_QAdd8Ux16, False );
13519663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13520663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13521663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
13522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13523663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xDD:
13524663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F DD = PADDUSW */
13525663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
13526663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSEint_E_to_G( vbi, pfx, delta,
13527663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    "paddusw", Iop_QAdd16Ux8, False );
13528663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13529663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13530663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
13531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13532663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xDE:
13533663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
13534663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F DE = PMAXUB -- 8x8 unsigned max */
13535663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && sz == 4) {
13536663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         do_MMX_preamble();
13537663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_MMXop_regmem_to_reg (
13538663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    vbi, pfx, delta, opc, "pmaxub", False );
13539663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13540663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13541663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F DE = PMAXUB -- 8x16 unsigned max */
13542663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
13543663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSEint_E_to_G( vbi, pfx, delta,
13544663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    "pmaxub", Iop_Max8Ux16, False );
13545663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13546663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13547663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
13548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13549663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xDF:
13550663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F DF = PANDN */
13551663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
13552663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_E_to_G_all_invG( vbi, pfx, delta, "pandn", Iop_AndV128 );
13553663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13554663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13555663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
13556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13557663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xE0:
13558663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
13559663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F E0 = PAVGB -- 8x8 unsigned Packed Average, with rounding */
13560663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && sz == 4) {
13561663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         do_MMX_preamble();
13562663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_MMXop_regmem_to_reg (
13563663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    vbi, pfx, delta, opc, "pavgb", False );
13564663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
13566663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F E0 = PAVGB */
13567663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
13568663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSEint_E_to_G( vbi, pfx, delta,
13569663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    "pavgb", Iop_Avg8Ux16, False );
13570663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
13572663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
13573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13574663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xE1:
13575663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F E1 = PSRAW by E */
13576663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
13577663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_shiftG_byE( vbi, pfx, delta, "psraw", Iop_SarN16x8 );
13578663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
13580663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
13581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13582663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xE2:
13583663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F E2 = PSRAD by E */
13584663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
13585663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_shiftG_byE( vbi, pfx, delta, "psrad", Iop_SarN32x4 );
13586663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13587663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13588663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
13589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13590663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xE3:
13591663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
13592663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F E3 = PAVGW -- 16x4 unsigned Packed Average, with rounding */
13593663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && sz == 4) {
13594663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         do_MMX_preamble();
13595663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_MMXop_regmem_to_reg (
13596663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    vbi, pfx, delta, opc, "pavgw", False );
13597663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13598663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13599663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F E3 = PAVGW */
13600663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
13601663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSEint_E_to_G( vbi, pfx, delta,
13602663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    "pavgw", Iop_Avg16Ux8, False );
13603663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13604663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13605663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
13606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13607663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xE4:
13608663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
13609663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F E4 = PMULUH -- 16x4 hi-half of unsigned widening multiply */
13610663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && sz == 4) {
13611663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         do_MMX_preamble();
13612663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_MMXop_regmem_to_reg (
13613663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    vbi, pfx, delta, opc, "pmuluh", False );
13614663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13615663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13616663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F E4 = PMULHUW -- 16x8 hi-half of unsigned widening multiply */
13617663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
13618663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSEint_E_to_G( vbi, pfx, delta,
13619663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    "pmulhuw", Iop_MulHi16Ux8, False );
13620663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13621663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13622663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
13623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13624663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xE5:
13625663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F E5 = PMULHW -- 16x8 hi-half of signed widening multiply */
13626663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
13627663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSEint_E_to_G( vbi, pfx, delta,
13628663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    "pmulhw", Iop_MulHi16Sx8, False );
13629663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13630663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13631663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
13632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13633663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xE6:
13634663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F E6 = CVTTPD2DQ -- convert 2 x F64 in mem/xmm to 2 x I32 in
13635663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         lo half xmm(G), and zero upper half, rounding towards zero */
13636663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F2 0F E6 = CVTPD2DQ -- convert 2 x F64 in mem/xmm to 2 x I32 in
13637663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         lo half xmm(G), according to prevailing rounding mode, and zero
13638663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         upper half */
13639663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if ( (haveF2no66noF3(pfx) && sz == 4)
13640663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           || (have66noF2noF3(pfx) && sz == 2) ) {
13641663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_CVTxPD2DQ_128( vbi, pfx, delta, False/*!isAvx*/,
13642663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    toBool(sz == 2)/*r2zero*/);
13643663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13644663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13645663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F3 0F E6 = CVTDQ2PD -- convert 2 x I32 in mem/lo half xmm to 2 x
13646663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         F64 in xmm(G) */
13647663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx) && sz == 4) {
13648663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_CVTDQ2PD_128(vbi, pfx, delta, False/*!isAvx*/);
13649663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13650663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13651663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
13652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13653663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xE7:
13654663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
13655663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F E7 = MOVNTQ -- for us, just a plain MMX store.  Note, the
13656663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Intel manual does not say anything about the usual business of
13657663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         the FP reg tags getting trashed whenever an MMX insn happens.
13658663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         So we just leave them alone.
13659663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      */
13660663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && sz == 4) {
13661663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
13662663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (!epartIsReg(modrm)) {
13663663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* do_MMX_preamble(); Intel docs don't specify this */
13664663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
13665663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            storeLE( mkexpr(addr), getMMXReg(gregLO3ofRM(modrm)) );
13666663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movntq %s,%s\n", dis_buf,
13667663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  nameMMXReg(gregLO3ofRM(modrm)));
13668663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
13669663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            goto decode_success;
13670663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
13671663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* else fall through */
13672663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13673663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F E7 = MOVNTDQ -- for us, just a plain SSE store. */
13674663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
13675663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
13676663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (!epartIsReg(modrm)) {
13677663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
13678663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gen_SEGV_if_not_16_aligned( addr );
13679663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            storeLE( mkexpr(addr), getXMMReg(gregOfRexRM(pfx,modrm)) );
13680663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movntdq %s,%s\n", dis_buf,
13681663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   nameXMMReg(gregOfRexRM(pfx,modrm)));
13682663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
13683663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            goto decode_success;
13684663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
13685663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* else fall through */
13686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
13687663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
13688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13689663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xE8:
13690663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F E8 = PSUBSB */
13691663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
13692663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSEint_E_to_G( vbi, pfx, delta,
13693663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    "psubsb", Iop_QSub8Sx16, False );
13694663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
13696663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
13697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13698663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xE9:
13699663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F E9 = PSUBSW */
13700663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
13701663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSEint_E_to_G( vbi, pfx, delta,
13702663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    "psubsw", Iop_QSub16Sx8, False );
13703663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13704663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13705663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
13706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13707663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xEA:
13708663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
13709663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F EA = PMINSW -- 16x4 signed min */
13710663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && sz == 4) {
13711663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         do_MMX_preamble();
13712663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_MMXop_regmem_to_reg (
13713663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    vbi, pfx, delta, opc, "pminsw", False );
13714663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13715663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13716663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F EA = PMINSW -- 16x8 signed min */
13717663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
13718663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSEint_E_to_G( vbi, pfx, delta,
13719663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    "pminsw", Iop_Min16Sx8, False );
13720663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13721663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13722663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
13723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13724663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xEB:
13725663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F EB = POR */
13726663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
13727663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_E_to_G_all( vbi, pfx, delta, "por", Iop_OrV128 );
13728663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13729663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13730663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
13731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13732663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xEC:
13733663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F EC = PADDSB */
13734663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
13735663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSEint_E_to_G( vbi, pfx, delta,
13736663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    "paddsb", Iop_QAdd8Sx16, False );
13737663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13738663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13739663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
13740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13741663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xED:
13742663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F ED = PADDSW */
13743663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
13744663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSEint_E_to_G( vbi, pfx, delta,
13745663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    "paddsw", Iop_QAdd16Sx8, False );
13746663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13747663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13748663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
13749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13750663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xEE:
13751663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
13752663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F EE = PMAXSW -- 16x4 signed max */
13753663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && sz == 4) {
13754663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         do_MMX_preamble();
13755663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_MMXop_regmem_to_reg (
13756663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    vbi, pfx, delta, opc, "pmaxsw", False );
13757663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
13759663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F EE = PMAXSW -- 16x8 signed max */
13760663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
13761663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSEint_E_to_G( vbi, pfx, delta,
13762663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    "pmaxsw", Iop_Max16Sx8, False );
13763663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13764663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13765663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
13766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13767663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xEF:
13768663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F EF = PXOR */
13769663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
13770663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_E_to_G_all( vbi, pfx, delta, "pxor", Iop_XorV128 );
13771663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13772663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13773663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
13774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13775663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xF1:
13776663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F F1 = PSLLW by E */
13777663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
13778663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_shiftG_byE( vbi, pfx, delta, "psllw", Iop_ShlN16x8 );
13779663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13780663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13781663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
13782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13783663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xF2:
13784663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F F2 = PSLLD by E */
13785663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
13786663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_shiftG_byE( vbi, pfx, delta, "pslld", Iop_ShlN32x4 );
13787663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13788663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13789663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
13790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13791663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xF3:
13792663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F F3 = PSLLQ by E */
13793663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
13794663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSE_shiftG_byE( vbi, pfx, delta, "psllq", Iop_ShlN64x2 );
13795663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13796663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13797663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
13798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13799663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xF4:
13800663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F F4 = PMULUDQ -- unsigned widening multiply of 32-lanes 0 x
13801663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         0 to form lower 64-bit half and lanes 2 x 2 to form upper 64-bit
13802663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         half */
13803663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
13804663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sV = newTemp(Ity_V128);
13805663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dV = newTemp(Ity_V128);
13806663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
13807663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt rG = gregOfRexRM(pfx,modrm);
13808663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( dV, getXMMReg(rG) );
13809663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
13810663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
13811663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, getXMMReg(rE) );
13812663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
13813663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("pmuludq %s,%s\n", nameXMMReg(rE), nameXMMReg(rG));
13814663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
13815663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
13816663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
13817663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
13818663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("pmuludq %s,%s\n", dis_buf, nameXMMReg(rG));
13819663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
13820663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMReg( rG, mkexpr(math_PMULUDQ_128( sV, dV )) );
13821663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
13823663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* ***--- this is an MMX class insn introduced in SSE2 ---*** */
13824663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F F4 = PMULUDQ -- unsigned widening multiply of 32-lanes 0 x
13825663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         0 to form 64-bit result */
13826663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && sz == 4) {
13827663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sV = newTemp(Ity_I64);
13828663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dV = newTemp(Ity_I64);
13829663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         t1 = newTemp(Ity_I32);
13830663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         t0 = newTemp(Ity_I32);
13831663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
13832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13833663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         do_MMX_preamble();
13834663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( dV, getMMXReg(gregLO3ofRM(modrm)) );
13835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13836663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
13837663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, getMMXReg(eregLO3ofRM(modrm)) );
13838663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
13839663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("pmuludq %s,%s\n", nameMMXReg(eregLO3ofRM(modrm)),
13840663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   nameMMXReg(gregLO3ofRM(modrm)));
13841663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
13842663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
13843663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, loadLE(Ity_I64, mkexpr(addr)) );
13844663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
13845663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("pmuludq %s,%s\n", dis_buf,
13846663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   nameMMXReg(gregLO3ofRM(modrm)));
13847663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
13848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13849663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( t0, unop(Iop_64to32, mkexpr(dV)) );
13850663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( t1, unop(Iop_64to32, mkexpr(sV)) );
13851663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putMMXReg( gregLO3ofRM(modrm),
13852663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    binop( Iop_MullU32, mkexpr(t0), mkexpr(t1) ) );
13853663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13854663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13855663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
13856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13857663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xF5:
13858663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F F5 = PMADDWD -- Multiply and add packed integers from
13859663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         E(xmm or mem) to G(xmm) */
13860663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
13861663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sV = newTemp(Ity_V128);
13862663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dV = newTemp(Ity_V128);
13863663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm     = getUChar(delta);
13864663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG = gregOfRexRM(pfx,modrm);
13865663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
13866663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
13867663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, getXMMReg(rE) );
13868663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
13869663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("pmaddwd %s,%s\n", nameXMMReg(rE), nameXMMReg(rG));
13870663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
13871663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
13872663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
13873663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
13874663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("pmaddwd %s,%s\n", dis_buf, nameXMMReg(rG));
13875663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
13876663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( dV, getXMMReg(rG) );
13877663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMReg( rG, mkexpr(math_PMADDWD_128(dV, sV)) );
13878663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13879663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13880663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
13881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13882663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xF6:
13883663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
13884663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F F6 = PSADBW -- sum of 8Ux8 absolute differences */
13885663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && sz == 4) {
13886663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         do_MMX_preamble();
13887663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_MMXop_regmem_to_reg (
13888663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    vbi, pfx, delta, opc, "psadbw", False );
13889663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
13891663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F F6 = PSADBW -- 2 x (8x8 -> 48 zeroes ++ u16) Sum Abs Diffs
13892663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         from E(xmm or mem) to G(xmm) */
13893663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
13894663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sV  = newTemp(Ity_V128);
13895663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dV  = newTemp(Ity_V128);
13896663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
13897663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG   = gregOfRexRM(pfx,modrm);
13898663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
13899663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
13900663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, getXMMReg(rE) );
13901663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
13902663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("psadbw %s,%s\n", nameXMMReg(rE), nameXMMReg(rG));
13903663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
13904663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
13905663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
13906663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
13907663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("psadbw %s,%s\n", dis_buf, nameXMMReg(rG));
13908663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
13909663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( dV, getXMMReg(rG) );
13910663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMReg( rG, mkexpr( math_PSADBW_128 ( dV, sV ) ) );
13911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13912663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13913663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13914663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
13915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13916663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xF7:
13917663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
13918663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F F7 = MASKMOVQ -- 8x8 masked store */
13919663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && sz == 4) {
13920663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Bool ok = False;
13921663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_MMX( &ok, vbi, pfx, sz, delta-1 );
13922663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (ok) goto decode_success;
13923663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13924663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F F7 = MASKMOVDQU -- store selected bytes of double quadword */
13925663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2 && epartIsReg(getUChar(delta))) {
13926663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_MASKMOVDQU( vbi, pfx, delta, False/*!isAvx*/ );
13927663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13928663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13929663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
13930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13931663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xF8:
13932663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F F8 = PSUBB */
13933663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
13934663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSEint_E_to_G( vbi, pfx, delta,
13935663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    "psubb", Iop_Sub8x16, False );
13936663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13937663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13938663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
13939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13940663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xF9:
13941663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F F9 = PSUBW */
13942663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
13943663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSEint_E_to_G( vbi, pfx, delta,
13944663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    "psubw", Iop_Sub16x8, False );
13945663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13946663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13947663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
13948f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
13949663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xFA:
13950663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F FA = PSUBD */
13951663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
13952663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSEint_E_to_G( vbi, pfx, delta,
13953663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    "psubd", Iop_Sub32x4, False );
13954663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13955f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      }
13956663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
13957f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
13958663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xFB:
13959663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F FB = PSUBQ */
13960663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
13961663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSEint_E_to_G( vbi, pfx, delta,
13962663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    "psubq", Iop_Sub64x2, False );
13963663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13964663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13965663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* ***--- this is an MMX class insn introduced in SSE2 ---*** */
13966663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F FB = PSUBQ -- sub 64x1 */
13967663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && sz == 4) {
13968663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         do_MMX_preamble();
13969663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_MMXop_regmem_to_reg (
13970663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   vbi, pfx, delta, opc, "psubq", False );
13971663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13972f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      }
13973663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
13974f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
13975663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xFC:
13976663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F FC = PADDB */
13977663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
13978663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSEint_E_to_G( vbi, pfx, delta,
13979663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    "paddb", Iop_Add8x16, False );
13980663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13981663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13982663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
13983f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
13984663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xFD:
13985663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F FD = PADDW */
13986663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
13987663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSEint_E_to_G( vbi, pfx, delta,
13988663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    "paddw", Iop_Add16x8, False );
13989663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13990663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
13991663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
13992f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
13993663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xFE:
13994663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F FE = PADDD */
13995663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
13996663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSEint_E_to_G( vbi, pfx, delta,
13997663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    "paddd", Iop_Add32x4, False );
13998663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
13999663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
14000663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
14001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14002663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   default:
14003663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      goto decode_failure;
14004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
14006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14007663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  decode_failure:
14008663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *decode_OK = False;
14009663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return deltaIN;
14010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14011663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  decode_success:
14012663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *decode_OK = True;
14013663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
14014663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
14015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14017663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*------------------------------------------------------------*/
14018663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---                                                      ---*/
14019663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*--- Top-level SSE3 (not SupSSE3): dis_ESC_0F__SSE3       ---*/
14020663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---                                                      ---*/
14021663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*------------------------------------------------------------*/
14022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14023663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_MOVDDUP_128 ( VexAbiInfo* vbi, Prefix pfx,
14024663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              Long delta, Bool isAvx )
14025663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
14026663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr   = IRTemp_INVALID;
14027663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen   = 0;
14028663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
14029663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp sV    = newTemp(Ity_V128);
14030663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp d0    = newTemp(Ity_I64);
14031663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm = getUChar(delta);
14032663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rG    = gregOfRexRM(pfx,modrm);
14033663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (epartIsReg(modrm)) {
14034663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt rE = eregOfRexRM(pfx,modrm);
14035663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( sV, getXMMReg(rE) );
14036663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%smovddup %s,%s\n",
14037663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          isAvx ? "v" : "", nameXMMReg(rE), nameXMMReg(rG));
14038663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1;
14039663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign ( d0, unop(Iop_V128to64, mkexpr(sV)) );
14040663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
14041663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
14042663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( d0, loadLE(Ity_I64, mkexpr(addr)) );
14043663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%smovddup %s,%s\n",
14044663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          isAvx ? "v" : "", dis_buf, nameXMMReg(rG));
14045663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen;
14046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
14047663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   (isAvx ? putYMMRegLoAndZU : putXMMReg)
14048663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ( rG, binop(Iop_64HLtoV128,mkexpr(d0),mkexpr(d0)) );
14049663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
14050663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
14051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14053663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_MOVDDUP_256 ( VexAbiInfo* vbi, Prefix pfx,
14054663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              Long delta )
14055663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
14056663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr   = IRTemp_INVALID;
14057663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen   = 0;
14058663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
14059663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp d0    = newTemp(Ity_I64);
14060663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp d1    = newTemp(Ity_I64);
14061663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm = getUChar(delta);
14062663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rG    = gregOfRexRM(pfx,modrm);
14063663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (epartIsReg(modrm)) {
14064663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt rE = eregOfRexRM(pfx,modrm);
14065663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("vmovddup %s,%s\n", nameYMMReg(rE), nameYMMReg(rG));
14066663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1;
14067663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign ( d0, getYMMRegLane64(rE, 0) );
14068663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign ( d1, getYMMRegLane64(rE, 2) );
14069663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
14070663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
14071663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( d0, loadLE(Ity_I64, mkexpr(addr)) );
14072663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( d1, loadLE(Ity_I64, binop(Iop_Add64,
14073663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        mkexpr(addr), mkU64(16))) );
14074663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("vmovddup %s,%s\n", dis_buf, nameYMMReg(rG));
14075663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen;
14076663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
14077663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putYMMRegLane64( rG, 0, mkexpr(d0) );
14078663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putYMMRegLane64( rG, 1, mkexpr(d0) );
14079663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putYMMRegLane64( rG, 2, mkexpr(d1) );
14080663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putYMMRegLane64( rG, 3, mkexpr(d1) );
14081663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
14082663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
14083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14085663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_MOVSxDUP_128 ( VexAbiInfo* vbi, Prefix pfx,
14086663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               Long delta, Bool isAvx, Bool isL )
14087663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
14088663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr  = IRTemp_INVALID;
14089663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen  = 0;
14090663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
14091663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp sV    = newTemp(Ity_V128);
14092663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm = getUChar(delta);
14093663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rG    = gregOfRexRM(pfx,modrm);
14094663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp s3, s2, s1, s0;
14095663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   s3 = s2 = s1 = s0 = IRTemp_INVALID;
14096663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (epartIsReg(modrm)) {
14097663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt rE = eregOfRexRM(pfx,modrm);
14098663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( sV, getXMMReg(rE) );
14099663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%smovs%cdup %s,%s\n",
14100663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          isAvx ? "v" : "", isL ? 'l' : 'h', nameXMMReg(rE), nameXMMReg(rG));
14101663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1;
14102663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
14103663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
14104663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (!isAvx)
14105663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         gen_SEGV_if_not_16_aligned( addr );
14106663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
14107663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%smovs%cdup %s,%s\n",
14108663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          isAvx ? "v" : "", isL ? 'l' : 'h', dis_buf, nameXMMReg(rG));
14109663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen;
14110663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
14111663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV128to32s( sV, &s3, &s2, &s1, &s0 );
14112663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   (isAvx ? putYMMRegLoAndZU : putXMMReg)
14113663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ( rG, isL ? mkV128from32s( s2, s2, s0, s0 )
14114663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                : mkV128from32s( s3, s3, s1, s1 ) );
14115663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
14116663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
14117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14119663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_MOVSxDUP_256 ( VexAbiInfo* vbi, Prefix pfx,
14120663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               Long delta, Bool isL )
14121663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
14122663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr  = IRTemp_INVALID;
14123663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen  = 0;
14124663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
14125663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp sV    = newTemp(Ity_V256);
14126663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm = getUChar(delta);
14127663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rG    = gregOfRexRM(pfx,modrm);
14128663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp s7, s6, s5, s4, s3, s2, s1, s0;
14129663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   s7 = s6 = s5 = s4 = s3 = s2 = s1 = s0 = IRTemp_INVALID;
14130663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (epartIsReg(modrm)) {
14131663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt rE = eregOfRexRM(pfx,modrm);
14132663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( sV, getYMMReg(rE) );
14133663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("vmovs%cdup %s,%s\n",
14134663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          isL ? 'l' : 'h', nameYMMReg(rE), nameYMMReg(rG));
14135663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1;
14136663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
14137663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
14138663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( sV, loadLE(Ity_V256, mkexpr(addr)) );
14139663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("vmovs%cdup %s,%s\n",
14140663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          isL ? 'l' : 'h', dis_buf, nameYMMReg(rG));
14141663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen;
14142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
14143663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV256to32s( sV, &s7, &s6, &s5, &s4, &s3, &s2, &s1, &s0 );
14144663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putYMMRegLane128( rG, 1, isL ? mkV128from32s( s6, s6, s4, s4 )
14145663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                : mkV128from32s( s7, s7, s5, s5 ) );
14146663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putYMMRegLane128( rG, 0, isL ? mkV128from32s( s2, s2, s0, s0 )
14147663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                : mkV128from32s( s3, s3, s1, s1 ) );
14148663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
14149663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
14150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14152663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRTemp math_HADDPS_128 ( IRTemp dV, IRTemp sV, Bool isAdd )
14153663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
14154663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp s3, s2, s1, s0, d3, d2, d1, d0;
14155663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp leftV  = newTemp(Ity_V128);
14156663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp rightV = newTemp(Ity_V128);
14157663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   s3 = s2 = s1 = s0 = d3 = d2 = d1 = d0 = IRTemp_INVALID;
14158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14159663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV128to32s( sV, &s3, &s2, &s1, &s0 );
14160663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV128to32s( dV, &d3, &d2, &d1, &d0 );
14161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14162663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( leftV,  mkV128from32s( s2, s0, d2, d0 ) );
14163663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( rightV, mkV128from32s( s3, s1, d3, d1 ) );
14164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14165663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp res = newTemp(Ity_V128);
14166663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( res, binop(isAdd ? Iop_Add32Fx4 : Iop_Sub32Fx4,
14167663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              mkexpr(leftV), mkexpr(rightV) ) );
14168663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return res;
14169663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
14170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14172663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRTemp math_HADDPD_128 ( IRTemp dV, IRTemp sV, Bool isAdd )
14173663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
14174663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp s1, s0, d1, d0;
14175663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp leftV  = newTemp(Ity_V128);
14176663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp rightV = newTemp(Ity_V128);
14177663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   s1 = s0 = d1 = d0 = IRTemp_INVALID;
14178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14179663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV128to64s( sV, &s1, &s0 );
14180663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV128to64s( dV, &d1, &d0 );
14181663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
14182663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( leftV,  binop(Iop_64HLtoV128, mkexpr(s0), mkexpr(d0)) );
14183663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( rightV, binop(Iop_64HLtoV128, mkexpr(s1), mkexpr(d1)) );
14184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14185663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp res = newTemp(Ity_V128);
14186663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( res, binop(isAdd ? Iop_Add64Fx2 : Iop_Sub64Fx2,
14187663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              mkexpr(leftV), mkexpr(rightV) ) );
14188663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return res;
14189663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
14190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14192663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng__attribute__((noinline))
14193663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic
14194663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengLong dis_ESC_0F__SSE3 ( Bool* decode_OK,
14195663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        VexAbiInfo* vbi,
14196663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        Prefix pfx, Int sz, Long deltaIN )
14197663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
14198663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr  = IRTemp_INVALID;
14199663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm = 0;
14200663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen  = 0;
14201663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
14202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14203663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *decode_OK = False;
14204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14205663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Long   delta = deltaIN;
14206663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  opc   = getUChar(delta);
14207663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   delta++;
14208663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (opc) {
14209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14210663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x12:
14211663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F3 0F 12 = MOVSLDUP -- move from E (mem or xmm) to G (xmm),
14212663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         duplicating some lanes (2:2:0:0). */
14213663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx) && sz == 4) {
14214663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_MOVSxDUP_128( vbi, pfx, delta, False/*!isAvx*/,
14215663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   True/*isL*/ );
14216663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
14217663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
14218663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F2 0F 12 = MOVDDUP -- move from E (mem or xmm) to G (xmm),
14219663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         duplicating some lanes (0:1:0:1). */
14220663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2no66noF3(pfx)
14221663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (sz == 4 || /* ignore redundant REX.W */ sz == 8)) {
14222663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_MOVDDUP_128( vbi, pfx, delta, False/*!isAvx*/ );
14223663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
14224663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
14225663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
14226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14227663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x16:
14228663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F3 0F 16 = MOVSHDUP -- move from E (mem or xmm) to G (xmm),
14229663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         duplicating some lanes (3:3:1:1). */
14230663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx) && sz == 4) {
14231663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_MOVSxDUP_128( vbi, pfx, delta, False/*!isAvx*/,
14232663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   False/*!isL*/ );
14233663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
14234663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
14235663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
14236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14237663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x7C:
14238663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x7D:
14239663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F2 0F 7C = HADDPS -- 32x4 add across from E (mem or xmm) to G (xmm). */
14240663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F2 0F 7D = HSUBPS -- 32x4 sub across from E (mem or xmm) to G (xmm). */
14241663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2no66noF3(pfx) && sz == 4) {
14242663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp eV     = newTemp(Ity_V128);
14243663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp gV     = newTemp(Ity_V128);
14244663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Bool   isAdd  = opc == 0x7C;
14245663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HChar* str    = isAdd ? "add" : "sub";
14246663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm         = getUChar(delta);
14247663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG     = gregOfRexRM(pfx,modrm);
14248663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
14249663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
14250663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( eV, getXMMReg(rE) );
14251663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("h%sps %s,%s\n", str, nameXMMReg(rE), nameXMMReg(rG));
14252663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
14253663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
14254663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
14255663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( eV, loadLE(Ity_V128, mkexpr(addr)) );
14256663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("h%sps %s,%s\n", str, dis_buf, nameXMMReg(rG));
14257663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
14258663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
14259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14260663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( gV, getXMMReg(rG) );
14261663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMReg( rG, mkexpr( math_HADDPS_128 ( gV, eV, isAdd ) ) );
14262663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
14263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
14264663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 7C = HADDPD -- 64x2 add across from E (mem or xmm) to G (xmm). */
14265663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 7D = HSUBPD -- 64x2 sub across from E (mem or xmm) to G (xmm). */
14266663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
14267663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp eV     = newTemp(Ity_V128);
14268663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp gV     = newTemp(Ity_V128);
14269663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Bool   isAdd  = opc == 0x7C;
14270663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HChar* str    = isAdd ? "add" : "sub";
14271663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm         = getUChar(delta);
14272663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG     = gregOfRexRM(pfx,modrm);
14273663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
14274663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
14275663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( eV, getXMMReg(rE) );
14276663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("h%spd %s,%s\n", str, nameXMMReg(rE), nameXMMReg(rG));
14277663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
14278663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
14279663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
14280663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( eV, loadLE(Ity_V128, mkexpr(addr)) );
14281663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("h%spd %s,%s\n", str, dis_buf, nameXMMReg(rG));
14282663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
14283663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
14284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14285663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( gV, getXMMReg(rG) );
14286663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMReg( rG, mkexpr( math_HADDPD_128 ( gV, eV, isAdd ) ) );
14287663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
14288663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
14289663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
14290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14291663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xD0:
14292663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F D0 = ADDSUBPD -- 64x4 +/- from E (mem or xmm) to G (xmm). */
14293663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
14294663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp eV   = newTemp(Ity_V128);
14295663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp gV   = newTemp(Ity_V128);
14296663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm       = getUChar(delta);
14297663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG   = gregOfRexRM(pfx,modrm);
14298663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
14299663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
14300663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( eV, getXMMReg(rE) );
14301663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("addsubpd %s,%s\n", nameXMMReg(rE), nameXMMReg(rG));
14302663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
14303663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
14304663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
14305663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( eV, loadLE(Ity_V128, mkexpr(addr)) );
14306663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("addsubpd %s,%s\n", dis_buf, nameXMMReg(rG));
14307663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
14308663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
14309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14310663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( gV, getXMMReg(rG) );
14311663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMReg( rG, mkexpr( math_ADDSUBPD_128 ( gV, eV ) ) );
14312663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
14313663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
14314663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F2 0F D0 = ADDSUBPS -- 32x4 +/-/+/- from E (mem or xmm) to G (xmm). */
14315663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2no66noF3(pfx) && sz == 4) {
14316663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp eV   = newTemp(Ity_V128);
14317663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp gV   = newTemp(Ity_V128);
14318663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm       = getUChar(delta);
14319663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG   = gregOfRexRM(pfx,modrm);
14320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14321663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
14322663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
14323663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
14324663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( eV, getXMMReg(rE) );
14325663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("addsubps %s,%s\n", nameXMMReg(rE), nameXMMReg(rG));
14326663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
14327663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
14328663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
14329663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( eV, loadLE(Ity_V128, mkexpr(addr)) );
14330663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("addsubps %s,%s\n", dis_buf, nameXMMReg(rG));
14331663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
14332663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
14333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14334663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( gV, getXMMReg(rG) );
14335663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMReg( rG, mkexpr( math_ADDSUBPS_128 ( gV, eV ) ) );
14336663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
14337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
14338663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
14339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14340663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xF0:
14341663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F2 0F F0 = LDDQU -- move from E (mem or xmm) to G (xmm). */
14342663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2no66noF3(pfx) && sz == 4) {
14343663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
14344663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
14345663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            goto decode_failure;
14346663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
14347663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
14348663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putXMMReg( gregOfRexRM(pfx,modrm),
14349663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       loadLE(Ity_V128, mkexpr(addr)) );
14350663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("lddqu %s,%s\n", dis_buf,
14351663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                 nameXMMReg(gregOfRexRM(pfx,modrm)));
14352663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
14353663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
14354663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
14355663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
14356663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
14357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14358663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   default:
14359663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      goto decode_failure;
14360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
14362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14363663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  decode_failure:
14364663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *decode_OK = False;
14365663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return deltaIN;
14366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14367663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  decode_success:
14368663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *decode_OK = True;
14369663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
14370663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
14371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14373663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*------------------------------------------------------------*/
14374663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---                                                      ---*/
14375663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*--- Top-level SSSE3: dis_ESC_0F38__SupSSE3               ---*/
14376663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---                                                      ---*/
14377663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*------------------------------------------------------------*/
14378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14379663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic
14380663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengIRTemp math_PSHUFB_XMM ( IRTemp dV/*data to perm*/, IRTemp sV/*perm*/ )
14381663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
14382663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp sHi        = newTemp(Ity_I64);
14383663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp sLo        = newTemp(Ity_I64);
14384663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp dHi        = newTemp(Ity_I64);
14385663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp dLo        = newTemp(Ity_I64);
14386663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp rHi        = newTemp(Ity_I64);
14387663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp rLo        = newTemp(Ity_I64);
14388663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp sevens     = newTemp(Ity_I64);
14389663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp mask0x80hi = newTemp(Ity_I64);
14390663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp mask0x80lo = newTemp(Ity_I64);
14391663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp maskBit3hi = newTemp(Ity_I64);
14392663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp maskBit3lo = newTemp(Ity_I64);
14393663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp sAnd7hi    = newTemp(Ity_I64);
14394663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp sAnd7lo    = newTemp(Ity_I64);
14395663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp permdHi    = newTemp(Ity_I64);
14396663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp permdLo    = newTemp(Ity_I64);
14397663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp res        = newTemp(Ity_V128);
14398663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
14399663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( dHi, unop(Iop_V128HIto64, mkexpr(dV)) );
14400663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( dLo, unop(Iop_V128to64,   mkexpr(dV)) );
14401663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( sHi, unop(Iop_V128HIto64, mkexpr(sV)) );
14402663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( sLo, unop(Iop_V128to64,   mkexpr(sV)) );
14403663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
14404663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( sevens, mkU64(0x0707070707070707ULL) );
14405663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
14406663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* mask0x80hi = Not(SarN8x8(sHi,7))
14407663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      maskBit3hi = SarN8x8(ShlN8x8(sHi,4),7)
14408663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      sAnd7hi    = And(sHi,sevens)
14409663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      permdHi    = Or( And(Perm8x8(dHi,sAnd7hi),maskBit3hi),
14410663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      And(Perm8x8(dLo,sAnd7hi),Not(maskBit3hi)) )
14411663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      rHi        = And(permdHi,mask0x80hi)
14412663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   */
14413663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(
14414663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      mask0x80hi,
14415663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      unop(Iop_Not64, binop(Iop_SarN8x8,mkexpr(sHi),mkU8(7))));
14416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14417663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(
14418663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      maskBit3hi,
14419663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      binop(Iop_SarN8x8,
14420663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            binop(Iop_ShlN8x8,mkexpr(sHi),mkU8(4)),
14421663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            mkU8(7)));
14422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14423663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(sAnd7hi, binop(Iop_And64,mkexpr(sHi),mkexpr(sevens)));
14424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14425663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(
14426663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      permdHi,
14427663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      binop(
14428663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Iop_Or64,
14429663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         binop(Iop_And64,
14430663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               binop(Iop_Perm8x8,mkexpr(dHi),mkexpr(sAnd7hi)),
14431663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               mkexpr(maskBit3hi)),
14432663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         binop(Iop_And64,
14433663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               binop(Iop_Perm8x8,mkexpr(dLo),mkexpr(sAnd7hi)),
14434663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               unop(Iop_Not64,mkexpr(maskBit3hi))) ));
14435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14436663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(rHi, binop(Iop_And64,mkexpr(permdHi),mkexpr(mask0x80hi)) );
14437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14438663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* And the same for the lower half of the result.  What fun. */
14439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14440663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(
14441663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      mask0x80lo,
14442663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      unop(Iop_Not64, binop(Iop_SarN8x8,mkexpr(sLo),mkU8(7))));
14443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14444663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(
14445663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      maskBit3lo,
14446663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      binop(Iop_SarN8x8,
14447663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            binop(Iop_ShlN8x8,mkexpr(sLo),mkU8(4)),
14448663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            mkU8(7)));
14449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14450663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(sAnd7lo, binop(Iop_And64,mkexpr(sLo),mkexpr(sevens)));
14451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14452663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(
14453663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      permdLo,
14454663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      binop(
14455663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Iop_Or64,
14456663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         binop(Iop_And64,
14457663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               binop(Iop_Perm8x8,mkexpr(dHi),mkexpr(sAnd7lo)),
14458663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               mkexpr(maskBit3lo)),
14459663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         binop(Iop_And64,
14460663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               binop(Iop_Perm8x8,mkexpr(dLo),mkexpr(sAnd7lo)),
14461663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               unop(Iop_Not64,mkexpr(maskBit3lo))) ));
14462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14463663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(rLo, binop(Iop_And64,mkexpr(permdLo),mkexpr(mask0x80lo)) );
14464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14465663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(res, binop(Iop_64HLtoV128, mkexpr(rHi), mkexpr(rLo)));
14466663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return res;
14467663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
14468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14470663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_PHADD_128 ( VexAbiInfo* vbi, Prefix pfx, Long delta,
14471663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            Bool isAvx, UChar opc )
14472663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
14473663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr   = IRTemp_INVALID;
14474663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen   = 0;
14475663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
14476663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar* str    = "???";
14477663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IROp   opV64  = Iop_INVALID;
14478663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IROp   opCatO = Iop_CatOddLanes16x4;
14479663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IROp   opCatE = Iop_CatEvenLanes16x4;
14480663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp sV     = newTemp(Ity_V128);
14481663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp dV     = newTemp(Ity_V128);
14482663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp sHi    = newTemp(Ity_I64);
14483663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp sLo    = newTemp(Ity_I64);
14484663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp dHi    = newTemp(Ity_I64);
14485663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp dLo    = newTemp(Ity_I64);
14486663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm  = getUChar(delta);
14487663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rG     = gregOfRexRM(pfx,modrm);
14488663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rV     = isAvx ? getVexNvvvv(pfx) : rG;
14489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14490663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (opc) {
14491663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x01: opV64 = Iop_Add16x4;   str = "addw";  break;
14492663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x02: opV64 = Iop_Add32x2;   str = "addd";  break;
14493663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x03: opV64 = Iop_QAdd16Sx4; str = "addsw"; break;
14494663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x05: opV64 = Iop_Sub16x4;   str = "subw";  break;
14495663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x06: opV64 = Iop_Sub32x2;   str = "subd";  break;
14496663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x07: opV64 = Iop_QSub16Sx4; str = "subsw"; break;
14497663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default: vassert(0);
14498663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
14499663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (opc == 0x02 || opc == 0x06) {
14500663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      opCatO = Iop_InterleaveHI32x2;
14501663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      opCatE = Iop_InterleaveLO32x2;
14502663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
14503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14504663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( dV, getXMMReg(rV) );
14505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14506663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (epartIsReg(modrm)) {
14507663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt rE = eregOfRexRM(pfx,modrm);
14508663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( sV, getXMMReg(rE) );
14509663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("ph%s %s,%s\n", str, nameXMMReg(rE), nameXMMReg(rG));
14510663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1;
14511663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
14512663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
14513663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (!isAvx)
14514663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         gen_SEGV_if_not_16_aligned( addr );
14515663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
14516663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("ph%s %s,%s\n", str, dis_buf, nameXMMReg(rG));
14517663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen;
14518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
14519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14520663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( dHi, unop(Iop_V128HIto64, mkexpr(dV)) );
14521663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( dLo, unop(Iop_V128to64,   mkexpr(dV)) );
14522663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( sHi, unop(Iop_V128HIto64, mkexpr(sV)) );
14523663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( sLo, unop(Iop_V128to64,   mkexpr(sV)) );
14524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14525663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* This isn't a particularly efficient way to compute the
14526663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      result, but at least it avoids a proliferation of IROps,
14527663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      hence avoids complication all the backends. */
14528663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
14529663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   (isAvx ? putYMMRegLoAndZU : putXMMReg)
14530663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ( rG,
14531663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        binop(Iop_64HLtoV128,
14532663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              binop(opV64,
14533663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    binop(opCatE,mkexpr(sHi),mkexpr(sLo)),
14534663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    binop(opCatO,mkexpr(sHi),mkexpr(sLo)) ),
14535663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              binop(opV64,
14536663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    binop(opCatE,mkexpr(dHi),mkexpr(dLo)),
14537663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    binop(opCatO,mkexpr(dHi),mkexpr(dLo)) ) ) );
14538663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
14539663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
14540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14542663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRTemp math_PMADDUBSW_128 ( IRTemp dV, IRTemp sV )
14543663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
14544663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp sVoddsSX  = newTemp(Ity_V128);
14545663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp sVevensSX = newTemp(Ity_V128);
14546663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp dVoddsZX  = newTemp(Ity_V128);
14547663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp dVevensZX = newTemp(Ity_V128);
14548663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* compute dV unsigned x sV signed */
14549663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( sVoddsSX, binop(Iop_SarN16x8, mkexpr(sV), mkU8(8)) );
14550663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( sVevensSX, binop(Iop_SarN16x8,
14551663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            binop(Iop_ShlN16x8, mkexpr(sV), mkU8(8)),
14552663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            mkU8(8)) );
14553663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( dVoddsZX, binop(Iop_ShrN16x8, mkexpr(dV), mkU8(8)) );
14554663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( dVevensZX, binop(Iop_ShrN16x8,
14555663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            binop(Iop_ShlN16x8, mkexpr(dV), mkU8(8)),
14556663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            mkU8(8)) );
14557663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
14558663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp res = newTemp(Ity_V128);
14559663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( res, binop(Iop_QAdd16Sx8,
14560663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      binop(Iop_Mul16x8, mkexpr(sVoddsSX), mkexpr(dVoddsZX)),
14561663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      binop(Iop_Mul16x8, mkexpr(sVevensSX), mkexpr(dVevensZX))
14562663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     )
14563663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         );
14564663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return res;
14565663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
14566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14568663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng__attribute__((noinline))
14569663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic
14570663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengLong dis_ESC_0F38__SupSSE3 ( Bool* decode_OK,
14571663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             VexAbiInfo* vbi,
14572663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             Prefix pfx, Int sz, Long deltaIN )
14573663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
14574663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr  = IRTemp_INVALID;
14575663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm = 0;
14576663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen  = 0;
14577663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
14578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14579663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *decode_OK = False;
14580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14581663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Long   delta = deltaIN;
14582663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  opc   = getUChar(delta);
14583663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   delta++;
14584663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (opc) {
14585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14586663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x00:
14587663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 38 00 = PSHUFB -- Packed Shuffle Bytes 8x16 (XMM) */
14588663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
14589663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (sz == 2 || /*redundant REX.W*/ sz == 8)) {
14590663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sV = newTemp(Ity_V128);
14591663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dV = newTemp(Ity_V128);
14592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14593663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
14594663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( dV, getXMMReg(gregOfRexRM(pfx,modrm)) );
14595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14596663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
14597663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, getXMMReg(eregOfRexRM(pfx,modrm)) );
14598663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
14599663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("pshufb %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)),
14600663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  nameXMMReg(gregOfRexRM(pfx,modrm)));
14601663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
14602663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
14603663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gen_SEGV_if_not_16_aligned( addr );
14604663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
14605663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
14606663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("pshufb %s,%s\n", dis_buf,
14607663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  nameXMMReg(gregOfRexRM(pfx,modrm)));
14608663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
14609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14610663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp res = math_PSHUFB_XMM( dV, sV );
14611663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMReg(gregOfRexRM(pfx,modrm), mkexpr(res));
14612663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
14613663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
14614663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 38 00 = PSHUFB -- Packed Shuffle Bytes 8x8 (MMX) */
14615663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && sz == 4) {
14616663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sV      = newTemp(Ity_I64);
14617663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dV      = newTemp(Ity_I64);
14618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14619663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
14620663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         do_MMX_preamble();
14621663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( dV, getMMXReg(gregLO3ofRM(modrm)) );
14622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14623663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
14624663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, getMMXReg(eregLO3ofRM(modrm)) );
14625663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
14626663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("pshufb %s,%s\n", nameMMXReg(eregLO3ofRM(modrm)),
14627663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  nameMMXReg(gregLO3ofRM(modrm)));
14628663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
14629663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
14630663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, loadLE(Ity_I64, mkexpr(addr)) );
14631663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
14632663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("pshufb %s,%s\n", dis_buf,
14633663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  nameMMXReg(gregLO3ofRM(modrm)));
14634663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
14635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14636663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putMMXReg(
14637663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gregLO3ofRM(modrm),
14638663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            binop(
14639663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               Iop_And64,
14640663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* permute the lanes */
14641663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               binop(
14642663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  Iop_Perm8x8,
14643663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  mkexpr(dV),
14644663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  binop(Iop_And64, mkexpr(sV), mkU64(0x0707070707070707ULL))
14645663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               ),
14646663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* mask off lanes which have (index & 0x80) == 0x80 */
14647663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               unop(Iop_Not64, binop(Iop_SarN8x8, mkexpr(sV), mkU8(7)))
14648663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            )
14649663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         );
14650663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
14651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
14652663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
14653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14654663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x01:
14655663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x02:
14656663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x03:
14657663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x05:
14658663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x06:
14659663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x07:
14660663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 38 01 = PHADDW -- 16x8 add across from E (mem or xmm) and
14661663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         G to G (xmm). */
14662663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 38 02 = PHADDD -- 32x4 add across from E (mem or xmm) and
14663663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         G to G (xmm). */
14664663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 38 03 = PHADDSW -- 16x8 signed qadd across from E (mem or
14665663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         xmm) and G to G (xmm). */
14666663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 38 05 = PHSUBW -- 16x8 sub across from E (mem or xmm) and
14667663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         G to G (xmm). */
14668663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 38 06 = PHSUBD -- 32x4 sub across from E (mem or xmm) and
14669663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         G to G (xmm). */
14670663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 38 07 = PHSUBSW -- 16x8 signed qsub across from E (mem or
14671663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         xmm) and G to G (xmm). */
14672663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
14673663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (sz == 2 || /*redundant REX.W*/ sz == 8)) {
14674663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_PHADD_128( vbi, pfx, delta, False/*isAvx*/, opc );
14675663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
14676663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
14677663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* ***--- these are MMX class insns introduced in SSSE3 ---*** */
14678663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 38 01 = PHADDW -- 16x4 add across from E (mem or mmx) and G
14679663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         to G (mmx). */
14680663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 38 02 = PHADDD -- 32x2 add across from E (mem or mmx) and G
14681663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         to G (mmx). */
14682663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 38 03 = PHADDSW -- 16x4 signed qadd across from E (mem or
14683663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         mmx) and G to G (mmx). */
14684663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 38 05 = PHSUBW -- 16x4 sub across from E (mem or mmx) and G
14685663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         to G (mmx). */
14686663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 38 06 = PHSUBD -- 32x2 sub across from E (mem or mmx) and G
14687663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         to G (mmx). */
14688663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 38 07 = PHSUBSW -- 16x4 signed qsub across from E (mem or
14689663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         mmx) and G to G (mmx). */
14690663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && sz == 4) {
14691663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HChar* str    = "???";
14692663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IROp   opV64  = Iop_INVALID;
14693663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IROp   opCatO = Iop_CatOddLanes16x4;
14694663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IROp   opCatE = Iop_CatEvenLanes16x4;
14695663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sV     = newTemp(Ity_I64);
14696663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dV     = newTemp(Ity_I64);
14697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14698663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
14699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14700663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         switch (opc) {
14701663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 0x01: opV64 = Iop_Add16x4;   str = "addw";  break;
14702663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 0x02: opV64 = Iop_Add32x2;   str = "addd";  break;
14703663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 0x03: opV64 = Iop_QAdd16Sx4; str = "addsw"; break;
14704663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 0x05: opV64 = Iop_Sub16x4;   str = "subw";  break;
14705663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 0x06: opV64 = Iop_Sub32x2;   str = "subd";  break;
14706663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 0x07: opV64 = Iop_QSub16Sx4; str = "subsw"; break;
14707663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            default: vassert(0);
14708663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
14709663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (opc == 0x02 || opc == 0x06) {
14710663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            opCatO = Iop_InterleaveHI32x2;
14711663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            opCatE = Iop_InterleaveLO32x2;
14712663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
14713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14714663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         do_MMX_preamble();
14715663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( dV, getMMXReg(gregLO3ofRM(modrm)) );
14716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14717663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
14718663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, getMMXReg(eregLO3ofRM(modrm)) );
14719663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
14720663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("ph%s %s,%s\n", str, nameMMXReg(eregLO3ofRM(modrm)),
14721663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                     nameMMXReg(gregLO3ofRM(modrm)));
14722663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
14723663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
14724663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, loadLE(Ity_I64, mkexpr(addr)) );
14725663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
14726663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("ph%s %s,%s\n", str, dis_buf,
14727663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                     nameMMXReg(gregLO3ofRM(modrm)));
14728663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
14729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14730663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putMMXReg(
14731663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gregLO3ofRM(modrm),
14732663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            binop(opV64,
14733663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  binop(opCatE,mkexpr(sV),mkexpr(dV)),
14734663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  binop(opCatO,mkexpr(sV),mkexpr(dV))
14735663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            )
14736663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         );
14737663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
14738663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
14739663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
14740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14741663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x04:
14742663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 38 04 = PMADDUBSW -- Multiply and Add Packed Signed and
14743663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Unsigned Bytes (XMM) */
14744663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
14745663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (sz == 2 || /*redundant REX.W*/ sz == 8)) {
14746663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sV = newTemp(Ity_V128);
14747663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dV = newTemp(Ity_V128);
14748663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm     = getUChar(delta);
14749663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG = gregOfRexRM(pfx,modrm);
14750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14751663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( dV, getXMMReg(rG) );
14752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14753663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
14754663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
14755663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, getXMMReg(rE) );
14756663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
14757663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("pmaddubsw %s,%s\n", nameXMMReg(rE), nameXMMReg(rG));
14758663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
14759663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
14760663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gen_SEGV_if_not_16_aligned( addr );
14761663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
14762663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
14763663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("pmaddubsw %s,%s\n", dis_buf, nameXMMReg(rG));
14764663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
14765f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
14766663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMReg( rG, mkexpr( math_PMADDUBSW_128( dV, sV ) ) );
14767663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
14768663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
14769663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 38 04 = PMADDUBSW -- Multiply and Add Packed Signed and
14770663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Unsigned Bytes (MMX) */
14771663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && sz == 4) {
14772663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sV        = newTemp(Ity_I64);
14773663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dV        = newTemp(Ity_I64);
14774663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sVoddsSX  = newTemp(Ity_I64);
14775663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sVevensSX = newTemp(Ity_I64);
14776663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dVoddsZX  = newTemp(Ity_I64);
14777663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dVevensZX = newTemp(Ity_I64);
14778f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
14779663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
14780663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         do_MMX_preamble();
14781663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( dV, getMMXReg(gregLO3ofRM(modrm)) );
14782f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
14783663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
14784663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, getMMXReg(eregLO3ofRM(modrm)) );
14785663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
14786663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("pmaddubsw %s,%s\n", nameMMXReg(eregLO3ofRM(modrm)),
14787663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                     nameMMXReg(gregLO3ofRM(modrm)));
14788663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
14789663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
14790663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, loadLE(Ity_I64, mkexpr(addr)) );
14791663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
14792663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("pmaddubsw %s,%s\n", dis_buf,
14793663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                     nameMMXReg(gregLO3ofRM(modrm)));
14794663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
14795f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
14796663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* compute dV unsigned x sV signed */
14797663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( sVoddsSX,
14798663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 binop(Iop_SarN16x4, mkexpr(sV), mkU8(8)) );
14799663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( sVevensSX,
14800663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 binop(Iop_SarN16x4,
14801663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       binop(Iop_ShlN16x4, mkexpr(sV), mkU8(8)),
14802663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       mkU8(8)) );
14803663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( dVoddsZX,
14804663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 binop(Iop_ShrN16x4, mkexpr(dV), mkU8(8)) );
14805663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( dVevensZX,
14806663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 binop(Iop_ShrN16x4,
14807663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       binop(Iop_ShlN16x4, mkexpr(dV), mkU8(8)),
14808663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       mkU8(8)) );
14809663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
14810663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putMMXReg(
14811663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gregLO3ofRM(modrm),
14812663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            binop(Iop_QAdd16Sx4,
14813663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  binop(Iop_Mul16x4, mkexpr(sVoddsSX), mkexpr(dVoddsZX)),
14814663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  binop(Iop_Mul16x4, mkexpr(sVevensSX), mkexpr(dVevensZX))
14815663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            )
14816663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         );
14817663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
14818f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      }
14819663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
14820f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
14821663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x08:
14822663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x09:
14823663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x0A:
14824663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 38 08 = PSIGNB -- Packed Sign 8x16 (XMM) */
14825663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 38 09 = PSIGNW -- Packed Sign 16x8 (XMM) */
14826663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 38 0A = PSIGND -- Packed Sign 32x4 (XMM) */
14827663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
14828663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (sz == 2 || /*redundant REX.W*/ sz == 8)) {
14829663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sV      = newTemp(Ity_V128);
14830663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dV      = newTemp(Ity_V128);
14831663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sHi     = newTemp(Ity_I64);
14832663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sLo     = newTemp(Ity_I64);
14833663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dHi     = newTemp(Ity_I64);
14834663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dLo     = newTemp(Ity_I64);
14835663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HChar* str     = "???";
14836663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int    laneszB = 0;
14837663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
14838663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         switch (opc) {
14839663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 0x08: laneszB = 1; str = "b"; break;
14840663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 0x09: laneszB = 2; str = "w"; break;
14841663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 0x0A: laneszB = 4; str = "d"; break;
14842663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            default: vassert(0);
14843663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
14844f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
14845663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
14846663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( dV, getXMMReg(gregOfRexRM(pfx,modrm)) );
14847f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
14848663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
14849663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, getXMMReg(eregOfRexRM(pfx,modrm)) );
14850663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
14851663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("psign%s %s,%s\n", str, nameXMMReg(eregOfRexRM(pfx,modrm)),
14852663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        nameXMMReg(gregOfRexRM(pfx,modrm)));
14853663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
14854663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
14855663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gen_SEGV_if_not_16_aligned( addr );
14856663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
14857663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
14858663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("psign%s %s,%s\n", str, dis_buf,
14859663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        nameXMMReg(gregOfRexRM(pfx,modrm)));
14860663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
14861f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
14862663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( dHi, unop(Iop_V128HIto64, mkexpr(dV)) );
14863663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( dLo, unop(Iop_V128to64,   mkexpr(dV)) );
14864663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( sHi, unop(Iop_V128HIto64, mkexpr(sV)) );
14865663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( sLo, unop(Iop_V128to64,   mkexpr(sV)) );
14866f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
14867663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMReg(
14868663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gregOfRexRM(pfx,modrm),
14869663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            binop(Iop_64HLtoV128,
14870663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  dis_PSIGN_helper( mkexpr(sHi), mkexpr(dHi), laneszB ),
14871663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  dis_PSIGN_helper( mkexpr(sLo), mkexpr(dLo), laneszB )
14872663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            )
14873663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         );
14874663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
14875663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
14876663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 38 08 = PSIGNB -- Packed Sign 8x8  (MMX) */
14877663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 38 09 = PSIGNW -- Packed Sign 16x4 (MMX) */
14878663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 38 0A = PSIGND -- Packed Sign 32x2 (MMX) */
14879663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && sz == 4) {
14880663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sV      = newTemp(Ity_I64);
14881663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dV      = newTemp(Ity_I64);
14882663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HChar* str     = "???";
14883663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int    laneszB = 0;
14884663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
14885663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         switch (opc) {
14886663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 0x08: laneszB = 1; str = "b"; break;
14887663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 0x09: laneszB = 2; str = "w"; break;
14888663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 0x0A: laneszB = 4; str = "d"; break;
14889663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            default: vassert(0);
14890663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
14891f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
14892663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
14893663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         do_MMX_preamble();
14894663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( dV, getMMXReg(gregLO3ofRM(modrm)) );
14895f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
14896663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
14897663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, getMMXReg(eregLO3ofRM(modrm)) );
14898663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
14899663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("psign%s %s,%s\n", str, nameMMXReg(eregLO3ofRM(modrm)),
14900663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        nameMMXReg(gregLO3ofRM(modrm)));
14901663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
14902663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
14903663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, loadLE(Ity_I64, mkexpr(addr)) );
14904663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
14905663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("psign%s %s,%s\n", str, dis_buf,
14906663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        nameMMXReg(gregLO3ofRM(modrm)));
14907663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
14908f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
14909663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putMMXReg(
14910663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gregLO3ofRM(modrm),
14911663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            dis_PSIGN_helper( mkexpr(sV), mkexpr(dV), laneszB )
14912663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         );
14913663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
14914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
14915663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
14916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14917663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x0B:
14918663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 38 0B = PMULHRSW -- Packed Multiply High with Round and
14919663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Scale (XMM) */
14920663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
14921663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (sz == 2 || /*redundant REX.W*/ sz == 8)) {
14922663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sV  = newTemp(Ity_V128);
14923663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dV  = newTemp(Ity_V128);
14924663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sHi = newTemp(Ity_I64);
14925663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sLo = newTemp(Ity_I64);
14926663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dHi = newTemp(Ity_I64);
14927663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dLo = newTemp(Ity_I64);
14928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14929663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
14930663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( dV, getXMMReg(gregOfRexRM(pfx,modrm)) );
14931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14932663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
14933663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, getXMMReg(eregOfRexRM(pfx,modrm)) );
14934663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
14935663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("pmulhrsw %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)),
14936663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    nameXMMReg(gregOfRexRM(pfx,modrm)));
14937663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
14938663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
14939663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gen_SEGV_if_not_16_aligned( addr );
14940663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
14941663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
14942663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("pmulhrsw %s,%s\n", dis_buf,
14943663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    nameXMMReg(gregOfRexRM(pfx,modrm)));
14944663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
14945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14946663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( dHi, unop(Iop_V128HIto64, mkexpr(dV)) );
14947663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( dLo, unop(Iop_V128to64,   mkexpr(dV)) );
14948663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( sHi, unop(Iop_V128HIto64, mkexpr(sV)) );
14949663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( sLo, unop(Iop_V128to64,   mkexpr(sV)) );
14950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14951663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMReg(
14952663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gregOfRexRM(pfx,modrm),
14953663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            binop(Iop_64HLtoV128,
14954663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  dis_PMULHRSW_helper( mkexpr(sHi), mkexpr(dHi) ),
14955663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  dis_PMULHRSW_helper( mkexpr(sLo), mkexpr(dLo) )
14956663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            )
14957663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         );
14958663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
14959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
14960663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 38 0B = PMULHRSW -- Packed Multiply High with Round and Scale
14961663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         (MMX) */
14962663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && sz == 4) {
14963663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sV = newTemp(Ity_I64);
14964663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dV = newTemp(Ity_I64);
14965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14966663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
14967663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         do_MMX_preamble();
14968663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( dV, getMMXReg(gregLO3ofRM(modrm)) );
14969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14970663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
14971663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, getMMXReg(eregLO3ofRM(modrm)) );
14972663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
14973663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("pmulhrsw %s,%s\n", nameMMXReg(eregLO3ofRM(modrm)),
14974663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    nameMMXReg(gregLO3ofRM(modrm)));
14975663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
14976663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
14977663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, loadLE(Ity_I64, mkexpr(addr)) );
14978663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
14979663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("pmulhrsw %s,%s\n", dis_buf,
14980663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    nameMMXReg(gregLO3ofRM(modrm)));
14981663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
14982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14983663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putMMXReg(
14984663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gregLO3ofRM(modrm),
14985663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            dis_PMULHRSW_helper( mkexpr(sV), mkexpr(dV) )
14986663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         );
14987663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
14988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
14989663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
14990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14991663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x1C:
14992663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x1D:
14993663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x1E:
14994663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 38 1C = PABSB -- Packed Absolute Value 8x16 (XMM) */
14995663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 38 1D = PABSW -- Packed Absolute Value 16x8 (XMM) */
14996663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 38 1E = PABSD -- Packed Absolute Value 32x4 (XMM) */
14997663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
14998663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (sz == 2 || /*redundant REX.W*/ sz == 8)) {
14999663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sV  = newTemp(Ity_V128);
15000663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HChar* str = "???";
15001663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int    laneszB = 0;
15002663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15003663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         switch (opc) {
15004663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 0x1C: laneszB = 1; str = "b"; break;
15005663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 0x1D: laneszB = 2; str = "w"; break;
15006663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 0x1E: laneszB = 4; str = "d"; break;
15007663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            default: vassert(0);
15008663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
15009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15010663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
15011663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
15012663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, getXMMReg(eregOfRexRM(pfx,modrm)) );
15013663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
15014663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("pabs%s %s,%s\n", str, nameXMMReg(eregOfRexRM(pfx,modrm)),
15015663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                       nameXMMReg(gregOfRexRM(pfx,modrm)));
15016663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
15017663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
15018663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gen_SEGV_if_not_16_aligned( addr );
15019663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
15020663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
15021663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("pabs%s %s,%s\n", str, dis_buf,
15022663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                       nameXMMReg(gregOfRexRM(pfx,modrm)));
15023663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
15024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15025663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMReg( gregOfRexRM(pfx,modrm),
15026663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    mkexpr(math_PABS_XMM(sV, laneszB)) );
15027663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
15028663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
15029663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 38 1C = PABSB -- Packed Absolute Value 8x8  (MMX) */
15030663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 38 1D = PABSW -- Packed Absolute Value 16x4 (MMX) */
15031663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 38 1E = PABSD -- Packed Absolute Value 32x2 (MMX) */
15032663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && sz == 4) {
15033663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sV      = newTemp(Ity_I64);
15034663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HChar* str     = "???";
15035663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int    laneszB = 0;
15036663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15037663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         switch (opc) {
15038663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 0x1C: laneszB = 1; str = "b"; break;
15039663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 0x1D: laneszB = 2; str = "w"; break;
15040663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 0x1E: laneszB = 4; str = "d"; break;
15041663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            default: vassert(0);
15042663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
15043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15044663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
15045663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         do_MMX_preamble();
15046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15047663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
15048663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, getMMXReg(eregLO3ofRM(modrm)) );
15049663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
15050663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("pabs%s %s,%s\n", str, nameMMXReg(eregLO3ofRM(modrm)),
15051663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                       nameMMXReg(gregLO3ofRM(modrm)));
15052663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
15053663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
15054663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, loadLE(Ity_I64, mkexpr(addr)) );
15055663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
15056663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("pabs%s %s,%s\n", str, dis_buf,
15057663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                       nameMMXReg(gregLO3ofRM(modrm)));
15058663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
15059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15060663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putMMXReg( gregLO3ofRM(modrm),
15061663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    mkexpr(math_PABS_MMX( sV, laneszB )) );
15062663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
15063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
15064663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
15065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15066663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   default:
15067663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
15068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15069663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
15070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15071663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  //decode_failure:
15072663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *decode_OK = False;
15073663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return deltaIN;
15074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15075663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  decode_success:
15076663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *decode_OK = True;
15077663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
15078663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
15079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15081663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*------------------------------------------------------------*/
15082663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---                                                      ---*/
15083663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*--- Top-level SSSE3: dis_ESC_0F3A__SupSSE3               ---*/
15084663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---                                                      ---*/
15085663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*------------------------------------------------------------*/
15086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15087663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng__attribute__((noinline))
15088663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic
15089663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengLong dis_ESC_0F3A__SupSSE3 ( Bool* decode_OK,
15090663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             VexAbiInfo* vbi,
15091663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             Prefix pfx, Int sz, Long deltaIN )
15092663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
15093663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Long   d64   = 0;
15094663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr  = IRTemp_INVALID;
15095663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm = 0;
15096663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen  = 0;
15097663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
15098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15099663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *decode_OK = False;
15100663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15101663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Long   delta = deltaIN;
15102663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  opc   = getUChar(delta);
15103663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   delta++;
15104663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (opc) {
15105663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15106663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x0F:
15107663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 3A 0F = PALIGNR -- Packed Align Right (XMM) */
15108663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
15109663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (sz == 2 || /*redundant REX.W*/ sz == 8)) {
15110663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sV  = newTemp(Ity_V128);
15111663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dV  = newTemp(Ity_V128);
15112663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15113663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
15114663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( dV, getXMMReg(gregOfRexRM(pfx,modrm)) );
15115663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15116663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
15117663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, getXMMReg(eregOfRexRM(pfx,modrm)) );
15118663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            d64 = (Long)getUChar(delta+1);
15119663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1+1;
15120663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("palignr $%d,%s,%s\n", (Int)d64,
15121663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                       nameXMMReg(eregOfRexRM(pfx,modrm)),
15122663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                       nameXMMReg(gregOfRexRM(pfx,modrm)));
15123663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
15124663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 1 );
15125663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gen_SEGV_if_not_16_aligned( addr );
15126663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
15127663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            d64 = (Long)getUChar(delta+alen);
15128663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen+1;
15129663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("palignr $%d,%s,%s\n", (Int)d64,
15130663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                       dis_buf,
15131663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                       nameXMMReg(gregOfRexRM(pfx,modrm)));
15132663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
15133663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15134663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp res = math_PALIGNR_XMM( sV, dV, d64 );
15135663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMReg( gregOfRexRM(pfx,modrm), mkexpr(res) );
15136663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
15137663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
15138663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 3A 0F = PALIGNR -- Packed Align Right (MMX) */
15139663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && sz == 4) {
15140663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sV  = newTemp(Ity_I64);
15141663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dV  = newTemp(Ity_I64);
15142663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp res = newTemp(Ity_I64);
15143663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15144663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
15145663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         do_MMX_preamble();
15146663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( dV, getMMXReg(gregLO3ofRM(modrm)) );
15147663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15148663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
15149663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, getMMXReg(eregLO3ofRM(modrm)) );
15150663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            d64 = (Long)getUChar(delta+1);
15151663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1+1;
15152663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("palignr $%d,%s,%s\n",  (Int)d64,
15153663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        nameMMXReg(eregLO3ofRM(modrm)),
15154663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        nameMMXReg(gregLO3ofRM(modrm)));
15155663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
15156663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 1 );
15157663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, loadLE(Ity_I64, mkexpr(addr)) );
15158663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            d64 = (Long)getUChar(delta+alen);
15159663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen+1;
15160663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("palignr $%d%s,%s\n", (Int)d64,
15161663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                      dis_buf,
15162663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                      nameMMXReg(gregLO3ofRM(modrm)));
15163663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
15164663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15165663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (d64 == 0) {
15166663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( res, mkexpr(sV) );
15167663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
15168663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         else if (d64 >= 1 && d64 <= 7) {
15169663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(res,
15170663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   binop(Iop_Or64,
15171663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         binop(Iop_Shr64, mkexpr(sV), mkU8(8*d64)),
15172663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         binop(Iop_Shl64, mkexpr(dV), mkU8(8*(8-d64))
15173663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        )));
15174663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
15175663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         else if (d64 == 8) {
15176663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           assign( res, mkexpr(dV) );
15177663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
15178663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         else if (d64 >= 9 && d64 <= 15) {
15179663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( res, binop(Iop_Shr64, mkexpr(dV), mkU8(8*(d64-8))) );
15180663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
15181663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         else if (d64 >= 16 && d64 <= 255) {
15182663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( res, mkU64(0) );
15183663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
15184663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         else
15185663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            vassert(0);
15186663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15187663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putMMXReg( gregLO3ofRM(modrm), mkexpr(res) );
15188663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
15189663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
15190663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
15191663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15192663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   default:
15193663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
15194663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15195663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
15196663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15197663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  //decode_failure:
15198663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *decode_OK = False;
15199663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return deltaIN;
15200663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15201663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  decode_success:
15202663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *decode_OK = True;
15203663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
15204663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
15205663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15206663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15207663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*------------------------------------------------------------*/
15208663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---                                                      ---*/
15209663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*--- Top-level SSE4: dis_ESC_0F__SSE4                     ---*/
15210663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---                                                      ---*/
15211663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*------------------------------------------------------------*/
15212663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15213663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng__attribute__((noinline))
15214663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic
15215663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengLong dis_ESC_0F__SSE4 ( Bool* decode_OK,
15216663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        VexArchInfo* archinfo,
15217663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        VexAbiInfo* vbi,
15218663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        Prefix pfx, Int sz, Long deltaIN )
15219663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
15220663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr  = IRTemp_INVALID;
15221663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRType ty    = Ity_INVALID;
15222663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm = 0;
15223663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen  = 0;
15224663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
15225663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15226663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *decode_OK = False;
15227663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15228663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Long   delta = deltaIN;
15229663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  opc   = getUChar(delta);
15230663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   delta++;
15231663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (opc) {
15232663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15233663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xB8:
15234663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F3 0F B8  = POPCNT{W,L,Q}
15235663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Count the number of 1 bits in a register
15236663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      */
15237663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3noF2(pfx) /* so both 66 and REX.W are possibilities */
15238663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (sz == 2 || sz == 4 || sz == 8)) {
15239663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /*IRType*/ ty  = szToITy(sz);
15240663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp     src = newTemp(ty);
15241663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
15242663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
15243663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(src, getIRegE(sz, pfx, modrm));
15244663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
15245663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("popcnt%c %s, %s\n", nameISize(sz), nameIRegE(sz, pfx, modrm),
15246663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                nameIRegG(sz, pfx, modrm));
15247663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
15248663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 0);
15249663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(src, loadLE(ty, mkexpr(addr)));
15250663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
15251663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("popcnt%c %s, %s\n", nameISize(sz), dis_buf,
15252663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                nameIRegG(sz, pfx, modrm));
15253663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
15254663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15255663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp result = gen_POPCOUNT(ty, src);
15256663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putIRegG(sz, pfx, modrm, mkexpr(result));
15257663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15258663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         // Update flags.  This is pretty lame .. perhaps can do better
15259663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         // if this turns out to be performance critical.
15260663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         // O S A C P are cleared.  Z is set if SRC == 0.
15261663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         stmt( IRStmt_Put( OFFB_CC_OP,   mkU64(AMD64G_CC_OP_COPY) ));
15262663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         stmt( IRStmt_Put( OFFB_CC_DEP2, mkU64(0) ));
15263663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         stmt( IRStmt_Put( OFFB_CC_NDEP, mkU64(0) ));
15264663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         stmt( IRStmt_Put( OFFB_CC_DEP1,
15265663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               binop(Iop_Shl64,
15266663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     unop(Iop_1Uto64,
15267663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          binop(Iop_CmpEQ64,
15268663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                widenUto64(mkexpr(src)),
15269663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                mkU64(0))),
15270663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     mkU8(AMD64G_CC_SHIFT_Z))));
15271663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15272663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
15273663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
15274663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
15275663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15276663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xBD:
15277663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F3 0F BD -- LZCNT (count leading zeroes.  An AMD extension,
15278663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         which we can only decode if we're sure this is an AMD cpu
15279663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         that supports LZCNT, since otherwise it's BSR, which behaves
15280663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         differently.  Bizarrely, my Sandy Bridge also accepts these
15281663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         instructions but produces different results. */
15282663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3noF2(pfx) /* so both 66 and 48 are possibilities */
15283663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (sz == 2 || sz == 4 || sz == 8)
15284663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && 0 != (archinfo->hwcaps & VEX_HWCAPS_AMD64_LZCNT)) {
15285663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /*IRType*/ ty  = szToITy(sz);
15286663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp     src = newTemp(ty);
15287663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
15288663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
15289663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(src, getIRegE(sz, pfx, modrm));
15290663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
15291663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("lzcnt%c %s, %s\n", nameISize(sz), nameIRegE(sz, pfx, modrm),
15292663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                nameIRegG(sz, pfx, modrm));
15293663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
15294663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 0);
15295663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(src, loadLE(ty, mkexpr(addr)));
15296663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
15297663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("lzcnt%c %s, %s\n", nameISize(sz), dis_buf,
15298663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                nameIRegG(sz, pfx, modrm));
15299663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
15300663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15301663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp res = gen_LZCNT(ty, src);
15302663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putIRegG(sz, pfx, modrm, mkexpr(res));
15303663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15304663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         // Update flags.  This is pretty lame .. perhaps can do better
15305663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         // if this turns out to be performance critical.
15306663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         // O S A P are cleared.  Z is set if RESULT == 0.
15307663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         // C is set if SRC is zero.
15308663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp src64 = newTemp(Ity_I64);
15309663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp res64 = newTemp(Ity_I64);
15310663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(src64, widenUto64(mkexpr(src)));
15311663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(res64, widenUto64(mkexpr(res)));
15312663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15313663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp oszacp = newTemp(Ity_I64);
15314663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(
15315663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            oszacp,
15316663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            binop(Iop_Or64,
15317663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  binop(Iop_Shl64,
15318663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        unop(Iop_1Uto64,
15319663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             binop(Iop_CmpEQ64, mkexpr(res64), mkU64(0))),
15320663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        mkU8(AMD64G_CC_SHIFT_Z)),
15321663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  binop(Iop_Shl64,
15322663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        unop(Iop_1Uto64,
15323663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             binop(Iop_CmpEQ64, mkexpr(src64), mkU64(0))),
15324663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        mkU8(AMD64G_CC_SHIFT_C))
15325663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            )
15326663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         );
15327663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15328663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         stmt( IRStmt_Put( OFFB_CC_OP,   mkU64(AMD64G_CC_OP_COPY) ));
15329663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         stmt( IRStmt_Put( OFFB_CC_DEP2, mkU64(0) ));
15330663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         stmt( IRStmt_Put( OFFB_CC_NDEP, mkU64(0) ));
15331663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         stmt( IRStmt_Put( OFFB_CC_DEP1, mkexpr(oszacp) ));
15332663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15333663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
15334663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
15335663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
15336663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15337663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   default:
15338663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
15339663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15340663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
15341663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15342663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  //decode_failure:
15343663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *decode_OK = False;
15344663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return deltaIN;
15345663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15346663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  decode_success:
15347663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *decode_OK = True;
15348663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
15349663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
15350663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15351663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15352663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*------------------------------------------------------------*/
15353663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---                                                      ---*/
15354663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*--- Top-level SSE4: dis_ESC_0F38__SSE4                   ---*/
15355663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---                                                      ---*/
15356663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*------------------------------------------------------------*/
15357663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15358663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRTemp math_PBLENDVB_128 ( IRTemp vecE, IRTemp vecG,
15359663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  IRTemp vec0/*controlling mask*/,
15360663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  UInt gran, IROp opSAR )
15361663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
15362663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* The tricky bit is to convert vec0 into a suitable mask, by
15363663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      copying the most significant bit of each lane into all positions
15364663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      in the lane. */
15365663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp sh = newTemp(Ity_I8);
15366663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(sh, mkU8(8 * gran - 1));
15367663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15368663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp mask = newTemp(Ity_V128);
15369663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(mask, binop(opSAR, mkexpr(vec0), mkexpr(sh)));
15370663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15371663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp notmask = newTemp(Ity_V128);
15372663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(notmask, unop(Iop_NotV128, mkexpr(mask)));
15373663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15374663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp res = newTemp(Ity_V128);
15375663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(res,  binop(Iop_OrV128,
15376663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      binop(Iop_AndV128, mkexpr(vecE), mkexpr(mask)),
15377663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      binop(Iop_AndV128, mkexpr(vecG), mkexpr(notmask))));
15378663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return res;
15379663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
15380663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15381663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRTemp math_PBLENDVB_256 ( IRTemp vecE, IRTemp vecG,
15382663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  IRTemp vec0/*controlling mask*/,
15383663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  UInt gran, IROp opSAR128 )
15384663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
15385663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* The tricky bit is to convert vec0 into a suitable mask, by
15386663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      copying the most significant bit of each lane into all positions
15387663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      in the lane. */
15388663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp sh = newTemp(Ity_I8);
15389663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(sh, mkU8(8 * gran - 1));
15390663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15391663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp vec0Hi = IRTemp_INVALID;
15392663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp vec0Lo = IRTemp_INVALID;
15393663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV256toV128s( vec0, &vec0Hi, &vec0Lo );
15394663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15395663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp mask = newTemp(Ity_V256);
15396663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(mask, binop(Iop_V128HLtoV256,
15397663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      binop(opSAR128, mkexpr(vec0Hi), mkexpr(sh)),
15398663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      binop(opSAR128, mkexpr(vec0Lo), mkexpr(sh))));
15399663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15400663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp notmask = newTemp(Ity_V256);
15401663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(notmask, unop(Iop_NotV256, mkexpr(mask)));
15402663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15403663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp res = newTemp(Ity_V256);
15404663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(res,  binop(Iop_OrV256,
15405663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      binop(Iop_AndV256, mkexpr(vecE), mkexpr(mask)),
15406663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      binop(Iop_AndV256, mkexpr(vecG), mkexpr(notmask))));
15407663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return res;
15408663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
15409663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15410663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_VBLENDV_128 ( VexAbiInfo* vbi, Prefix pfx, Long delta,
15411663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              const HChar *name, UInt gran, IROp opSAR )
15412663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
15413663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr   = IRTemp_INVALID;
15414663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen   = 0;
15415663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
15416663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm  = getUChar(delta);
15417663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rG     = gregOfRexRM(pfx, modrm);
15418663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rV     = getVexNvvvv(pfx);
15419663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rIS4   = 0xFF; /* invalid */
15420663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp vecE   = newTemp(Ity_V128);
15421663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp vecV   = newTemp(Ity_V128);
15422663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp vecIS4 = newTemp(Ity_V128);
15423663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (epartIsReg(modrm)) {
15424663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta++;
15425663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt rE = eregOfRexRM(pfx, modrm);
15426663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(vecE, getXMMReg(rE));
15427663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UChar ib = getUChar(delta);
15428663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      rIS4 = (ib >> 4) & 0xF;
15429663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%s %s,%s,%s,%s\n",
15430663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          name, nameXMMReg(rIS4), nameXMMReg(rE),
15431663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          nameXMMReg(rV), nameXMMReg(rG));
15432663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
15433663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 1 );
15434663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen;
15435663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(vecE, loadLE(Ity_V128, mkexpr(addr)));
15436663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UChar ib = getUChar(delta);
15437663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      rIS4 = (ib >> 4) & 0xF;
15438663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%s %s,%s,%s,%s\n",
15439663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          name, nameXMMReg(rIS4), dis_buf, nameXMMReg(rV), nameXMMReg(rG));
15440663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
15441663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   delta++;
15442663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(vecV,   getXMMReg(rV));
15443663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(vecIS4, getXMMReg(rIS4));
15444663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp res = math_PBLENDVB_128( vecE, vecV, vecIS4, gran, opSAR );
15445663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putYMMRegLoAndZU( rG, mkexpr(res) );
15446663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
15447663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
15448663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15449663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_VBLENDV_256 ( VexAbiInfo* vbi, Prefix pfx, Long delta,
15450663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              const HChar *name, UInt gran, IROp opSAR128 )
15451663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
15452663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr   = IRTemp_INVALID;
15453663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen   = 0;
15454663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
15455663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm  = getUChar(delta);
15456663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rG     = gregOfRexRM(pfx, modrm);
15457663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rV     = getVexNvvvv(pfx);
15458663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rIS4   = 0xFF; /* invalid */
15459663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp vecE   = newTemp(Ity_V256);
15460663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp vecV   = newTemp(Ity_V256);
15461663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp vecIS4 = newTemp(Ity_V256);
15462663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (epartIsReg(modrm)) {
15463663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta++;
15464663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt rE = eregOfRexRM(pfx, modrm);
15465663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(vecE, getYMMReg(rE));
15466663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UChar ib = getUChar(delta);
15467663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      rIS4 = (ib >> 4) & 0xF;
15468663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%s %s,%s,%s,%s\n",
15469663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          name, nameYMMReg(rIS4), nameYMMReg(rE),
15470663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          nameYMMReg(rV), nameYMMReg(rG));
15471663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
15472663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 1 );
15473663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen;
15474663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(vecE, loadLE(Ity_V256, mkexpr(addr)));
15475663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UChar ib = getUChar(delta);
15476663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      rIS4 = (ib >> 4) & 0xF;
15477663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%s %s,%s,%s,%s\n",
15478663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          name, nameYMMReg(rIS4), dis_buf, nameYMMReg(rV), nameYMMReg(rG));
15479663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
15480663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   delta++;
15481663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(vecV,   getYMMReg(rV));
15482663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(vecIS4, getYMMReg(rIS4));
15483663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp res = math_PBLENDVB_256( vecE, vecV, vecIS4, gran, opSAR128 );
15484663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putYMMReg( rG, mkexpr(res) );
15485663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
15486663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
15487663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15488663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void finish_xTESTy ( IRTemp andV, IRTemp andnV, Int sign )
15489663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
15490663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Set Z=1 iff (vecE & vecG) == 0
15491663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Set C=1 iff (vecE & not vecG) == 0
15492663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   */
15493663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15494663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* andV, andnV:  vecE & vecG,  vecE and not(vecG) */
15495663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15496663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* andV resp. andnV, reduced to 64-bit values, by or-ing the top
15497663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      and bottom 64-bits together.  It relies on this trick:
15498663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15499663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      InterleaveLO64x2([a,b],[c,d]) == [b,d]    hence
15500663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15501663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      InterleaveLO64x2([a,b],[a,b]) == [b,b]    and similarly
15502663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      InterleaveHI64x2([a,b],[a,b]) == [a,a]
15503663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15504663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      and so the OR of the above 2 exprs produces
15505663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      [a OR b, a OR b], from which we simply take the lower half.
15506663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   */
15507663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp and64  = newTemp(Ity_I64);
15508663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp andn64 = newTemp(Ity_I64);
15509663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15510663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(and64,
15511663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          unop(Iop_V128to64,
15512663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               binop(Iop_OrV128,
15513663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     binop(Iop_InterleaveLO64x2,
15514663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           mkexpr(andV), mkexpr(andV)),
15515663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     binop(Iop_InterleaveHI64x2,
15516663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           mkexpr(andV), mkexpr(andV)))));
15517663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15518663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(andn64,
15519663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          unop(Iop_V128to64,
15520663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               binop(Iop_OrV128,
15521663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     binop(Iop_InterleaveLO64x2,
15522663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           mkexpr(andnV), mkexpr(andnV)),
15523663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     binop(Iop_InterleaveHI64x2,
15524663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           mkexpr(andnV), mkexpr(andnV)))));
15525663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15526663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp z64 = newTemp(Ity_I64);
15527663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp c64 = newTemp(Ity_I64);
15528663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (sign == 64) {
15529663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* When only interested in the most significant bit, just shift
15530663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         arithmetically right and negate.  */
15531663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(z64,
15532663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             unop(Iop_Not64,
15533663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  binop(Iop_Sar64, mkexpr(and64), mkU8(63))));
15534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15535663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(c64,
15536663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             unop(Iop_Not64,
15537663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  binop(Iop_Sar64, mkexpr(andn64), mkU8(63))));
15538663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
15539663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (sign == 32) {
15540663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* When interested in bit 31 and bit 63, mask those bits and
15541663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            fallthrough into the PTEST handling.  */
15542663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp t0 = newTemp(Ity_I64);
15543663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp t1 = newTemp(Ity_I64);
15544663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp t2 = newTemp(Ity_I64);
15545663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(t0, mkU64(0x8000000080000000ULL));
15546663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(t1, binop(Iop_And64, mkexpr(and64), mkexpr(t0)));
15547663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(t2, binop(Iop_And64, mkexpr(andn64), mkexpr(t0)));
15548663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         and64 = t1;
15549663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         andn64 = t2;
15550663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
15551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Now convert and64, andn64 to all-zeroes or all-1s, so we can
15552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         slice out the Z and C bits conveniently.  We use the standard
15553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         trick all-zeroes -> all-zeroes, anything-else -> all-ones
15554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         done by "(x | -x) >>s (word-size - 1)".
15555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      */
15556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(z64,
15557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             unop(Iop_Not64,
15558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(Iop_Sar64,
15559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_Or64,
15560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              binop(Iop_Sub64, mkU64(0), mkexpr(and64)),
15561663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    mkexpr(and64)), mkU8(63))));
15562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(c64,
15564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             unop(Iop_Not64,
15565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(Iop_Sar64,
15566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_Or64,
15567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              binop(Iop_Sub64, mkU64(0), mkexpr(andn64)),
15568663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    mkexpr(andn64)), mkU8(63))));
15569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
15570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15571663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* And finally, slice out the Z and C flags and set the flags
15572663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      thunk to COPY for them.  OSAP are set to zero. */
15573663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp newOSZACP = newTemp(Ity_I64);
15574663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(newOSZACP,
15575663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          binop(Iop_Or64,
15576663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                binop(Iop_And64, mkexpr(z64), mkU64(AMD64G_CC_MASK_Z)),
15577663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                binop(Iop_And64, mkexpr(c64), mkU64(AMD64G_CC_MASK_C))));
15578663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15579663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   stmt( IRStmt_Put( OFFB_CC_DEP1, mkexpr(newOSZACP)));
15580663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   stmt( IRStmt_Put( OFFB_CC_OP,   mkU64(AMD64G_CC_OP_COPY) ));
15581663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   stmt( IRStmt_Put( OFFB_CC_DEP2, mkU64(0) ));
15582663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   stmt( IRStmt_Put( OFFB_CC_NDEP, mkU64(0) ));
15583663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
15584f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
15585f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
15586663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Handles 128 bit versions of PTEST, VTESTPS or VTESTPD.
15587663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   sign is 0 for PTEST insn, 32 for VTESTPS and 64 for VTESTPD. */
15588663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_xTESTy_128 ( VexAbiInfo* vbi, Prefix pfx,
15589663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             Long delta, Bool isAvx, Int sign )
15590663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
15591663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr   = IRTemp_INVALID;
15592663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen   = 0;
15593663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
15594663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm  = getUChar(delta);
15595663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rG     = gregOfRexRM(pfx, modrm);
15596663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp vecE = newTemp(Ity_V128);
15597663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp vecG = newTemp(Ity_V128);
15598663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15599663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if ( epartIsReg(modrm) ) {
15600663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt rE = eregOfRexRM(pfx, modrm);
15601663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(vecE, getXMMReg(rE));
15602663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1;
15603663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP( "%s%stest%s %s,%s\n",
15604663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           isAvx ? "v" : "", sign == 0 ? "p" : "",
15605663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           sign == 0 ? "" : sign == 32 ? "ps" : "pd",
15606663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           nameXMMReg(rE), nameXMMReg(rG) );
15607663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
15608663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 0 );
15609663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (!isAvx)
15610f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         gen_SEGV_if_not_16_aligned( addr );
15611663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(vecE, loadLE( Ity_V128, mkexpr(addr) ));
15612663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen;
15613663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP( "%s%stest%s %s,%s\n",
15614663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           isAvx ? "v" : "", sign == 0 ? "p" : "",
15615663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           sign == 0 ? "" : sign == 32 ? "ps" : "pd",
15616663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           dis_buf, nameXMMReg(rG) );
15617663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
15618f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
15619663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(vecG, getXMMReg(rG));
15620f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
15621663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Set Z=1 iff (vecE & vecG) == 0
15622663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Set C=1 iff (vecE & not vecG) == 0
15623663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   */
15624f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
15625663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* andV, andnV:  vecE & vecG,  vecE and not(vecG) */
15626663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp andV  = newTemp(Ity_V128);
15627663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp andnV = newTemp(Ity_V128);
15628663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(andV,  binop(Iop_AndV128, mkexpr(vecE), mkexpr(vecG)));
15629663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(andnV, binop(Iop_AndV128,
15630663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       mkexpr(vecE),
15631663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       binop(Iop_XorV128, mkexpr(vecG),
15632663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                          mkV128(0xFFFF))));
15633f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
15634663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   finish_xTESTy ( andV, andnV, sign );
15635663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
15636663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
15637f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
15638f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
15639663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Handles 256 bit versions of PTEST, VTESTPS or VTESTPD.
15640663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   sign is 0 for PTEST insn, 32 for VTESTPS and 64 for VTESTPD. */
15641663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_xTESTy_256 ( VexAbiInfo* vbi, Prefix pfx,
15642663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             Long delta, Int sign )
15643663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
15644663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr   = IRTemp_INVALID;
15645663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen   = 0;
15646663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
15647663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm  = getUChar(delta);
15648663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rG     = gregOfRexRM(pfx, modrm);
15649663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp vecE   = newTemp(Ity_V256);
15650663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp vecG   = newTemp(Ity_V256);
15651663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15652663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if ( epartIsReg(modrm) ) {
15653663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt rE = eregOfRexRM(pfx, modrm);
15654663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(vecE, getYMMReg(rE));
15655663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1;
15656663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP( "v%stest%s %s,%s\n", sign == 0 ? "p" : "",
15657663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           sign == 0 ? "" : sign == 32 ? "ps" : "pd",
15658663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           nameYMMReg(rE), nameYMMReg(rG) );
15659663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
15660663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 0 );
15661663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(vecE, loadLE( Ity_V256, mkexpr(addr) ));
15662663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen;
15663663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP( "v%stest%s %s,%s\n", sign == 0 ? "p" : "",
15664663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           sign == 0 ? "" : sign == 32 ? "ps" : "pd",
15665663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           dis_buf, nameYMMReg(rG) );
15666f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   }
15667f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
15668663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(vecG, getYMMReg(rG));
15669663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15670663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Set Z=1 iff (vecE & vecG) == 0
15671663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Set C=1 iff (vecE & not vecG) == 0
15672f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   */
15673f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
15674663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* andV, andnV:  vecE & vecG,  vecE and not(vecG) */
15675663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp andV  = newTemp(Ity_V256);
15676663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp andnV = newTemp(Ity_V256);
15677663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(andV,  binop(Iop_AndV256, mkexpr(vecE), mkexpr(vecG)));
15678663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(andnV, binop(Iop_AndV256,
15679663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       mkexpr(vecE), unop(Iop_NotV256, mkexpr(vecG))));
15680663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15681663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp andVhi  = IRTemp_INVALID;
15682663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp andVlo  = IRTemp_INVALID;
15683663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp andnVhi = IRTemp_INVALID;
15684663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp andnVlo = IRTemp_INVALID;
15685663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV256toV128s( andV, &andVhi, &andVlo );
15686663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV256toV128s( andnV, &andnVhi, &andnVlo );
15687663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15688663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp andV128  = newTemp(Ity_V128);
15689663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp andnV128 = newTemp(Ity_V128);
15690663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( andV128, binop( Iop_OrV128, mkexpr(andVhi), mkexpr(andVlo) ) );
15691663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( andnV128, binop( Iop_OrV128, mkexpr(andnVhi), mkexpr(andnVlo) ) );
15692663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15693663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   finish_xTESTy ( andV128, andnV128, sign );
15694663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
15695663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
15696f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
15697b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
15698663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Handles 128 bit versions of PMOVZXBW and PMOVSXBW. */
15699663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_PMOVxXBW_128 ( VexAbiInfo* vbi, Prefix pfx,
15700663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               Long delta, Bool isAvx, Bool xIsZ )
15701663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
15702663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr   = IRTemp_INVALID;
15703663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen   = 0;
15704663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
15705663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp srcVec = newTemp(Ity_V128);
15706663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm  = getUChar(delta);
15707663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar* mbV    = isAvx ? "v" : "";
15708663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  how    = xIsZ ? 'z' : 's';
15709663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rG     = gregOfRexRM(pfx, modrm);
15710663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if ( epartIsReg(modrm) ) {
15711663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt rE = eregOfRexRM(pfx, modrm);
15712663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( srcVec, getXMMReg(rE) );
15713663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1;
15714663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP( "%spmov%cxbw %s,%s\n", mbV, how, nameXMMReg(rE), nameXMMReg(rG) );
15715663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
15716663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 0 );
15717663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( srcVec,
15718663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              unop( Iop_64UtoV128, loadLE( Ity_I64, mkexpr(addr) ) ) );
15719663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen;
15720663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP( "%spmov%cxbw %s,%s\n", mbV, how, dis_buf, nameXMMReg(rG) );
15721663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
15722663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15723663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRExpr* res
15724663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      = xIsZ /* do math for either zero or sign extend */
15725663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        ? binop( Iop_InterleaveLO8x16,
15726663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 IRExpr_Const( IRConst_V128(0) ), mkexpr(srcVec) )
15727663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        : binop( Iop_SarN16x8,
15728663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 binop( Iop_ShlN16x8,
15729663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        binop( Iop_InterleaveLO8x16,
15730663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               IRExpr_Const( IRConst_V128(0) ),
15731663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               mkexpr(srcVec) ),
15732663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        mkU8(8) ),
15733663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 mkU8(8) );
15734b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
15735663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   (isAvx ? putYMMRegLoAndZU : putXMMReg) ( rG, res );
15736b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
15737663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
15738663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
15739b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
15740b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
15741663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_PMOVxXWD_128 ( VexAbiInfo* vbi, Prefix pfx,
15742663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               Long delta, Bool isAvx, Bool xIsZ )
15743663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
15744663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr   = IRTemp_INVALID;
15745663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen   = 0;
15746663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
15747663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp srcVec = newTemp(Ity_V128);
15748663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm  = getUChar(delta);
15749663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar* mbV    = isAvx ? "v" : "";
15750663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  how    = xIsZ ? 'z' : 's';
15751663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rG     = gregOfRexRM(pfx, modrm);
15752663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15753663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if ( epartIsReg(modrm) ) {
15754663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt rE = eregOfRexRM(pfx, modrm);
15755663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( srcVec, getXMMReg(rE) );
15756663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1;
15757663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP( "%spmov%cxwd %s,%s\n", mbV, how, nameXMMReg(rE), nameXMMReg(rG) );
15758663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
15759663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 0 );
15760663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( srcVec,
15761663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              unop( Iop_64UtoV128, loadLE( Ity_I64, mkexpr(addr) ) ) );
15762663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen;
15763663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP( "%spmov%cxwd %s,%s\n", mbV, how, dis_buf, nameXMMReg(rG) );
15764b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
15765b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
15766663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRExpr* res
15767663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      = binop( Iop_InterleaveLO16x8,
15768663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               IRExpr_Const( IRConst_V128(0) ), mkexpr(srcVec) );
15769663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (!xIsZ)
15770663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      res = binop(Iop_SarN32x4,
15771663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  binop(Iop_ShlN32x4, res, mkU8(16)), mkU8(16));
15772b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
15773663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   (isAvx ? putYMMRegLoAndZU : putXMMReg)
15774663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ( gregOfRexRM(pfx, modrm), res );
15775b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
15776663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
15777663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
15778b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
15779b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
15780663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_PMOVSXWQ_128 ( VexAbiInfo* vbi, Prefix pfx,
15781663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               Long delta, Bool isAvx )
15782663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
15783663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr     = IRTemp_INVALID;
15784663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen     = 0;
15785663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
15786663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp srcBytes = newTemp(Ity_I32);
15787663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm    = getUChar(delta);
15788663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar* mbV      = isAvx ? "v" : "";
15789663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rG       = gregOfRexRM(pfx, modrm);
15790663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15791663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if ( epartIsReg( modrm ) ) {
15792663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt rE = eregOfRexRM(pfx, modrm);
15793663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( srcBytes, getXMMRegLane32( rE, 0 ) );
15794663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1;
15795663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP( "%spmovsxwq %s,%s\n", mbV, nameXMMReg(rE), nameXMMReg(rG) );
15796663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
15797663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 0 );
15798663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( srcBytes, loadLE( Ity_I32, mkexpr(addr) ) );
15799663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen;
15800663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP( "%spmovsxwq %s,%s\n", mbV, dis_buf, nameXMMReg(rG) );
15801b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
15802b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
15803663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   (isAvx ? putYMMRegLoAndZU : putXMMReg)
15804663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ( rG, binop( Iop_64HLtoV128,
15805663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   unop( Iop_16Sto64,
15806663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         unop( Iop_32HIto16, mkexpr(srcBytes) ) ),
15807663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   unop( Iop_16Sto64,
15808663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         unop( Iop_32to16, mkexpr(srcBytes) ) ) ) );
15809663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
15810663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
15811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15813663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_PMOVZXWQ_128 ( VexAbiInfo* vbi, Prefix pfx,
15814663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               Long delta, Bool isAvx )
15815663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
15816663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr     = IRTemp_INVALID;
15817663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen     = 0;
15818663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
15819663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp srcVec = newTemp(Ity_V128);
15820663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm    = getUChar(delta);
15821663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar* mbV      = isAvx ? "v" : "";
15822663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rG       = gregOfRexRM(pfx, modrm);
15823663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15824663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if ( epartIsReg( modrm ) ) {
15825663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt rE = eregOfRexRM(pfx, modrm);
15826663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( srcVec, getXMMReg(rE) );
15827663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1;
15828663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP( "%spmovzxwq %s,%s\n", mbV, nameXMMReg(rE), nameXMMReg(rG) );
15829663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
15830663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 0 );
15831663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( srcVec,
15832663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              unop( Iop_32UtoV128, loadLE( Ity_I32, mkexpr(addr) ) ) );
15833663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen;
15834663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP( "%spmovzxwq %s,%s\n", mbV, dis_buf, nameXMMReg(rG) );
15835663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
15836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15837663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp zeroVec = newTemp( Ity_V128 );
15838663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( zeroVec, IRExpr_Const( IRConst_V128(0) ) );
15839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15840663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   (isAvx ? putYMMRegLoAndZU : putXMMReg)
15841663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ( rG, binop( Iop_InterleaveLO16x8,
15842663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   mkexpr(zeroVec),
15843663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   binop( Iop_InterleaveLO16x8,
15844663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          mkexpr(zeroVec), mkexpr(srcVec) ) ) );
15845663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
15846663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
15847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15849663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Handles 128 bit versions of PMOVZXDQ and PMOVSXDQ. */
15850663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_PMOVxXDQ_128 ( VexAbiInfo* vbi, Prefix pfx,
15851663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               Long delta, Bool isAvx, Bool xIsZ )
15852663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
15853663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr   = IRTemp_INVALID;
15854663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen   = 0;
15855663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
15856663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp srcI64 = newTemp(Ity_I64);
15857663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp srcVec = newTemp(Ity_V128);
15858663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm  = getUChar(delta);
15859663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar* mbV    = isAvx ? "v" : "";
15860663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  how    = xIsZ ? 'z' : 's';
15861663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rG     = gregOfRexRM(pfx, modrm);
15862663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Compute both srcI64 -- the value to expand -- and srcVec -- same
15863663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      thing in a V128, with arbitrary junk in the top 64 bits.  Use
15864663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      one or both of them and let iropt clean up afterwards (as
15865663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      usual). */
15866663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if ( epartIsReg(modrm) ) {
15867663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt rE = eregOfRexRM(pfx, modrm);
15868663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( srcVec, getXMMReg(rE) );
15869663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( srcI64, unop(Iop_V128to64, mkexpr(srcVec)) );
15870663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1;
15871663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP( "%spmov%cxdq %s,%s\n", mbV, how, nameXMMReg(rE), nameXMMReg(rG) );
15872663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
15873663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 0 );
15874663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( srcI64, loadLE(Ity_I64, mkexpr(addr)) );
15875663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( srcVec, unop( Iop_64UtoV128, mkexpr(srcI64)) );
15876663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen;
15877663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP( "%spmov%cxdq %s,%s\n", mbV, how, dis_buf, nameXMMReg(rG) );
15878663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
15879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15880663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRExpr* res
15881663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      = xIsZ /* do math for either zero or sign extend */
15882663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        ? binop( Iop_InterleaveLO32x4,
15883663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 IRExpr_Const( IRConst_V128(0) ), mkexpr(srcVec) )
15884663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        : binop( Iop_64HLtoV128,
15885663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 unop( Iop_32Sto64,
15886663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       unop( Iop_64HIto32, mkexpr(srcI64) ) ),
15887663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 unop( Iop_32Sto64,
15888663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       unop( Iop_64to32, mkexpr(srcI64) ) ) );
15889b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
15890663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   (isAvx ? putYMMRegLoAndZU : putXMMReg) ( rG, res );
15891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15892663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
15893663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
15894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15896663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Handles 128 bit versions of PMOVZXBD and PMOVSXBD. */
15897663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_PMOVxXBD_128 ( VexAbiInfo* vbi, Prefix pfx,
15898663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               Long delta, Bool isAvx, Bool xIsZ )
15899663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
15900663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr   = IRTemp_INVALID;
15901663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen   = 0;
15902663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
15903663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp srcVec = newTemp(Ity_V128);
15904663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm  = getUChar(delta);
15905663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar* mbV    = isAvx ? "v" : "";
15906663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  how    = xIsZ ? 'z' : 's';
15907663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rG     = gregOfRexRM(pfx, modrm);
15908663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if ( epartIsReg(modrm) ) {
15909663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt rE = eregOfRexRM(pfx, modrm);
15910663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( srcVec, getXMMReg(rE) );
15911663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1;
15912663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP( "%spmov%cxbd %s,%s\n", mbV, how, nameXMMReg(rE), nameXMMReg(rG) );
15913663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
15914663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 0 );
15915663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( srcVec,
15916663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              unop( Iop_32UtoV128, loadLE( Ity_I32, mkexpr(addr) ) ) );
15917663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen;
15918663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP( "%spmov%cxbd %s,%s\n", mbV, how, dis_buf, nameXMMReg(rG) );
15919663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
15920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15921663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp zeroVec = newTemp(Ity_V128);
15922663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( zeroVec, IRExpr_Const( IRConst_V128(0) ) );
15923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15924663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRExpr* res
15925663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      = binop(Iop_InterleaveLO8x16,
15926663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              mkexpr(zeroVec),
15927663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              binop(Iop_InterleaveLO8x16,
15928663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    mkexpr(zeroVec), mkexpr(srcVec)));
15929663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (!xIsZ)
15930663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      res = binop(Iop_SarN32x4,
15931663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  binop(Iop_ShlN32x4, res, mkU8(24)), mkU8(24));
15932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15933663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   (isAvx ? putYMMRegLoAndZU : putXMMReg) ( rG, res );
15934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15935663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
15936663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
15937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15939663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Handles 128 bit versions of PMOVSXBQ. */
15940663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_PMOVSXBQ_128 ( VexAbiInfo* vbi, Prefix pfx,
15941663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               Long delta, Bool isAvx )
15942663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
15943663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr     = IRTemp_INVALID;
15944663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen     = 0;
15945663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
15946663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp srcBytes = newTemp(Ity_I16);
15947663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm    = getUChar(delta);
15948663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar* mbV      = isAvx ? "v" : "";
15949663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rG       = gregOfRexRM(pfx, modrm);
15950663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if ( epartIsReg(modrm) ) {
15951663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt rE = eregOfRexRM(pfx, modrm);
15952663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( srcBytes, getXMMRegLane16( rE, 0 ) );
15953663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1;
15954663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP( "%spmovsxbq %s,%s\n", mbV, nameXMMReg(rE), nameXMMReg(rG) );
15955663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
15956663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 0 );
15957663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( srcBytes, loadLE( Ity_I16, mkexpr(addr) ) );
15958663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen;
15959663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP( "%spmovsxbq %s,%s\n", mbV, dis_buf, nameXMMReg(rG) );
15960663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
15961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15962663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   (isAvx ? putYMMRegLoAndZU : putXMMReg)
15963663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ( rG, binop( Iop_64HLtoV128,
15964663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   unop( Iop_8Sto64,
15965663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         unop( Iop_16HIto8, mkexpr(srcBytes) ) ),
15966663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   unop( Iop_8Sto64,
15967663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         unop( Iop_16to8, mkexpr(srcBytes) ) ) ) );
15968663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
15969663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
15970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15972663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Handles 128 bit versions of PMOVZXBQ. */
15973663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_PMOVZXBQ_128 ( VexAbiInfo* vbi, Prefix pfx,
15974663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               Long delta, Bool isAvx )
15975663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
15976663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr     = IRTemp_INVALID;
15977663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen     = 0;
15978663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
15979663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp srcVec   = newTemp(Ity_V128);
15980663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm    = getUChar(delta);
15981663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar* mbV      = isAvx ? "v" : "";
15982663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rG       = gregOfRexRM(pfx, modrm);
15983663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if ( epartIsReg(modrm) ) {
15984663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt rE = eregOfRexRM(pfx, modrm);
15985663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( srcVec, getXMMReg(rE) );
15986663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1;
15987663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP( "%spmovzxbq %s,%s\n", mbV, nameXMMReg(rE), nameXMMReg(rG) );
15988663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
15989663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 0 );
15990663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( srcVec,
15991663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              unop( Iop_32UtoV128,
15992663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    unop( Iop_16Uto32, loadLE( Ity_I16, mkexpr(addr) ))));
15993663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen;
15994663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP( "%spmovzxbq %s,%s\n", mbV, dis_buf, nameXMMReg(rG) );
15995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
15996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15997663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp zeroVec = newTemp(Ity_V128);
15998663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( zeroVec, IRExpr_Const( IRConst_V128(0) ) );
15999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16000663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   (isAvx ? putYMMRegLoAndZU : putXMMReg)
16001663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ( rG, binop( Iop_InterleaveLO8x16,
16002663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   mkexpr(zeroVec),
16003663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   binop( Iop_InterleaveLO8x16,
16004663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          mkexpr(zeroVec),
16005663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          binop( Iop_InterleaveLO8x16,
16006663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                 mkexpr(zeroVec), mkexpr(srcVec) ) ) ) );
16007663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
16008663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
16009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16010663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
16011663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_PHMINPOSUW_128 ( VexAbiInfo* vbi, Prefix pfx,
16012663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                 Long delta, Bool isAvx )
16013663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
16014663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr   = IRTemp_INVALID;
16015663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen   = 0;
16016663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
16017663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm  = getUChar(delta);
16018663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar* mbV    = isAvx ? "v" : "";
16019663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp sV     = newTemp(Ity_V128);
16020663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp sHi    = newTemp(Ity_I64);
16021663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp sLo    = newTemp(Ity_I64);
16022663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp dLo    = newTemp(Ity_I64);
16023663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rG     = gregOfRexRM(pfx,modrm);
16024663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (epartIsReg(modrm)) {
16025663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt rE = eregOfRexRM(pfx,modrm);
16026663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( sV, getXMMReg(rE) );
16027663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1;
16028663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%sphminposuw %s,%s\n", mbV, nameXMMReg(rE), nameXMMReg(rG));
16029663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
16030663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
16031663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (!isAvx)
16032663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         gen_SEGV_if_not_16_aligned(addr);
16033663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
16034663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen;
16035663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%sphminposuw %s,%s\n", mbV, dis_buf, nameXMMReg(rG));
16036663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
16037663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( sHi, unop(Iop_V128HIto64, mkexpr(sV)) );
16038663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( sLo, unop(Iop_V128to64,   mkexpr(sV)) );
16039663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( dLo, mkIRExprCCall(
16040663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   Ity_I64, 0/*regparms*/,
16041663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   "amd64g_calculate_sse_phminposuw",
16042663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   &amd64g_calculate_sse_phminposuw,
16043663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   mkIRExprVec_2( mkexpr(sLo), mkexpr(sHi) )
16044663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         ));
16045663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   (isAvx ? putYMMRegLoAndZU : putXMMReg)
16046663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      (rG, unop(Iop_64UtoV128, mkexpr(dLo)));
16047663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
16048663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
16049663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
16050663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
16051663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_AESx ( VexAbiInfo* vbi, Prefix pfx,
16052663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       Long delta, Bool isAvx, UChar opc )
16053663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
16054663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr   = IRTemp_INVALID;
16055663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen   = 0;
16056663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
16057663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm  = getUChar(delta);
16058663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rG     = gregOfRexRM(pfx, modrm);
16059663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   regNoL = 0;
16060663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   regNoR = (isAvx && opc != 0xDB) ? getVexNvvvv(pfx) : rG;
16061663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
16062663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* This is a nasty kludge.  We need to pass 2 x V128 to the
16063663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      helper.  Since we can't do that, use a dirty
16064663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      helper to compute the results directly from the XMM regs in
16065663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      the guest state.  That means for the memory case, we need to
16066663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      move the left operand into a pseudo-register (XMM16, let's
16067663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      call it). */
16068663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (epartIsReg(modrm)) {
16069663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      regNoL = eregOfRexRM(pfx, modrm);
16070663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1;
16071663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
16072663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      regNoL = 16; /* use XMM16 as an intermediary */
16073663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 0 );
16074663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* alignment check needed ???? */
16075663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      stmt( IRStmt_Put( OFFB_YMM16, loadLE(Ity_V128, mkexpr(addr)) ));
16076663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen;
16077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
16078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16079663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   void*  fn = &amd64g_dirtyhelper_AES;
16080663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar* nm = "amd64g_dirtyhelper_AES";
16081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16082663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Round up the arguments.  Note that this is a kludge -- the
16083663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      use of mkU64 rather than mkIRExpr_HWord implies the
16084663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assumption that the host's word size is 64-bit. */
16085663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt gstOffD = ymmGuestRegOffset(rG);
16086663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt gstOffL = regNoL == 16 ? OFFB_YMM16 : ymmGuestRegOffset(regNoL);
16087663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt gstOffR = ymmGuestRegOffset(regNoR);
16088663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRExpr*  opc4         = mkU64(opc);
16089663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRExpr*  gstOffDe     = mkU64(gstOffD);
16090663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRExpr*  gstOffLe     = mkU64(gstOffL);
16091663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRExpr*  gstOffRe     = mkU64(gstOffR);
16092663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRExpr** args
16093663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      = mkIRExprVec_4( opc4, gstOffDe, gstOffLe, gstOffRe );
16094663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
16095663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRDirty* d    = unsafeIRDirty_0_N( 0/*regparms*/, nm, fn, args );
16096663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* It's not really a dirty call, but we can't use the clean
16097663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      helper mechanism here for the very lame reason that we can't
16098663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      pass 2 x V128s by value to a helper, nor get one back.  Hence
16099663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      this roundabout scheme. */
16100663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   d->needsBBP = True;
16101663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   d->nFxState = 2;
16102663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vex_bzero(&d->fxState, sizeof(d->fxState));
16103663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* AES{ENC,ENCLAST,DEC,DECLAST} read both registers, and writes
16104663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      the second for !isAvx or the third for isAvx.
16105663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      AESIMC (0xDB) reads the first register, and writes the second. */
16106663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   d->fxState[0].fx     = Ifx_Read;
16107663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   d->fxState[0].offset = gstOffL;
16108663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   d->fxState[0].size   = sizeof(U128);
16109663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   d->fxState[1].offset = gstOffR;
16110663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   d->fxState[1].size   = sizeof(U128);
16111663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (opc == 0xDB)
16112663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d->fxState[1].fx   = Ifx_Write;
16113663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   else if (!isAvx || rG == regNoR)
16114663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d->fxState[1].fx   = Ifx_Modify;
16115663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   else {
16116663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d->fxState[1].fx     = Ifx_Read;
16117663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d->nFxState++;
16118663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d->fxState[2].fx     = Ifx_Write;
16119663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d->fxState[2].offset = gstOffD;
16120663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d->fxState[2].size   = sizeof(U128);
16121663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
16122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16123663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   stmt( IRStmt_Dirty(d) );
16124663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   {
16125663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HChar* opsuf;
16126663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (opc) {
16127663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case 0xDC: opsuf = "enc"; break;
16128663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case 0XDD: opsuf = "enclast"; break;
16129663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case 0xDE: opsuf = "dec"; break;
16130663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case 0xDF: opsuf = "declast"; break;
16131663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case 0xDB: opsuf = "imc"; break;
16132663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         default: vassert(0);
16133663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
16134663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%saes%s %s,%s%s%s\n", isAvx ? "v" : "", opsuf,
16135663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          (regNoL == 16 ? dis_buf : nameXMMReg(regNoL)),
16136663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          nameXMMReg(regNoR),
16137663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          (isAvx && opc != 0xDB) ? "," : "",
16138663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          (isAvx && opc != 0xDB) ? nameXMMReg(rG) : "");
16139663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
16140663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (isAvx)
16141663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      putYMMRegLane128( rG, 1, mkV128(0) );
16142663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
16143663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
16144663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
16145663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_AESKEYGENASSIST ( VexAbiInfo* vbi, Prefix pfx,
16146663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  Long delta, Bool isAvx )
16147663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
16148663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr   = IRTemp_INVALID;
16149663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen   = 0;
16150663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
16151663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm  = getUChar(delta);
16152663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   regNoL = 0;
16153663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   regNoR = gregOfRexRM(pfx, modrm);
16154663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  imm    = 0;
16155663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
16156663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* This is a nasty kludge.  See AESENC et al. instructions. */
16157663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   modrm = getUChar(delta);
16158663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (epartIsReg(modrm)) {
16159663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      regNoL = eregOfRexRM(pfx, modrm);
16160663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      imm = getUChar(delta+1);
16161663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1+1;
16162663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
16163663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      regNoL = 16; /* use XMM16 as an intermediary */
16164663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 1 );
16165663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* alignment check ???? . */
16166663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      stmt( IRStmt_Put( OFFB_YMM16, loadLE(Ity_V128, mkexpr(addr)) ));
16167663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      imm = getUChar(delta+alen);
16168663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen+1;
16169663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
16170663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
16171663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Who ya gonna call?  Presumably not Ghostbusters. */
16172663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   void*  fn = &amd64g_dirtyhelper_AESKEYGENASSIST;
16173663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar* nm = "amd64g_dirtyhelper_AESKEYGENASSIST";
16174663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
16175663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Round up the arguments.  Note that this is a kludge -- the
16176663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      use of mkU64 rather than mkIRExpr_HWord implies the
16177663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assumption that the host's word size is 64-bit. */
16178663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt gstOffL = regNoL == 16 ? OFFB_YMM16 : ymmGuestRegOffset(regNoL);
16179663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt gstOffR = ymmGuestRegOffset(regNoR);
16180663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
16181663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRExpr*  imme          = mkU64(imm & 0xFF);
16182663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRExpr*  gstOffLe     = mkU64(gstOffL);
16183663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRExpr*  gstOffRe     = mkU64(gstOffR);
16184663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRExpr** args
16185663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      = mkIRExprVec_3( imme, gstOffLe, gstOffRe );
16186663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
16187663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRDirty* d    = unsafeIRDirty_0_N( 0/*regparms*/, nm, fn, args );
16188663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* It's not really a dirty call, but we can't use the clean
16189663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      helper mechanism here for the very lame reason that we can't
16190663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      pass 2 x V128s by value to a helper, nor get one back.  Hence
16191663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      this roundabout scheme. */
16192663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   d->needsBBP = True;
16193663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   d->nFxState = 2;
16194663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vex_bzero(&d->fxState, sizeof(d->fxState));
16195663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   d->fxState[0].fx     = Ifx_Read;
16196663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   d->fxState[0].offset = gstOffL;
16197663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   d->fxState[0].size   = sizeof(U128);
16198663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   d->fxState[1].fx     = Ifx_Write;
16199663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   d->fxState[1].offset = gstOffR;
16200663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   d->fxState[1].size   = sizeof(U128);
16201663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   stmt( IRStmt_Dirty(d) );
16202663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
16203663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   DIP("%saeskeygenassist $%x,%s,%s\n", isAvx ? "v" : "", (UInt)imm,
16204663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       (regNoL == 16 ? dis_buf : nameXMMReg(regNoL)),
16205663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       nameXMMReg(regNoR));
16206663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (isAvx)
16207663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      putYMMRegLane128( regNoR, 1, mkV128(0) );
16208663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
16209663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
16210663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
16211663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
16212663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng__attribute__((noinline))
16213663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic
16214663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengLong dis_ESC_0F38__SSE4 ( Bool* decode_OK,
16215663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          VexAbiInfo* vbi,
16216663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          Prefix pfx, Int sz, Long deltaIN )
16217663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
16218663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr  = IRTemp_INVALID;
16219663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm = 0;
16220663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen  = 0;
16221663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
16222663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
16223663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *decode_OK = False;
16224663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
16225663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Long   delta = deltaIN;
16226663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  opc   = getUChar(delta);
16227663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   delta++;
16228663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (opc) {
16229663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
16230663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x10:
16231663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x14:
16232663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x15:
16233663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 38 10 /r = PBLENDVB xmm1, xmm2/m128  (byte gran)
16234663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         66 0F 38 14 /r = BLENDVPS xmm1, xmm2/m128  (float gran)
16235663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         66 0F 38 15 /r = BLENDVPD xmm1, xmm2/m128  (double gran)
16236663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Blend at various granularities, with XMM0 (implicit operand)
16237663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         providing the controlling mask.
16238663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      */
16239663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
16240663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
16241663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
16242663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HChar* nm    = NULL;
16243663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   gran  = 0;
16244663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IROp   opSAR = Iop_INVALID;
16245663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         switch (opc) {
16246663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 0x10:
16247663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               nm = "pblendvb"; gran = 1; opSAR = Iop_SarN8x16;
16248663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               break;
16249663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 0x14:
16250663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               nm = "blendvps"; gran = 4; opSAR = Iop_SarN32x4;
16251663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               break;
16252663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 0x15:
16253663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               nm = "blendvpd"; gran = 8; opSAR = Iop_SarN64x2;
16254663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               break;
16255663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
16256663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(nm);
16257663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
16258663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp vecE = newTemp(Ity_V128);
16259663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp vecG = newTemp(Ity_V128);
16260663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp vec0 = newTemp(Ity_V128);
16261663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
16262663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if ( epartIsReg(modrm) ) {
16263663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(vecE, getXMMReg(eregOfRexRM(pfx, modrm)));
16264663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
16265663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "%s %s,%s\n", nm,
16266663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 nameXMMReg( eregOfRexRM(pfx, modrm) ),
16267663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 nameXMMReg( gregOfRexRM(pfx, modrm) ) );
16268663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
16269663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 0 );
16270663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gen_SEGV_if_not_16_aligned( addr );
16271663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(vecE, loadLE( Ity_V128, mkexpr(addr) ));
16272663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
16273663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "%s %s,%s\n", nm,
16274663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 dis_buf, nameXMMReg( gregOfRexRM(pfx, modrm) ) );
16275663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
16276663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
16277663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(vecG, getXMMReg(gregOfRexRM(pfx, modrm)));
16278663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(vec0, getXMMReg(0));
16279663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
16280663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp res = math_PBLENDVB_128( vecE, vecG, vec0, gran, opSAR );
16281663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMReg(gregOfRexRM(pfx, modrm), mkexpr(res));
16282663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
16283663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
16284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
16285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
16286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16287663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x17:
16288663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 38 17 /r = PTEST xmm1, xmm2/m128
16289663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Logical compare (set ZF and CF from AND/ANDN of the operands) */
16290663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
16291663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (sz == 2 || /* ignore redundant REX.W */ sz == 8)) {
16292663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_xTESTy_128( vbi, pfx, delta, False/*!isAvx*/, 0 );
16293663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
16294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
16295663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
16296663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
16297663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x20:
16298663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 38 20 /r = PMOVSXBW xmm1, xmm2/m64
16299663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Packed Move with Sign Extend from Byte to Word (XMM) */
16300663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
16301663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_PMOVxXBW_128( vbi, pfx, delta,
16302663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   False/*!isAvx*/, False/*!xIsZ*/ );
16303663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
16304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
16305663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
16306663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
16307663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x21:
16308663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 38 21 /r = PMOVSXBD xmm1, xmm2/m32
16309663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Packed Move with Sign Extend from Byte to DWord (XMM) */
16310663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
16311663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_PMOVxXBD_128( vbi, pfx, delta,
16312663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   False/*!isAvx*/, False/*!xIsZ*/ );
16313663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
16314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
16315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
16316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16317663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x22:
16318663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 38 22 /r = PMOVSXBQ xmm1, xmm2/m16
16319663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Packed Move with Sign Extend from Byte to QWord (XMM) */
16320663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
16321663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_PMOVSXBQ_128( vbi, pfx, delta, False/*!isAvx*/ );
16322663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
16323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
16324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
16325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16326663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x23:
16327663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 38 23 /r = PMOVSXWD xmm1, xmm2/m64
16328663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Packed Move with Sign Extend from Word to DWord (XMM) */
16329663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
16330663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_PMOVxXWD_128(vbi, pfx, delta,
16331663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  False/*!isAvx*/, False/*!xIsZ*/);
16332663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
16333663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
16334663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
16335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16336663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x24:
16337663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 38 24 /r = PMOVSXWQ xmm1, xmm2/m32
16338663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Packed Move with Sign Extend from Word to QWord (XMM) */
16339663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
16340663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_PMOVSXWQ_128( vbi, pfx, delta, False/*!isAvx*/ );
16341663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
16342f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      }
16343663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
16344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16345663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x25:
16346663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 38 25 /r = PMOVSXDQ xmm1, xmm2/m64
16347663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Packed Move with Sign Extend from Double Word to Quad Word (XMM) */
16348663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
16349663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_PMOVxXDQ_128( vbi, pfx, delta,
16350663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   False/*!isAvx*/, False/*!xIsZ*/ );
16351663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
16352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
16353663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
16354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16355663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x28:
16356663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 38 28 = PMULDQ -- signed widening multiply of 32-lanes
16357663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         0 x 0 to form lower 64-bit half and lanes 2 x 2 to form upper
16358663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         64-bit half */
16359663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* This is a really poor translation -- could be improved if
16360663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         performance critical.  It's a copy-paste of PMULUDQ, too. */
16361663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
16362663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sV = newTemp(Ity_V128);
16363663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dV = newTemp(Ity_V128);
16364663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
16365663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt rG = gregOfRexRM(pfx,modrm);
16366663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( dV, getXMMReg(rG) );
16367663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
16368663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
16369663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, getXMMReg(rE) );
16370663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
16371663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("pmuldq %s,%s\n", nameXMMReg(rE), nameXMMReg(rG));
16372663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
16373663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
16374663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
16375663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
16376663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("pmuldq %s,%s\n", dis_buf, nameXMMReg(rG));
16377663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
16378663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
16379663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMReg( rG, mkexpr(math_PMULDQ_128( dV, sV )) );
16380663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
16381663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
16382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
16383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16384663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x29:
16385663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 38 29 = PCMPEQQ
16386663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         64x2 equality comparison */
16387663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
16388663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* FIXME: this needs an alignment check */
16389663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSEint_E_to_G( vbi, pfx, delta,
16390663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    "pcmpeqq", Iop_CmpEQ64x2, False );
16391663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
16392663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
16393663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
16394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16395663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x2B:
16396663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0f 38 2B /r = PACKUSDW xmm1, xmm2/m128
16397663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         2x 32x4 S->U saturating narrow from xmm2/m128 to xmm1 */
16398663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
16399663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
16400663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
16401663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
16402663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp argL = newTemp(Ity_V128);
16403663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp argR = newTemp(Ity_V128);
16404663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
16405663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if ( epartIsReg(modrm) ) {
16406663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( argL, getXMMReg( eregOfRexRM(pfx, modrm) ) );
16407663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
16408663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "packusdw %s,%s\n",
16409663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 nameXMMReg( eregOfRexRM(pfx, modrm) ),
16410663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 nameXMMReg( gregOfRexRM(pfx, modrm) ) );
16411663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
16412663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 0 );
16413663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gen_SEGV_if_not_16_aligned( addr );
16414663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( argL, loadLE( Ity_V128, mkexpr(addr) ));
16415663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
16416663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "packusdw %s,%s\n",
16417663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 dis_buf, nameXMMReg( gregOfRexRM(pfx, modrm) ) );
16418663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
16419663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
16420663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(argR, getXMMReg( gregOfRexRM(pfx, modrm) ));
16421663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
16422663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMReg( gregOfRexRM(pfx, modrm),
16423663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    binop( Iop_QNarrowBin32Sto16Ux8,
16424663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           mkexpr(argL), mkexpr(argR)) );
16425663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
16426663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
16427663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
16428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
16429663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
16430663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x30:
16431663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 38 30 /r = PMOVZXBW xmm1, xmm2/m64
16432663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Packed Move with Zero Extend from Byte to Word (XMM) */
16433663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
16434663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_PMOVxXBW_128( vbi, pfx, delta,
16435663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   False/*!isAvx*/, True/*xIsZ*/ );
16436663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
16437663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
16438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
16439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16440663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x31:
16441663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 38 31 /r = PMOVZXBD xmm1, xmm2/m32
16442663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Packed Move with Zero Extend from Byte to DWord (XMM) */
16443663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
16444663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_PMOVxXBD_128( vbi, pfx, delta,
16445663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   False/*!isAvx*/, True/*xIsZ*/ );
16446663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
16447663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
16448663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
16449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16450663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x32:
16451663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 38 32 /r = PMOVZXBQ xmm1, xmm2/m16
16452663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Packed Move with Zero Extend from Byte to QWord (XMM) */
16453663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
16454663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_PMOVZXBQ_128( vbi, pfx, delta, False/*!isAvx*/ );
16455663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
16456663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
16457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
16458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16459663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x33:
16460663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 38 33 /r = PMOVZXWD xmm1, xmm2/m64
16461663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Packed Move with Zero Extend from Word to DWord (XMM) */
16462663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
16463663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_PMOVxXWD_128( vbi, pfx, delta,
16464663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   False/*!isAvx*/, True/*xIsZ*/ );
16465663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
16466663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
16467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
16468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16469663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x34:
16470663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 38 34 /r = PMOVZXWQ xmm1, xmm2/m32
16471663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Packed Move with Zero Extend from Word to QWord (XMM) */
16472663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
16473663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_PMOVZXWQ_128( vbi, pfx, delta, False/*!isAvx*/ );
16474663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
16475663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
16476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
16477663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
16478663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x35:
16479663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 38 35 /r = PMOVZXDQ xmm1, xmm2/m64
16480663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Packed Move with Zero Extend from DWord to QWord (XMM) */
16481663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
16482663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_PMOVxXDQ_128( vbi, pfx, delta,
16483663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   False/*!isAvx*/, True/*xIsZ*/ );
16484663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
16485663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
16486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
16487663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
16488663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x37:
16489663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 38 37 = PCMPGTQ
16490663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         64x2 comparison (signed, presumably; the Intel docs don't say :-)
16491663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      */
16492663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
16493663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* FIXME: this needs an alignment check */
16494663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSEint_E_to_G( vbi, pfx, delta,
16495663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    "pcmpgtq", Iop_CmpGT64Sx2, False );
16496663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
16497663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
16498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
16499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16500663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x38:
16501663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x3C:
16502663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 38 38 /r = PMINSB xmm1, xmm2/m128    8Sx16 (signed) min
16503663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         66 0F 38 3C /r = PMAXSB xmm1, xmm2/m128    8Sx16 (signed) max
16504663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      */
16505663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
16506663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* FIXME: this needs an alignment check */
16507663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Bool isMAX = opc == 0x3C;
16508663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSEint_E_to_G(
16509663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    vbi, pfx, delta,
16510663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    isMAX ? "pmaxsb" : "pminsb",
16511663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    isMAX ? Iop_Max8Sx16 : Iop_Min8Sx16,
16512663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    False
16513663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 );
16514663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
16515663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
16516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
16517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16518663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x39:
16519663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x3D:
16520663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 38 39 /r = PMINSD xmm1, xmm2/m128
16521663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Minimum of Packed Signed Double Word Integers (XMM)
16522663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         66 0F 38 3D /r = PMAXSD xmm1, xmm2/m128
16523663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Maximum of Packed Signed Double Word Integers (XMM)
16524663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      */
16525663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
16526663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* FIXME: this needs an alignment check */
16527663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Bool isMAX = opc == 0x3D;
16528663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSEint_E_to_G(
16529663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    vbi, pfx, delta,
16530663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    isMAX ? "pmaxsd" : "pminsd",
16531663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    isMAX ? Iop_Max32Sx4 : Iop_Min32Sx4,
16532663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    False
16533663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 );
16534663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
16535663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
16536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
16537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16538663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x3A:
16539663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x3E:
16540663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 38 3A /r = PMINUW xmm1, xmm2/m128
16541663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Minimum of Packed Unsigned Word Integers (XMM)
16542663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         66 0F 38 3E /r = PMAXUW xmm1, xmm2/m128
16543663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Maximum of Packed Unsigned Word Integers (XMM)
16544663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      */
16545663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
16546663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* FIXME: this needs an alignment check */
16547663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Bool isMAX = opc == 0x3E;
16548663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSEint_E_to_G(
16549663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    vbi, pfx, delta,
16550663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    isMAX ? "pmaxuw" : "pminuw",
16551663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    isMAX ? Iop_Max16Ux8 : Iop_Min16Ux8,
16552663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    False
16553663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 );
16554663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
16555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
16556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
16557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16558663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x3B:
16559663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x3F:
16560663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 38 3B /r = PMINUD xmm1, xmm2/m128
16561663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Minimum of Packed Unsigned Doubleword Integers (XMM)
16562663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         66 0F 38 3F /r = PMAXUD xmm1, xmm2/m128
16563663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Maximum of Packed Unsigned Doubleword Integers (XMM)
16564663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      */
16565663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
16566663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* FIXME: this needs an alignment check */
16567663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Bool isMAX = opc == 0x3F;
16568663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_SSEint_E_to_G(
16569663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    vbi, pfx, delta,
16570663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    isMAX ? "pmaxud" : "pminud",
16571663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    isMAX ? Iop_Max32Ux4 : Iop_Min32Ux4,
16572663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    False
16573663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 );
16574663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
16575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
16576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
16577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16578663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x40:
16579663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 38 40 /r = PMULLD xmm1, xmm2/m128
16580663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         32x4 integer multiply from xmm2/m128 to xmm1 */
16581663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
16582663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
16583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         modrm = getUChar(delta);
16584663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
16585663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp argL = newTemp(Ity_V128);
16586663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp argR = newTemp(Ity_V128);
16587663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
16588663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if ( epartIsReg(modrm) ) {
16589663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( argL, getXMMReg( eregOfRexRM(pfx, modrm) ) );
16590663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
16591663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "pmulld %s,%s\n",
16592663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 nameXMMReg( eregOfRexRM(pfx, modrm) ),
16593663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 nameXMMReg( gregOfRexRM(pfx, modrm) ) );
16594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
16595663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 0 );
16596663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gen_SEGV_if_not_16_aligned( addr );
16597663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( argL, loadLE( Ity_V128, mkexpr(addr) ));
16598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            delta += alen;
16599663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "pmulld %s,%s\n",
16600663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 dis_buf, nameXMMReg( gregOfRexRM(pfx, modrm) ) );
16601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
16602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16603663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(argR, getXMMReg( gregOfRexRM(pfx, modrm) ));
16604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16605663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMReg( gregOfRexRM(pfx, modrm),
16606663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    binop( Iop_Mul32x4, mkexpr(argL), mkexpr(argR)) );
16607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16608663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
16609663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
16610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
16611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16612663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x41:
16613663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 38 41 /r = PHMINPOSUW xmm1, xmm2/m128
16614663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Packed Horizontal Word Minimum from xmm2/m128 to xmm1 */
16615663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
16616663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_PHMINPOSUW_128( vbi, pfx, delta, False/*!isAvx*/ );
16617663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
16618663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
16619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
16620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16621663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xDC:
16622663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xDD:
16623663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xDE:
16624663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xDF:
16625663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xDB:
16626663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 38 DC /r = AESENC xmm1, xmm2/m128
16627663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  DD /r = AESENCLAST xmm1, xmm2/m128
16628663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  DE /r = AESDEC xmm1, xmm2/m128
16629663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  DF /r = AESDECLAST xmm1, xmm2/m128
16630663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
16631663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  DB /r = AESIMC xmm1, xmm2/m128 */
16632663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
16633663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AESx( vbi, pfx, delta, False/*!isAvx*/, opc );
16634663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
16635663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
16636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
16637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16638663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xF0:
16639663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xF1:
16640663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F2 0F 38 F0 /r = CRC32 r/m8, r32 (REX.W ok, 66 not ok)
16641663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         F2 0F 38 F1 /r = CRC32 r/m{16,32,64}, r32
16642663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         The decoding on this is a bit unusual.
16643663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      */
16644663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2noF3(pfx)
16645663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (opc == 0xF1 || (opc == 0xF0 && !have66(pfx)))) {
16646663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
16647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16648663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (opc == 0xF0)
16649663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            sz = 1;
16650663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         else
16651663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            vassert(sz == 2 || sz == 4 || sz == 8);
16652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16653663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRType tyE = szToITy(sz);
16654663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp valE = newTemp(tyE);
16655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16656663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
16657663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(valE, getIRegE(sz, pfx, modrm));
16658663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
16659663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("crc32b %s,%s\n", nameIRegE(sz, pfx, modrm),
16660663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                nameIRegG(1==getRexW(pfx) ? 8 : 4, pfx, modrm));
16661663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
16662663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 0 );
16663663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(valE, loadLE(tyE, mkexpr(addr)));
16664663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
16665663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("crc32b %s,%s\n", dis_buf,
16666663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                nameIRegG(1==getRexW(pfx) ? 8 : 4, pfx, modrm));
16667663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
16668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16669663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Somewhat funny getting/putting of the crc32 value, in order
16670663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            to ensure that it turns into 64-bit gets and puts.  However,
16671663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            mask off the upper 32 bits so as to not get memcheck false
16672663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            +ves around the helper call. */
16673663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp valG0 = newTemp(Ity_I64);
16674663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(valG0, binop(Iop_And64, getIRegG(8, pfx, modrm),
16675663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             mkU64(0xFFFFFFFF)));
16676663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
16677663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HChar* nm = NULL;
16678663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         void*  fn = NULL;
16679663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         switch (sz) {
16680663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 1: nm = "amd64g_calc_crc32b";
16681663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    fn = &amd64g_calc_crc32b; break;
16682663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 2: nm = "amd64g_calc_crc32w";
16683663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    fn = &amd64g_calc_crc32w; break;
16684663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 4: nm = "amd64g_calc_crc32l";
16685663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    fn = &amd64g_calc_crc32l; break;
16686663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 8: nm = "amd64g_calc_crc32q";
16687663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    fn = &amd64g_calc_crc32q; break;
16688663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
16689663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(nm && fn);
16690663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp valG1 = newTemp(Ity_I64);
16691663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(valG1,
16692663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                mkIRExprCCall(Ity_I64, 0/*regparm*/, nm, fn,
16693663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              mkIRExprVec_2(mkexpr(valG0),
16694663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                            widenUto64(mkexpr(valE)))));
16695663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
16696663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putIRegG(4, pfx, modrm, unop(Iop_64to32, mkexpr(valG1)));
16697663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
16698663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
16699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
16700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16701663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   default:
16702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
16703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16704663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
16705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16706663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  //decode_failure:
16707663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *decode_OK = False;
16708663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return deltaIN;
16709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16710663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  decode_success:
16711663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *decode_OK = True;
16712663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
16713663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
16714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16716663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*------------------------------------------------------------*/
16717663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---                                                      ---*/
16718663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*--- Top-level SSE4: dis_ESC_0F3A__SSE4                   ---*/
16719663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---                                                      ---*/
16720663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*------------------------------------------------------------*/
16721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16722663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_PEXTRW ( VexAbiInfo* vbi, Prefix pfx,
16723663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         Long delta, Bool isAvx )
16724663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
16725663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr  = IRTemp_INVALID;
16726663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t0    = IRTemp_INVALID;
16727663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t1    = IRTemp_INVALID;
16728663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t2    = IRTemp_INVALID;
16729663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t3    = IRTemp_INVALID;
16730663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm = getUChar(delta);
16731663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen  = 0;
16732663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
16733663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rG    = gregOfRexRM(pfx,modrm);
16734663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    imm8_20;
16735663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp xmm_vec = newTemp(Ity_V128);
16736663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp d16   = newTemp(Ity_I16);
16737663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar* mbV   = isAvx ? "v" : "";
16738663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
16739663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(0==getRexW(pfx)); /* ensured by caller */
16740663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( xmm_vec, getXMMReg(rG) );
16741663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV128to32s( xmm_vec, &t3, &t2, &t1, &t0 );
16742663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
16743663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if ( epartIsReg( modrm ) ) {
16744663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      imm8_20 = (Int)(getUChar(delta+1) & 7);
16745663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
16746663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 1 );
16747663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      imm8_20 = (Int)(getUChar(delta+alen) & 7);
16748663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
16749663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
16750663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (imm8_20) {
16751663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0:  assign(d16, unop(Iop_32to16,   mkexpr(t0))); break;
16752663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 1:  assign(d16, unop(Iop_32HIto16, mkexpr(t0))); break;
16753663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 2:  assign(d16, unop(Iop_32to16,   mkexpr(t1))); break;
16754663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 3:  assign(d16, unop(Iop_32HIto16, mkexpr(t1))); break;
16755663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 4:  assign(d16, unop(Iop_32to16,   mkexpr(t2))); break;
16756663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 5:  assign(d16, unop(Iop_32HIto16, mkexpr(t2))); break;
16757663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 6:  assign(d16, unop(Iop_32to16,   mkexpr(t3))); break;
16758663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 7:  assign(d16, unop(Iop_32HIto16, mkexpr(t3))); break;
16759663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default: vassert(0);
16760663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
16761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16762663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if ( epartIsReg( modrm ) ) {
16763663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt rE = eregOfRexRM(pfx,modrm);
16764663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      putIReg32( rE, unop(Iop_16Uto32, mkexpr(d16)) );
16765663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1+1;
16766663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP( "%spextrw $%d, %s,%s\n", mbV, imm8_20,
16767663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           nameXMMReg( rG ), nameIReg32( rE ) );
16768663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
16769663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      storeLE( mkexpr(addr), mkexpr(d16) );
16770663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen+1;
16771663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP( "%spextrw $%d, %s,%s\n", mbV, imm8_20, nameXMMReg( rG ), dis_buf );
16772663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
16773663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
16774663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
16775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16777663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_PEXTRD ( VexAbiInfo* vbi, Prefix pfx,
16778663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         Long delta, Bool isAvx )
16779663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
16780663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr  = IRTemp_INVALID;
16781663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t0    = IRTemp_INVALID;
16782663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t1    = IRTemp_INVALID;
16783663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t2    = IRTemp_INVALID;
16784663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t3    = IRTemp_INVALID;
16785663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm = 0;
16786663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen  = 0;
16787663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
16788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16789663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    imm8_10;
16790663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp xmm_vec   = newTemp(Ity_V128);
16791663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp src_dword = newTemp(Ity_I32);
16792663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar* mbV = isAvx ? "v" : "";
16793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16794663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(0==getRexW(pfx)); /* ensured by caller */
16795663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   modrm = getUChar(delta);
16796663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( xmm_vec, getXMMReg( gregOfRexRM(pfx,modrm) ) );
16797663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV128to32s( xmm_vec, &t3, &t2, &t1, &t0 );
16798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16799663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if ( epartIsReg( modrm ) ) {
16800663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      imm8_10 = (Int)(getUChar(delta+1) & 3);
16801663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
16802663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 1 );
16803663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      imm8_10 = (Int)(getUChar(delta+alen) & 3);
16804663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
16805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16806663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch ( imm8_10 ) {
16807663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0:  assign( src_dword, mkexpr(t0) ); break;
16808663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 1:  assign( src_dword, mkexpr(t1) ); break;
16809663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 2:  assign( src_dword, mkexpr(t2) ); break;
16810663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 3:  assign( src_dword, mkexpr(t3) ); break;
16811663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default: vassert(0);
16812663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
16813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16814663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if ( epartIsReg( modrm ) ) {
16815663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      putIReg32( eregOfRexRM(pfx,modrm), mkexpr(src_dword) );
16816663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1+1;
16817663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP( "%spextrd $%d, %s,%s\n", mbV, imm8_10,
16818663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           nameXMMReg( gregOfRexRM(pfx, modrm) ),
16819663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           nameIReg32( eregOfRexRM(pfx, modrm) ) );
16820663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
16821663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      storeLE( mkexpr(addr), mkexpr(src_dword) );
16822663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen+1;
16823663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP( "%spextrd $%d, %s,%s\n", mbV,
16824663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           imm8_10, nameXMMReg( gregOfRexRM(pfx, modrm) ), dis_buf );
16825663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
16826663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
16827663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
16828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16830663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_PEXTRQ ( VexAbiInfo* vbi, Prefix pfx,
16831663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         Long delta, Bool isAvx )
16832663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
16833663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr  = IRTemp_INVALID;
16834663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm = 0;
16835663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen  = 0;
16836663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
16837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16838663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int imm8_0;
16839663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp xmm_vec   = newTemp(Ity_V128);
16840663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp src_qword = newTemp(Ity_I64);
16841663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar* mbV = isAvx ? "v" : "";
16842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16843663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(1==getRexW(pfx)); /* ensured by caller */
16844663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   modrm = getUChar(delta);
16845663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( xmm_vec, getXMMReg( gregOfRexRM(pfx,modrm) ) );
16846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16847663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if ( epartIsReg( modrm ) ) {
16848663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      imm8_0 = (Int)(getUChar(delta+1) & 1);
16849663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
16850663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr   = disAMode( &alen, vbi, pfx, delta, dis_buf, 1 );
16851663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      imm8_0 = (Int)(getUChar(delta+alen) & 1);
16852663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
16853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16854663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch ( imm8_0 ) {
16855663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0:  assign( src_qword, unop(Iop_V128to64,   mkexpr(xmm_vec)) );
16856663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               break;
16857663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 1:  assign( src_qword, unop(Iop_V128HIto64, mkexpr(xmm_vec)) );
16858663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               break;
16859663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default: vassert(0);
16860663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
16861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16862663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if ( epartIsReg( modrm ) ) {
16863663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      putIReg64( eregOfRexRM(pfx,modrm), mkexpr(src_qword) );
16864663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1+1;
16865663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP( "%spextrq $%d, %s,%s\n", mbV, imm8_0,
16866663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           nameXMMReg( gregOfRexRM(pfx, modrm) ),
16867663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           nameIReg64( eregOfRexRM(pfx, modrm) ) );
16868663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
16869663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      storeLE( mkexpr(addr), mkexpr(src_qword) );
16870663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen+1;
16871663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP( "%spextrq $%d, %s,%s\n", mbV,
16872663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           imm8_0, nameXMMReg( gregOfRexRM(pfx, modrm) ), dis_buf );
16873663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
16874663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
16875663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
16876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16878663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* This can fail, in which case it returns the original (unchanged)
16879663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   delta. */
16880663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_PCMPxSTRx ( VexAbiInfo* vbi, Prefix pfx,
16881663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            Long delta, Bool isAvx, UChar opc )
16882663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
16883663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Long   delta0  = delta;
16884663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   isISTRx = opc & 2;
16885663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   isxSTRM = (opc & 1) ^ 1;
16886663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   regNoL  = 0;
16887663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   regNoR  = 0;
16888663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  imm     = 0;
16889663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr    = IRTemp_INVALID;
16890663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen    = 0;
16891663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
16892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16893663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* This is a nasty kludge.  We need to pass 2 x V128 to the helper
16894663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      (which is clean).  Since we can't do that, use a dirty helper to
16895663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      compute the results directly from the XMM regs in the guest
16896663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      state.  That means for the memory case, we need to move the left
16897663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      operand into a pseudo-register (XMM16, let's call it). */
16898663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar modrm = getUChar(delta);
16899663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (epartIsReg(modrm)) {
16900663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      regNoL = eregOfRexRM(pfx, modrm);
16901663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      regNoR = gregOfRexRM(pfx, modrm);
16902663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      imm = getUChar(delta+1);
16903663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1+1;
16904663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
16905663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      regNoL = 16; /* use XMM16 as an intermediary */
16906663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      regNoR = gregOfRexRM(pfx, modrm);
16907663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 1 );
16908663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* No alignment check; I guess that makes sense, given that
16909663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         these insns are for dealing with C style strings. */
16910663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      stmt( IRStmt_Put( OFFB_YMM16, loadLE(Ity_V128, mkexpr(addr)) ));
16911663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      imm = getUChar(delta+alen);
16912663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen+1;
16913663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
16914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16915663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Now we know the XMM reg numbers for the operands, and the
16916663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      immediate byte.  Is it one we can actually handle? Throw out any
16917663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      cases for which the helper function has not been verified. */
16918663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (imm) {
16919663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x00:
16920663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x02: case 0x08: case 0x0A: case 0x0C: case 0x12:
16921663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x1A: case 0x38: case 0x3A: case 0x44: case 0x4A:
16922663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x46:
16923663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
16924663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x01: // the 16-bit character versions of the above
16925663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x03: case 0x09: case 0x0B: case 0x0D: case 0x13:
16926663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x1B: case 0x39: case 0x3B: case 0x45: case 0x4B:
16927663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
16928663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default:
16929663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return delta0; /*FAIL*/
16930663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
16931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16932663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Who ya gonna call?  Presumably not Ghostbusters. */
16933663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   void*  fn = &amd64g_dirtyhelper_PCMPxSTRx;
16934663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar* nm = "amd64g_dirtyhelper_PCMPxSTRx";
16935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16936663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Round up the arguments.  Note that this is a kludge -- the use
16937663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      of mkU64 rather than mkIRExpr_HWord implies the assumption that
16938663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      the host's word size is 64-bit. */
16939663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt gstOffL = regNoL == 16 ? OFFB_YMM16 : ymmGuestRegOffset(regNoL);
16940663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt gstOffR = ymmGuestRegOffset(regNoR);
16941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16942663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRExpr*  opc4_and_imm = mkU64((opc << 8) | (imm & 0xFF));
16943663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRExpr*  gstOffLe     = mkU64(gstOffL);
16944663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRExpr*  gstOffRe     = mkU64(gstOffR);
16945663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRExpr*  edxIN        = isISTRx ? mkU64(0) : getIRegRDX(8);
16946663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRExpr*  eaxIN        = isISTRx ? mkU64(0) : getIRegRAX(8);
16947663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRExpr** args
16948663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      = mkIRExprVec_5( opc4_and_imm, gstOffLe, gstOffRe, edxIN, eaxIN );
16949663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
16950663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp   resT = newTemp(Ity_I64);
16951663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRDirty* d    = unsafeIRDirty_1_N( resT, 0/*regparms*/, nm, fn, args );
16952663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* It's not really a dirty call, but we can't use the clean helper
16953663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      mechanism here for the very lame reason that we can't pass 2 x
16954663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      V128s by value to a helper, nor get one back.  Hence this
16955663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      roundabout scheme. */
16956663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   d->needsBBP = True;
16957663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   d->nFxState = 2;
16958663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vex_bzero(&d->fxState, sizeof(d->fxState));
16959663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   d->fxState[0].fx     = Ifx_Read;
16960663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   d->fxState[0].offset = gstOffL;
16961663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   d->fxState[0].size   = sizeof(U128);
16962663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   d->fxState[1].fx     = Ifx_Read;
16963663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   d->fxState[1].offset = gstOffR;
16964663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   d->fxState[1].size   = sizeof(U128);
16965663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (isxSTRM) {
16966663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Declare that the helper writes XMM0. */
16967663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d->nFxState = 3;
16968663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d->fxState[2].fx     = Ifx_Write;
16969663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d->fxState[2].offset = ymmGuestRegOffset(0);
16970663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d->fxState[2].size   = sizeof(U128);
16971663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
16972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16973663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   stmt( IRStmt_Dirty(d) );
16974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16975663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Now resT[15:0] holds the new OSZACP values, so the condition
16976663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      codes must be updated. And for a xSTRI case, resT[31:16] holds
16977663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      the new ECX value, so stash that too. */
16978663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (!isxSTRM) {
16979663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      putIReg64(R_RCX, binop(Iop_And64,
16980663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             binop(Iop_Shr64, mkexpr(resT), mkU8(16)),
16981663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             mkU64(0xFFFF)));
16982663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
16983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16984663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Zap the upper half of the dest reg as per AVX conventions. */
16985663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (isxSTRM && isAvx)
16986663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      putYMMRegLane128(/*YMM*/0, 1, mkV128(0));
16987663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
16988663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   stmt( IRStmt_Put(
16989663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            OFFB_CC_DEP1,
16990663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            binop(Iop_And64, mkexpr(resT), mkU64(0xFFFF))
16991663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   ));
16992663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   stmt( IRStmt_Put( OFFB_CC_OP,   mkU64(AMD64G_CC_OP_COPY) ));
16993663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   stmt( IRStmt_Put( OFFB_CC_DEP2, mkU64(0) ));
16994663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   stmt( IRStmt_Put( OFFB_CC_NDEP, mkU64(0) ));
16995663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
16996663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (regNoL == 16) {
16997663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%spcmp%cstr%c $%x,%s,%s\n",
16998663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          isAvx ? "v" : "", isISTRx ? 'i' : 'e', isxSTRM ? 'm' : 'i',
16999663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          (UInt)imm, dis_buf, nameXMMReg(regNoR));
17000663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
17001663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%spcmp%cstr%c $%x,%s,%s\n",
17002663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          isAvx ? "v" : "", isISTRx ? 'i' : 'e', isxSTRM ? 'm' : 'i',
17003663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          (UInt)imm, nameXMMReg(regNoL), nameXMMReg(regNoR));
17004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
17005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17006663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
17007663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
17008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17010663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRTemp math_PINSRB_128 ( IRTemp v128, IRTemp u8, UInt imm8 )
17011663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
17012663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(imm8 >= 0 && imm8 <= 15);
17013663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17014663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // Create a V128 value which has the selected byte in the
17015663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // specified lane, and zeroes everywhere else.
17016663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp tmp128    = newTemp(Ity_V128);
17017663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp halfshift = newTemp(Ity_I64);
17018663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(halfshift, binop(Iop_Shl64,
17019663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           unop(Iop_8Uto64, mkexpr(u8)),
17020663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           mkU8(8 * (imm8 & 7))));
17021663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (imm8 < 8) {
17022663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(tmp128, binop(Iop_64HLtoV128, mkU64(0), mkexpr(halfshift)));
17023663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
17024663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(tmp128, binop(Iop_64HLtoV128, mkexpr(halfshift), mkU64(0)));
17025663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
17026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17027663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UShort mask = ~(1 << imm8);
17028663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp res  = newTemp(Ity_V128);
17029663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( res, binop(Iop_OrV128,
17030663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      mkexpr(tmp128),
17031663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      binop(Iop_AndV128, mkexpr(v128), mkV128(mask))) );
17032663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return res;
17033663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
17034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17036663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRTemp math_PINSRD_128 ( IRTemp v128, IRTemp u32, UInt imm8 )
17037663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
17038663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp z32 = newTemp(Ity_I32);
17039663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(z32, mkU32(0));
17040663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17041663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Surround u32 with zeroes as per imm, giving us something we can
17042663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      OR into a suitably masked-out v128.*/
17043663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp withZs = newTemp(Ity_V128);
17044663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UShort mask = 0;
17045663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (imm8) {
17046663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 3:  mask = 0x0FFF;
17047663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               assign(withZs, mkV128from32s(u32, z32, z32, z32));
17048663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               break;
17049663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 2:  mask = 0xF0FF;
17050663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               assign(withZs, mkV128from32s(z32, u32, z32, z32));
17051663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               break;
17052663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 1:  mask = 0xFF0F;
17053663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               assign(withZs, mkV128from32s(z32, z32, u32, z32));
17054663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               break;
17055663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0:  mask = 0xFFF0;
17056663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               assign(withZs, mkV128from32s(z32, z32, z32, u32));
17057663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               break;
17058663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default: vassert(0);
17059663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
17060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17061663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp res = newTemp(Ity_V128);
17062663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(res, binop( Iop_OrV128,
17063663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      mkexpr(withZs),
17064663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      binop( Iop_AndV128, mkexpr(v128), mkV128(mask) ) ) );
17065663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return res;
17066663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
17067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17069663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRTemp math_PINSRQ_128 ( IRTemp v128, IRTemp u64, UInt imm8 )
17070663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
17071663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Surround u64 with zeroes as per imm, giving us something we can
17072663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      OR into a suitably masked-out v128.*/
17073663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp withZs = newTemp(Ity_V128);
17074663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UShort mask = 0;
17075663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (imm8 == 0) {
17076663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      mask = 0xFF00;
17077663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(withZs, binop(Iop_64HLtoV128, mkU64(0), mkexpr(u64)));
17078663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
17079663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(imm8 == 1);
17080663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      mask = 0x00FF;
17081663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( withZs, binop(Iop_64HLtoV128, mkexpr(u64), mkU64(0)));
17082663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
17083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17084663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp res = newTemp(Ity_V128);
17085663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( res, binop( Iop_OrV128,
17086663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       mkexpr(withZs),
17087663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       binop( Iop_AndV128, mkexpr(v128), mkV128(mask) ) ) );
17088663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return res;
17089663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
17090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17092663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRTemp math_INSERTPS ( IRTemp dstV, IRTemp toInsertD, UInt imm8 )
17093663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
17094663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   const IRTemp inval = IRTemp_INVALID;
17095663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp dstDs[4] = { inval, inval, inval, inval };
17096663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV128to32s( dstV, &dstDs[3], &dstDs[2], &dstDs[1], &dstDs[0] );
17097663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17098663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(imm8 <= 255);
17099663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   dstDs[(imm8 >> 4) & 3] = toInsertD; /* "imm8_count_d" */
17100663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17101663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt imm8_zmask = (imm8 & 15);
17102663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp zero_32 = newTemp(Ity_I32);
17103663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( zero_32, mkU32(0) );
17104663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp resV = newTemp(Ity_V128);
17105663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( resV, mkV128from32s(
17106663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    ((imm8_zmask & 8) == 8) ? zero_32 : dstDs[3],
17107663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    ((imm8_zmask & 4) == 4) ? zero_32 : dstDs[2],
17108663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    ((imm8_zmask & 2) == 2) ? zero_32 : dstDs[1],
17109663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    ((imm8_zmask & 1) == 1) ? zero_32 : dstDs[0]) );
17110663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return resV;
17111663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
17112663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17113663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17114663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_PEXTRB_128_GtoE ( VexAbiInfo* vbi, Prefix pfx,
17115663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  Long delta, Bool isAvx )
17116663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
17117663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr     = IRTemp_INVALID;
17118663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen     = 0;
17119663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
17120663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp xmm_vec  = newTemp(Ity_V128);
17121663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp sel_lane = newTemp(Ity_I32);
17122663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp shr_lane = newTemp(Ity_I32);
17123663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar* mbV      = isAvx ? "v" : "";
17124663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm    = getUChar(delta);
17125663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t3, t2, t1, t0;
17126663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    imm8;
17127663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( xmm_vec, getXMMReg( gregOfRexRM(pfx,modrm) ) );
17128663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t3 = t2 = t1 = t0 = IRTemp_INVALID;
17129663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV128to32s( xmm_vec, &t3, &t2, &t1, &t0 );
17130663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17131663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if ( epartIsReg( modrm ) ) {
17132663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      imm8 = (Int)getUChar(delta+1);
17133663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
17134663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 1 );
17135663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      imm8 = (Int)getUChar(delta+alen);
17136663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
17137663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch ( (imm8 >> 2) & 3 ) {
17138663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0:  assign( sel_lane, mkexpr(t0) ); break;
17139663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 1:  assign( sel_lane, mkexpr(t1) ); break;
17140663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 2:  assign( sel_lane, mkexpr(t2) ); break;
17141663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 3:  assign( sel_lane, mkexpr(t3) ); break;
17142663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default: vassert(0);
17143663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
17144663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( shr_lane,
17145663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           binop( Iop_Shr32, mkexpr(sel_lane), mkU8(((imm8 & 3)*8)) ) );
17146663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17147663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if ( epartIsReg( modrm ) ) {
17148663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      putIReg64( eregOfRexRM(pfx,modrm),
17149663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 unop( Iop_32Uto64,
17150663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       binop(Iop_And32, mkexpr(shr_lane), mkU32(255)) ) );
17151663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1+1;
17152663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP( "%spextrb $%d, %s,%s\n", mbV, imm8,
17153663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           nameXMMReg( gregOfRexRM(pfx, modrm) ),
17154663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           nameIReg64( eregOfRexRM(pfx, modrm) ) );
17155663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
17156663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      storeLE( mkexpr(addr), unop(Iop_32to8, mkexpr(shr_lane) ) );
17157663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen+1;
17158663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP( "%spextrb $%d,%s,%s\n", mbV,
17159663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           imm8, nameXMMReg( gregOfRexRM(pfx, modrm) ), dis_buf );
17160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
17161663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17162663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
17163663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
17164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17166663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRTemp math_DPPD_128 ( IRTemp src_vec, IRTemp dst_vec, UInt imm8 )
17167663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
17168663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(imm8 < 256);
17169663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UShort imm8_perms[4] = { 0x0000, 0x00FF, 0xFF00, 0xFFFF };
17170663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp and_vec = newTemp(Ity_V128);
17171663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp sum_vec = newTemp(Ity_V128);
17172663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( and_vec, binop( Iop_AndV128,
17173663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           binop( Iop_Mul64Fx2,
17174663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  mkexpr(dst_vec), mkexpr(src_vec) ),
17175663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           mkV128( imm8_perms[ ((imm8 >> 4) & 3) ] ) ) );
17176663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17177663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( sum_vec, binop( Iop_Add64F0x2,
17178663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           binop( Iop_InterleaveHI64x2,
17179663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  mkexpr(and_vec), mkexpr(and_vec) ),
17180663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           binop( Iop_InterleaveLO64x2,
17181663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  mkexpr(and_vec), mkexpr(and_vec) ) ) );
17182663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp res = newTemp(Ity_V128);
17183663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(res, binop( Iop_AndV128,
17184663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      binop( Iop_InterleaveLO64x2,
17185663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             mkexpr(sum_vec), mkexpr(sum_vec) ),
17186663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      mkV128( imm8_perms[ (imm8 & 3) ] ) ) );
17187663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return res;
17188663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
17189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17191663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRTemp math_DPPS_128 ( IRTemp src_vec, IRTemp dst_vec, UInt imm8 )
17192663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
17193663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(imm8 < 256);
17194663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp tmp_prod_vec = newTemp(Ity_V128);
17195663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp prod_vec     = newTemp(Ity_V128);
17196663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp sum_vec      = newTemp(Ity_V128);
17197663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp v3, v2, v1, v0;
17198663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   v3 = v2 = v1 = v0   = IRTemp_INVALID;
17199663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UShort imm8_perms[16] = { 0x0000, 0x000F, 0x00F0, 0x00FF, 0x0F00,
17200663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             0x0F0F, 0x0FF0, 0x0FFF, 0xF000, 0xF00F,
17201663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             0xF0F0, 0xF0FF, 0xFF00, 0xFF0F, 0xFFF0,
17202663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             0xFFFF };
17203663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17204663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( tmp_prod_vec,
17205663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           binop( Iop_AndV128,
17206663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  binop( Iop_Mul32Fx4, mkexpr(dst_vec),
17207663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                       mkexpr(src_vec) ),
17208663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  mkV128( imm8_perms[((imm8 >> 4)& 15)] ) ) );
17209663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV128to32s( tmp_prod_vec, &v3, &v2, &v1, &v0 );
17210663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( prod_vec, mkV128from32s( v3, v1, v2, v0 ) );
17211663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17212663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( sum_vec, binop( Iop_Add32Fx4,
17213663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           binop( Iop_InterleaveHI32x4,
17214663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  mkexpr(prod_vec), mkexpr(prod_vec) ),
17215663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           binop( Iop_InterleaveLO32x4,
17216663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  mkexpr(prod_vec), mkexpr(prod_vec) ) ) );
17217663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17218663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp res = newTemp(Ity_V128);
17219663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( res, binop( Iop_AndV128,
17220663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       binop( Iop_Add32Fx4,
17221663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              binop( Iop_InterleaveHI32x4,
17222663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                     mkexpr(sum_vec), mkexpr(sum_vec) ),
17223663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              binop( Iop_InterleaveLO32x4,
17224663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                     mkexpr(sum_vec), mkexpr(sum_vec) ) ),
17225663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       mkV128( imm8_perms[ (imm8 & 15) ] ) ) );
17226663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return res;
17227663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
17228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17230663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRTemp math_MPSADBW_128 ( IRTemp dst_vec, IRTemp src_vec, UInt imm8 )
17231663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
17232663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Mask out bits of the operands we don't need.  This isn't
17233663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      strictly necessary, but it does ensure Memcheck doesn't
17234663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      give us any false uninitialised value errors as a
17235663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      result. */
17236663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UShort src_mask[4] = { 0x000F, 0x00F0, 0x0F00, 0xF000 };
17237663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UShort dst_mask[2] = { 0x07FF, 0x7FF0 };
17238663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17239663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp src_maskV = newTemp(Ity_V128);
17240663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp dst_maskV = newTemp(Ity_V128);
17241663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(src_maskV, mkV128( src_mask[ imm8 & 3 ] ));
17242663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(dst_maskV, mkV128( dst_mask[ (imm8 >> 2) & 1 ] ));
17243663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17244663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp src_masked = newTemp(Ity_V128);
17245663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp dst_masked = newTemp(Ity_V128);
17246663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(src_masked, binop(Iop_AndV128, mkexpr(src_vec), mkexpr(src_maskV)));
17247663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(dst_masked, binop(Iop_AndV128, mkexpr(dst_vec), mkexpr(dst_maskV)));
17248663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17249663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Generate 4 64 bit values that we can hand to a clean helper */
17250663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp sHi = newTemp(Ity_I64);
17251663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp sLo = newTemp(Ity_I64);
17252663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( sHi, unop(Iop_V128HIto64, mkexpr(src_masked)) );
17253663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( sLo, unop(Iop_V128to64,   mkexpr(src_masked)) );
17254663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17255663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp dHi = newTemp(Ity_I64);
17256663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp dLo = newTemp(Ity_I64);
17257663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( dHi, unop(Iop_V128HIto64, mkexpr(dst_masked)) );
17258663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( dLo, unop(Iop_V128to64,   mkexpr(dst_masked)) );
17259663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17260663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Compute halves of the result separately */
17261663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp resHi = newTemp(Ity_I64);
17262663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp resLo = newTemp(Ity_I64);
17263663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17264663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRExpr** argsHi
17265663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      = mkIRExprVec_5( mkexpr(sHi), mkexpr(sLo), mkexpr(dHi), mkexpr(dLo),
17266663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       mkU64( 0x80 | (imm8 & 7) ));
17267663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRExpr** argsLo
17268663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      = mkIRExprVec_5( mkexpr(sHi), mkexpr(sLo), mkexpr(dHi), mkexpr(dLo),
17269663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       mkU64( 0x00 | (imm8 & 7) ));
17270663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17271663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(resHi, mkIRExprCCall( Ity_I64, 0/*regparm*/,
17272663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                "amd64g_calc_mpsadbw",
17273663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                &amd64g_calc_mpsadbw, argsHi ));
17274663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(resLo, mkIRExprCCall( Ity_I64, 0/*regparm*/,
17275663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                "amd64g_calc_mpsadbw",
17276663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                &amd64g_calc_mpsadbw, argsLo ));
17277663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17278663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp res = newTemp(Ity_V128);
17279663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(res, binop(Iop_64HLtoV128, mkexpr(resHi), mkexpr(resLo)));
17280663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return res;
17281663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
17282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17283663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_EXTRACTPS ( VexAbiInfo* vbi, Prefix pfx,
17284663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            Long delta, Bool isAvx )
17285663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
17286663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr       = IRTemp_INVALID;
17287663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen       = 0;
17288663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
17289663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm      = getUChar(delta);
17290663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int imm8_10;
17291663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp xmm_vec    = newTemp(Ity_V128);
17292663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp src_dword  = newTemp(Ity_I32);
17293663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rG         = gregOfRexRM(pfx,modrm);
17294663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t3, t2, t1, t0;
17295663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t3 = t2 = t1 = t0 = IRTemp_INVALID;
17296663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17297663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( xmm_vec, getXMMReg( rG ) );
17298663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV128to32s( xmm_vec, &t3, &t2, &t1, &t0 );
17299663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17300663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if ( epartIsReg( modrm ) ) {
17301663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      imm8_10 = (Int)(getUChar(delta+1) & 3);
17302663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
17303663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 1 );
17304663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      imm8_10 = (Int)(getUChar(delta+alen) & 3);
17305663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
17306663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17307663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch ( imm8_10 ) {
17308663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0:  assign( src_dword, mkexpr(t0) ); break;
17309663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 1:  assign( src_dword, mkexpr(t1) ); break;
17310663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 2:  assign( src_dword, mkexpr(t2) ); break;
17311663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 3:  assign( src_dword, mkexpr(t3) ); break;
17312663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default: vassert(0);
17313663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
17314663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17315663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if ( epartIsReg( modrm ) ) {
17316663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt rE = eregOfRexRM(pfx,modrm);
17317663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      putIReg32( rE, mkexpr(src_dword) );
17318663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1+1;
17319663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP( "%sextractps $%d, %s,%s\n", isAvx ? "v" : "", imm8_10,
17320663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           nameXMMReg( rG ), nameIReg32( rE ) );
17321663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
17322663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      storeLE( mkexpr(addr), mkexpr(src_dword) );
17323663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen+1;
17324663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP( "%sextractps $%d, %s,%s\n", isAvx ? "v" : "", imm8_10,
17325663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           nameXMMReg( rG ), dis_buf );
17326663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
17327663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17328663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
17329663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
17330663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17331663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17332663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRTemp math_PCLMULQDQ( IRTemp dV, IRTemp sV, UInt imm8 )
17333663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
17334663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t0 = newTemp(Ity_I64);
17335663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t1 = newTemp(Ity_I64);
17336663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(t0, unop((imm8&1)? Iop_V128HIto64 : Iop_V128to64,
17337663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              mkexpr(dV)));
17338663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(t1, unop((imm8&16) ? Iop_V128HIto64 : Iop_V128to64,
17339663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              mkexpr(sV)));
17340663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17341663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t2 = newTemp(Ity_I64);
17342663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t3 = newTemp(Ity_I64);
17343663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17344663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRExpr** args;
17345663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17346663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   args = mkIRExprVec_3(mkexpr(t0), mkexpr(t1), mkU64(0));
17347663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(t2, mkIRExprCCall(Ity_I64,0, "amd64g_calculate_pclmul",
17348663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            &amd64g_calculate_pclmul, args));
17349663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   args = mkIRExprVec_3(mkexpr(t0), mkexpr(t1), mkU64(1));
17350663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(t3, mkIRExprCCall(Ity_I64,0, "amd64g_calculate_pclmul",
17351663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            &amd64g_calculate_pclmul, args));
17352663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17353663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp res     = newTemp(Ity_V128);
17354663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(res, binop(Iop_64HLtoV128, mkexpr(t3), mkexpr(t2)));
17355663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return res;
17356663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
17357663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17358663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17359663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng__attribute__((noinline))
17360663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic
17361663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengLong dis_ESC_0F3A__SSE4 ( Bool* decode_OK,
17362663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          VexAbiInfo* vbi,
17363663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          Prefix pfx, Int sz, Long deltaIN )
17364663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
17365663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr  = IRTemp_INVALID;
17366663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm = 0;
17367663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen  = 0;
17368663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
17369663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17370663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *decode_OK = False;
17371663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17372663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Long   delta = deltaIN;
17373663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  opc   = getUChar(delta);
17374663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   delta++;
17375663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (opc) {
17376663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17377663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x08:
17378663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 3A 08 /r ib = ROUNDPS imm8, xmm2/m128, xmm1 */
17379663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
17380663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17381663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp src0 = newTemp(Ity_F32);
17382663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp src1 = newTemp(Ity_F32);
17383663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp src2 = newTemp(Ity_F32);
17384663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp src3 = newTemp(Ity_F32);
17385663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp res0 = newTemp(Ity_F32);
17386663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp res1 = newTemp(Ity_F32);
17387663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp res2 = newTemp(Ity_F32);
17388663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp res3 = newTemp(Ity_F32);
17389663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp rm   = newTemp(Ity_I32);
17390663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int    imm  = 0;
17391663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17392663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
17393663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17394663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
17395663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( src0,
17396663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    getXMMRegLane32F( eregOfRexRM(pfx, modrm), 0 ) );
17397663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( src1,
17398663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    getXMMRegLane32F( eregOfRexRM(pfx, modrm), 1 ) );
17399663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( src2,
17400663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    getXMMRegLane32F( eregOfRexRM(pfx, modrm), 2 ) );
17401663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( src3,
17402663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    getXMMRegLane32F( eregOfRexRM(pfx, modrm), 3 ) );
17403663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm = getUChar(delta+1);
17404663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (imm & ~15) goto decode_failure;
17405663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1+1;
17406663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "roundps $%d,%s,%s\n",
17407663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 imm, nameXMMReg( eregOfRexRM(pfx, modrm) ),
17408663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      nameXMMReg( gregOfRexRM(pfx, modrm) ) );
17409663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
17410663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 1 );
17411663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gen_SEGV_if_not_16_aligned(addr);
17412663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( src0, loadLE(Ity_F32,
17413663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                 binop(Iop_Add64, mkexpr(addr), mkU64(0) )));
17414663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( src1, loadLE(Ity_F32,
17415663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                 binop(Iop_Add64, mkexpr(addr), mkU64(4) )));
17416663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( src2, loadLE(Ity_F32,
17417663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                 binop(Iop_Add64, mkexpr(addr), mkU64(8) )));
17418663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( src3, loadLE(Ity_F32,
17419663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                 binop(Iop_Add64, mkexpr(addr), mkU64(12) )));
17420663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm = getUChar(delta+alen);
17421663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (imm & ~15) goto decode_failure;
17422663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen+1;
17423663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "roundps $%d,%s,%s\n",
17424663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 imm, dis_buf, nameXMMReg( gregOfRexRM(pfx, modrm) ) );
17425663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
17426663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17427663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* (imm & 3) contains an Intel-encoded rounding mode.  Because
17428663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            that encoding is the same as the encoding for IRRoundingMode,
17429663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            we can use that value directly in the IR as a rounding
17430663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            mode. */
17431663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(rm, (imm & 4) ? get_sse_roundingmode() : mkU32(imm & 3));
17432663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17433663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(res0, binop(Iop_RoundF32toInt, mkexpr(rm), mkexpr(src0)) );
17434663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(res1, binop(Iop_RoundF32toInt, mkexpr(rm), mkexpr(src1)) );
17435663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(res2, binop(Iop_RoundF32toInt, mkexpr(rm), mkexpr(src2)) );
17436663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(res3, binop(Iop_RoundF32toInt, mkexpr(rm), mkexpr(src3)) );
17437663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17438663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMRegLane32F( gregOfRexRM(pfx, modrm), 0, mkexpr(res0) );
17439663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMRegLane32F( gregOfRexRM(pfx, modrm), 1, mkexpr(res1) );
17440663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMRegLane32F( gregOfRexRM(pfx, modrm), 2, mkexpr(res2) );
17441663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMRegLane32F( gregOfRexRM(pfx, modrm), 3, mkexpr(res3) );
17442663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17443663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
17444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
17445663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
17446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17447663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x09:
17448663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 3A 09 /r ib = ROUNDPD imm8, xmm2/m128, xmm1 */
17449663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
17450663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17451663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp src0 = newTemp(Ity_F64);
17452663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp src1 = newTemp(Ity_F64);
17453663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp res0 = newTemp(Ity_F64);
17454663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp res1 = newTemp(Ity_F64);
17455663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp rm   = newTemp(Ity_I32);
17456663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int    imm  = 0;
17457663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17458663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
17459663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17460663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
17461663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( src0,
17462663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    getXMMRegLane64F( eregOfRexRM(pfx, modrm), 0 ) );
17463663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( src1,
17464663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    getXMMRegLane64F( eregOfRexRM(pfx, modrm), 1 ) );
17465663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm = getUChar(delta+1);
17466663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (imm & ~15) goto decode_failure;
17467663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1+1;
17468663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "roundpd $%d,%s,%s\n",
17469663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 imm, nameXMMReg( eregOfRexRM(pfx, modrm) ),
17470663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      nameXMMReg( gregOfRexRM(pfx, modrm) ) );
17471663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
17472663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 1 );
17473663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gen_SEGV_if_not_16_aligned(addr);
17474663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( src0, loadLE(Ity_F64,
17475663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                 binop(Iop_Add64, mkexpr(addr), mkU64(0) )));
17476663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( src1, loadLE(Ity_F64,
17477663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                 binop(Iop_Add64, mkexpr(addr), mkU64(8) )));
17478663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm = getUChar(delta+alen);
17479663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (imm & ~15) goto decode_failure;
17480663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen+1;
17481663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "roundpd $%d,%s,%s\n",
17482663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 imm, dis_buf, nameXMMReg( gregOfRexRM(pfx, modrm) ) );
17483663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
17484663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17485663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* (imm & 3) contains an Intel-encoded rounding mode.  Because
17486663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            that encoding is the same as the encoding for IRRoundingMode,
17487663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            we can use that value directly in the IR as a rounding
17488663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            mode. */
17489663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(rm, (imm & 4) ? get_sse_roundingmode() : mkU32(imm & 3));
17490663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17491663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(res0, binop(Iop_RoundF64toInt, mkexpr(rm), mkexpr(src0)) );
17492663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(res1, binop(Iop_RoundF64toInt, mkexpr(rm), mkexpr(src1)) );
17493663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17494663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMRegLane64F( gregOfRexRM(pfx, modrm), 0, mkexpr(res0) );
17495663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMRegLane64F( gregOfRexRM(pfx, modrm), 1, mkexpr(res1) );
17496663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17497663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
17498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
17499663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
17500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17501663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x0A:
17502663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x0B:
17503663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 3A 0A /r ib = ROUNDSS imm8, xmm2/m32, xmm1
17504663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         66 0F 3A 0B /r ib = ROUNDSD imm8, xmm2/m64, xmm1
17505663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      */
17506663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
17507663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17508663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Bool   isD = opc == 0x0B;
17509663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp src = newTemp(isD ? Ity_F64 : Ity_F32);
17510663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp res = newTemp(isD ? Ity_F64 : Ity_F32);
17511663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int    imm = 0;
17512663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17513663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
17514663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17515663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
17516663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( src,
17517663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    isD ? getXMMRegLane64F( eregOfRexRM(pfx, modrm), 0 )
17518663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        : getXMMRegLane32F( eregOfRexRM(pfx, modrm), 0 ) );
17519663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm = getUChar(delta+1);
17520663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (imm & ~15) goto decode_failure;
17521663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1+1;
17522663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "rounds%c $%d,%s,%s\n",
17523663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 isD ? 'd' : 's',
17524663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 imm, nameXMMReg( eregOfRexRM(pfx, modrm) ),
17525663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      nameXMMReg( gregOfRexRM(pfx, modrm) ) );
17526663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
17527663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 1 );
17528663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( src, loadLE( isD ? Ity_F64 : Ity_F32, mkexpr(addr) ));
17529663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm = getUChar(delta+alen);
17530663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (imm & ~15) goto decode_failure;
17531663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen+1;
17532663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "rounds%c $%d,%s,%s\n",
17533663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 isD ? 'd' : 's',
17534663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 imm, dis_buf, nameXMMReg( gregOfRexRM(pfx, modrm) ) );
17535663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
17536663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17537663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* (imm & 3) contains an Intel-encoded rounding mode.  Because
17538663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            that encoding is the same as the encoding for IRRoundingMode,
17539663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            we can use that value directly in the IR as a rounding
17540663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            mode. */
17541663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(res, binop(isD ? Iop_RoundF64toInt : Iop_RoundF32toInt,
17542663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           (imm & 4) ? get_sse_roundingmode()
17543663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                     : mkU32(imm & 3),
17544663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           mkexpr(src)) );
17545663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17546663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (isD)
17547663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putXMMRegLane64F( gregOfRexRM(pfx, modrm), 0, mkexpr(res) );
17548663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         else
17549663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putXMMRegLane32F( gregOfRexRM(pfx, modrm), 0, mkexpr(res) );
17550663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17551663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
17552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
17553663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
17554663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17555663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x0C:
17556663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 3A 0C /r ib = BLENDPS xmm1, xmm2/m128, imm8
17557663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Blend Packed Single Precision Floating-Point Values (XMM) */
17558663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
17559663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17560663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int imm8;
17561663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dst_vec = newTemp(Ity_V128);
17562663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp src_vec = newTemp(Ity_V128);
17563663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17564663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
17565663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17566663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( dst_vec, getXMMReg( gregOfRexRM(pfx, modrm) ) );
17567663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17568663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if ( epartIsReg( modrm ) ) {
17569663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = (Int)getUChar(delta+1);
17570663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( src_vec, getXMMReg( eregOfRexRM(pfx, modrm) ) );
17571663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1+1;
17572663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "blendps $%d, %s,%s\n", imm8,
17573663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 nameXMMReg( eregOfRexRM(pfx, modrm) ),
17574663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 nameXMMReg( gregOfRexRM(pfx, modrm) ) );
17575663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
17576663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf,
17577663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             1/* imm8 is 1 byte after the amode */ );
17578663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gen_SEGV_if_not_16_aligned( addr );
17579663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( src_vec, loadLE( Ity_V128, mkexpr(addr) ) );
17580663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = (Int)getUChar(delta+alen);
17581663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen+1;
17582663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "blendpd $%d, %s,%s\n",
17583663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 imm8, dis_buf, nameXMMReg( gregOfRexRM(pfx, modrm) ) );
17584663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
17585663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17586663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMReg( gregOfRexRM(pfx, modrm),
17587663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    mkexpr( math_BLENDPS_128( src_vec, dst_vec, imm8) ) );
17588663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
17589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
17590663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
17591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17592663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x0D:
17593663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 3A 0D /r ib = BLENDPD xmm1, xmm2/m128, imm8
17594663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Blend Packed Double Precision Floating-Point Values (XMM) */
17595663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
17596663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17597663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int imm8;
17598663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dst_vec = newTemp(Ity_V128);
17599663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp src_vec = newTemp(Ity_V128);
17600663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17601663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
17602663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( dst_vec, getXMMReg( gregOfRexRM(pfx, modrm) ) );
17603663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17604663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if ( epartIsReg( modrm ) ) {
17605663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = (Int)getUChar(delta+1);
17606663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( src_vec, getXMMReg( eregOfRexRM(pfx, modrm) ) );
17607663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1+1;
17608663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "blendpd $%d, %s,%s\n", imm8,
17609663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 nameXMMReg( eregOfRexRM(pfx, modrm) ),
17610663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 nameXMMReg( gregOfRexRM(pfx, modrm) ) );
17611663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
17612663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf,
17613663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             1/* imm8 is 1 byte after the amode */ );
17614663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gen_SEGV_if_not_16_aligned( addr );
17615663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( src_vec, loadLE( Ity_V128, mkexpr(addr) ) );
17616663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = (Int)getUChar(delta+alen);
17617663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen+1;
17618663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "blendpd $%d, %s,%s\n",
17619663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 imm8, dis_buf, nameXMMReg( gregOfRexRM(pfx, modrm) ) );
17620663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
17621663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17622663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMReg( gregOfRexRM(pfx, modrm),
17623663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    mkexpr( math_BLENDPD_128( src_vec, dst_vec, imm8) ) );
17624663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
17625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
17626663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
17627663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17628663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x0E:
17629663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 3A 0E /r ib = PBLENDW xmm1, xmm2/m128, imm8
17630663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Blend Packed Words (XMM) */
17631663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
17632663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17633663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int imm8;
17634663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dst_vec = newTemp(Ity_V128);
17635663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp src_vec = newTemp(Ity_V128);
17636663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17637663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
17638663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17639663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( dst_vec, getXMMReg( gregOfRexRM(pfx, modrm) ) );
17640663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17641663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if ( epartIsReg( modrm ) ) {
17642663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = (Int)getUChar(delta+1);
17643663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( src_vec, getXMMReg( eregOfRexRM(pfx, modrm) ) );
17644663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1+1;
17645663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "pblendw $%d, %s,%s\n", imm8,
17646663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 nameXMMReg( eregOfRexRM(pfx, modrm) ),
17647663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 nameXMMReg( gregOfRexRM(pfx, modrm) ) );
17648663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
17649663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf,
17650663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             1/* imm8 is 1 byte after the amode */ );
17651663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gen_SEGV_if_not_16_aligned( addr );
17652663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( src_vec, loadLE( Ity_V128, mkexpr(addr) ) );
17653663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = (Int)getUChar(delta+alen);
17654663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen+1;
17655663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "pblendw $%d, %s,%s\n",
17656663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 imm8, dis_buf, nameXMMReg( gregOfRexRM(pfx, modrm) ) );
17657663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
17658663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17659663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMReg( gregOfRexRM(pfx, modrm),
17660663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    mkexpr( math_PBLENDW_128( src_vec, dst_vec, imm8) ) );
17661663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
17662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
17663663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
17664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17665663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x14:
17666663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 3A 14 /r ib = PEXTRB r/m16, xmm, imm8
17667663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Extract Byte from xmm, store in mem or zero-extend + store in gen.reg.
17668663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         (XMM) */
17669663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
17670663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_PEXTRB_128_GtoE( vbi, pfx, delta, False/*!isAvx*/ );
17671663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
17672663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
17673663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
17674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17675663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x15:
17676663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 3A 15 /r ib = PEXTRW r/m16, xmm, imm8
17677663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Extract Word from xmm, store in mem or zero-extend + store in gen.reg.
17678663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         (XMM) */
17679663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
17680663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_PEXTRW( vbi, pfx, delta, False/*!isAvx*/ );
17681663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
17682663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
17683663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
17684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17685663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x16:
17686663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 no-REX.W 0F 3A 16 /r ib = PEXTRD reg/mem32, xmm2, imm8
17687663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Extract Doubleword int from xmm reg and store in gen.reg or mem. (XMM)
17688663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Note that this insn has the same opcodes as PEXTRQ, but
17689663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         here the REX.W bit is _not_ present */
17690663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
17691663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && sz == 2 /* REX.W is _not_ present */) {
17692663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_PEXTRD( vbi, pfx, delta, False/*!isAvx*/ );
17693663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
17694663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
17695663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 REX.W 0F 3A 16 /r ib = PEXTRQ reg/mem64, xmm2, imm8
17696663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Extract Quadword int from xmm reg and store in gen.reg or mem. (XMM)
17697663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Note that this insn has the same opcodes as PEXTRD, but
17698663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         here the REX.W bit is present */
17699663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
17700663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && sz == 8 /* REX.W is present */) {
17701663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_PEXTRQ( vbi, pfx, delta, False/*!isAvx*/);
17702663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
17703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
17704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
17705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17706663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x17:
17707663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 3A 17 /r ib = EXTRACTPS reg/mem32, xmm2, imm8 Extract
17708663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         float from xmm reg and store in gen.reg or mem.  This is
17709663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         identical to PEXTRD, except that REX.W appears to be ignored.
17710663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      */
17711663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
17712663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (sz == 2 || /* ignore redundant REX.W */ sz == 8)) {
17713663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_EXTRACTPS( vbi, pfx, delta, False/*!isAvx*/ );
17714663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
17715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
17716663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
17717663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17718663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x20:
17719663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 3A 20 /r ib = PINSRB xmm1, r32/m8, imm8
17720663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Extract byte from r32/m8 and insert into xmm1 */
17721663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
17722663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int    imm8;
17723663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp new8 = newTemp(Ity_I8);
17724663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
17725663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt rG = gregOfRexRM(pfx, modrm);
17726663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if ( epartIsReg( modrm ) ) {
17727663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
17728663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = (Int)(getUChar(delta+1) & 0xF);
17729663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( new8, unop(Iop_32to8, getIReg32(rE)) );
17730663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1+1;
17731663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "pinsrb $%d,%s,%s\n", imm8,
17732663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 nameIReg32(rE), nameXMMReg(rG) );
17733663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
17734663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 1 );
17735663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = (Int)(getUChar(delta+alen) & 0xF);
17736663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( new8, loadLE( Ity_I8, mkexpr(addr) ) );
17737663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen+1;
17738663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "pinsrb $%d,%s,%s\n",
17739663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 imm8, dis_buf, nameXMMReg(rG) );
17740663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
17741663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp src_vec = newTemp(Ity_V128);
17742663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(src_vec, getXMMReg( gregOfRexRM(pfx, modrm) ));
17743663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp res = math_PINSRB_128( src_vec, new8, imm8 );
17744663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMReg( rG, mkexpr(res) );
17745663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
17746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
17747663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
17748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17749663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x21:
17750663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 3A 21 /r ib = INSERTPS imm8, xmm2/m32, xmm1
17751663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Insert Packed Single Precision Floating-Point Value (XMM) */
17752663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
17753663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   imm8;
17754663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp d2ins = newTemp(Ity_I32); /* comes from the E part */
17755663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         const IRTemp inval = IRTemp_INVALID;
17756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17757663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
17758663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt rG = gregOfRexRM(pfx, modrm);
17759663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17760663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if ( epartIsReg( modrm ) ) {
17761663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt   rE = eregOfRexRM(pfx, modrm);
17762663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            IRTemp vE = newTemp(Ity_V128);
17763663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( vE, getXMMReg(rE) );
17764663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            IRTemp dsE[4] = { inval, inval, inval, inval };
17765663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            breakupV128to32s( vE, &dsE[3], &dsE[2], &dsE[1], &dsE[0] );
17766663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = getUChar(delta+1);
17767663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            d2ins = dsE[(imm8 >> 6) & 3]; /* "imm8_count_s" */
17768663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1+1;
17769663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "insertps $%u, %s,%s\n",
17770663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 imm8, nameXMMReg(rE), nameXMMReg(rG) );
17771663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
17772663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 1 );
17773663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( d2ins, loadLE( Ity_I32, mkexpr(addr) ) );
17774663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = getUChar(delta+alen);
17775663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen+1;
17776663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "insertps $%u, %s,%s\n",
17777663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 imm8, dis_buf, nameXMMReg(rG) );
17778663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
17779663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17780663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp vG = newTemp(Ity_V128);
17781663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( vG, getXMMReg(rG) );
17782663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17783663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMReg( rG, mkexpr(math_INSERTPS( vG, d2ins, imm8 )) );
17784663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
17785663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
17786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
17787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17788663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x22:
17789663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 no-REX.W 0F 3A 22 /r ib = PINSRD xmm1, r/m32, imm8
17790663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Extract Doubleword int from gen.reg/mem32 and insert into xmm1 */
17791663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
17792663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && sz == 2 /* REX.W is NOT present */) {
17793663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int    imm8_10;
17794663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp src_u32 = newTemp(Ity_I32);
17795663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
17796663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt rG = gregOfRexRM(pfx, modrm);
17797663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17798663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if ( epartIsReg( modrm ) ) {
17799663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
17800663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8_10 = (Int)(getUChar(delta+1) & 3);
17801663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( src_u32, getIReg32( rE ) );
17802663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1+1;
17803663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "pinsrd $%d, %s,%s\n",
17804663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 imm8_10, nameIReg32(rE), nameXMMReg(rG) );
17805663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
17806663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 1 );
17807663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8_10 = (Int)(getUChar(delta+alen) & 3);
17808663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( src_u32, loadLE( Ity_I32, mkexpr(addr) ) );
17809663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen+1;
17810663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "pinsrd $%d, %s,%s\n",
17811663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 imm8_10, dis_buf, nameXMMReg(rG) );
17812663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
17813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17814663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp src_vec = newTemp(Ity_V128);
17815663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(src_vec, getXMMReg( rG ));
17816663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp res_vec = math_PINSRD_128( src_vec, src_u32, imm8_10 );
17817663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMReg( rG, mkexpr(res_vec) );
17818663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
17819663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
17820663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 REX.W 0F 3A 22 /r ib = PINSRQ xmm1, r/m64, imm8
17821663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Extract Quadword int from gen.reg/mem64 and insert into xmm1 */
17822663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
17823663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && sz == 8 /* REX.W is present */) {
17824663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int imm8_0;
17825663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp src_u64 = newTemp(Ity_I64);
17826663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
17827663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt rG = gregOfRexRM(pfx, modrm);
17828663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17829663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if ( epartIsReg( modrm ) ) {
17830663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
17831663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8_0 = (Int)(getUChar(delta+1) & 1);
17832663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( src_u64, getIReg64( rE ) );
17833663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1+1;
17834663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "pinsrq $%d, %s,%s\n",
17835663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 imm8_0, nameIReg64(rE), nameXMMReg(rG) );
17836663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
17837663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 1 );
17838663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8_0 = (Int)(getUChar(delta+alen) & 1);
17839663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( src_u64, loadLE( Ity_I64, mkexpr(addr) ) );
17840663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen+1;
17841663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "pinsrq $%d, %s,%s\n",
17842663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 imm8_0, dis_buf, nameXMMReg(rG) );
17843663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
17844663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17845663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp src_vec = newTemp(Ity_V128);
17846663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(src_vec, getXMMReg( rG ));
17847663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp res_vec = math_PINSRQ_128( src_vec, src_u64, imm8_0 );
17848663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMReg( rG, mkexpr(res_vec) );
17849663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
17850663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
17851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
17852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17853663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x40:
17854663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 3A 40 /r ib = DPPS xmm1, xmm2/m128, imm8
17855663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Dot Product of Packed Single Precision Floating-Point Values (XMM) */
17856663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
17857663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
17858663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int    imm8;
17859663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp src_vec = newTemp(Ity_V128);
17860663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dst_vec = newTemp(Ity_V128);
17861663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG      = gregOfRexRM(pfx, modrm);
17862663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( dst_vec, getXMMReg( rG ) );
17863663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if ( epartIsReg( modrm ) ) {
17864663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx, modrm);
17865663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = (Int)getUChar(delta+1);
17866663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( src_vec, getXMMReg(rE) );
17867663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1+1;
17868663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "dpps $%d, %s,%s\n",
17869663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 imm8, nameXMMReg(rE), nameXMMReg(rG) );
17870663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
17871663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf,
17872663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             1/* imm8 is 1 byte after the amode */ );
17873663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gen_SEGV_if_not_16_aligned( addr );
17874663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( src_vec, loadLE( Ity_V128, mkexpr(addr) ) );
17875663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = (Int)getUChar(delta+alen);
17876663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen+1;
17877663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "dpps $%d, %s,%s\n",
17878663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 imm8, dis_buf, nameXMMReg(rG) );
17879663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
17880663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp res = math_DPPS_128( src_vec, dst_vec, imm8 );
17881663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMReg( rG, mkexpr(res) );
17882663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
17883663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
17884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
17885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17886663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x41:
17887663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 3A 41 /r ib = DPPD xmm1, xmm2/m128, imm8
17888663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Dot Product of Packed Double Precision Floating-Point Values (XMM) */
17889663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
17890663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
17891663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int    imm8;
17892663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp src_vec = newTemp(Ity_V128);
17893663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dst_vec = newTemp(Ity_V128);
17894663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG      = gregOfRexRM(pfx, modrm);
17895663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( dst_vec, getXMMReg( rG ) );
17896663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if ( epartIsReg( modrm ) ) {
17897663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx, modrm);
17898663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = (Int)getUChar(delta+1);
17899663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( src_vec, getXMMReg(rE) );
17900663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1+1;
17901663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "dppd $%d, %s,%s\n",
17902663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 imm8, nameXMMReg(rE), nameXMMReg(rG) );
17903663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
17904663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf,
17905663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             1/* imm8 is 1 byte after the amode */ );
17906663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gen_SEGV_if_not_16_aligned( addr );
17907663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( src_vec, loadLE( Ity_V128, mkexpr(addr) ) );
17908663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = (Int)getUChar(delta+alen);
17909663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen+1;
17910663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "dppd $%d, %s,%s\n",
17911663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 imm8, dis_buf, nameXMMReg(rG) );
17912663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
17913663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp res = math_DPPD_128( src_vec, dst_vec, imm8 );
17914663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMReg( rG, mkexpr(res) );
17915663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
17916663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
17917663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
17918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17919663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x42:
17920663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 3A 42 /r ib = MPSADBW xmm1, xmm2/m128, imm8
17921663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Multiple Packed Sums of Absolule Difference (XMM) */
17922663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
17923663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int    imm8;
17924663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp src_vec = newTemp(Ity_V128);
17925663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dst_vec = newTemp(Ity_V128);
17926663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm          = getUChar(delta);
17927663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG      = gregOfRexRM(pfx, modrm);
17928663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17929663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( dst_vec, getXMMReg(rG) );
17930663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17931663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if ( epartIsReg( modrm ) ) {
17932663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx, modrm);
17933663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17934663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = (Int)getUChar(delta+1);
17935663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( src_vec, getXMMReg(rE) );
17936663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1+1;
17937663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "mpsadbw $%d, %s,%s\n", imm8,
17938663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 nameXMMReg(rE), nameXMMReg(rG) );
17939663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
17940663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf,
17941663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             1/* imm8 is 1 byte after the amode */ );
17942663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gen_SEGV_if_not_16_aligned( addr );
17943663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( src_vec, loadLE( Ity_V128, mkexpr(addr) ) );
17944663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = (Int)getUChar(delta+alen);
17945663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen+1;
17946663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "mpsadbw $%d, %s,%s\n", imm8, dis_buf, nameXMMReg(rG) );
17947663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
17948663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17949663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMReg( rG, mkexpr( math_MPSADBW_128(dst_vec, src_vec, imm8) ) );
17950663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
17951663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
17952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
17953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17954663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x44:
17955663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 3A 44 /r ib = PCLMULQDQ xmm1, xmm2/m128, imm8
17956663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       * Carry-less multiplication of selected XMM quadwords into XMM
17957663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       * registers (a.k.a multiplication of polynomials over GF(2))
17958663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       */
17959663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
17960663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17961663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int imm8;
17962663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp svec = newTemp(Ity_V128);
17963663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dvec = newTemp(Ity_V128);
17964663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm       = getUChar(delta);
17965663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG   = gregOfRexRM(pfx, modrm);
17966663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17967663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( dvec, getXMMReg(rG) );
17968663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17969663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if ( epartIsReg( modrm ) ) {
17970663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx, modrm);
17971663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = (Int)getUChar(delta+1);
17972663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( svec, getXMMReg(rE) );
17973663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1+1;
17974663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "pclmulqdq $%d, %s,%s\n", imm8,
17975663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 nameXMMReg(rE), nameXMMReg(rG) );
17976663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
17977663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf,
17978663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             1/* imm8 is 1 byte after the amode */ );
17979663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gen_SEGV_if_not_16_aligned( addr );
17980663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( svec, loadLE( Ity_V128, mkexpr(addr) ) );
17981663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = (Int)getUChar(delta+alen);
17982663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen+1;
17983663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "pclmulqdq $%d, %s,%s\n",
17984663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 imm8, dis_buf, nameXMMReg(rG) );
17985663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
17986663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17987663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMReg( rG, mkexpr( math_PCLMULQDQ(dvec, svec, imm8) ) );
17988663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
17989663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
17990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
17991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17992663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x60:
17993663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x61:
17994663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x62:
17995663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x63:
17996663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 3A 63 /r ib = PCMPISTRI imm8, xmm2/m128, xmm1
17997663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         66 0F 3A 62 /r ib = PCMPISTRM imm8, xmm2/m128, xmm1
17998663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         66 0F 3A 61 /r ib = PCMPESTRI imm8, xmm2/m128, xmm1
17999663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         66 0F 3A 60 /r ib = PCMPESTRM imm8, xmm2/m128, xmm1
18000663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         (selected special cases that actually occur in glibc,
18001663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          not by any means a complete implementation.)
18002663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      */
18003663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
18004663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Long delta0 = delta;
18005663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_PCMPxSTRx( vbi, pfx, delta, False/*!isAvx*/, opc );
18006663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (delta > delta0) goto decode_success;
18007663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* else fall though; dis_PCMPxSTRx failed to decode it */
18008663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
18009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
18010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18011663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xDF:
18012663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 3A DF /r ib = AESKEYGENASSIST imm8, xmm2/m128, xmm1 */
18013663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && sz == 2) {
18014663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AESKEYGENASSIST( vbi, pfx, delta, False/*!isAvx*/ );
18015663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
18016663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
18017663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
18018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18019663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   default:
18020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
18021663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
18023663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18024663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  decode_failure:
18025663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *decode_OK = False;
18026663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return deltaIN;
18027663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18028663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  decode_success:
18029663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *decode_OK = True;
18030663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
18031663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
18032663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18033663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18034663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*------------------------------------------------------------*/
18035663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---                                                      ---*/
18036663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*--- Top-level post-escape decoders: dis_ESC_NONE         ---*/
18037663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---                                                      ---*/
18038663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*------------------------------------------------------------*/
18039663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18040663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng__attribute__((noinline))
18041663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic
18042663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengLong dis_ESC_NONE (
18043663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        /*MB_OUT*/DisResult* dres,
18044663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        /*MB_OUT*/Bool*      expect_CAS,
18045663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        Bool         (*resteerOkFn) ( /*opaque*/void*, Addr64 ),
18046663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        Bool         resteerCisOk,
18047663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        void*        callback_opaque,
18048663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        VexArchInfo* archinfo,
18049663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        VexAbiInfo*  vbi,
18050663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        Prefix pfx, Int sz, Long deltaIN
18051663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     )
18052663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
18053663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Long   d64   = 0;
18054663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  abyte = 0;
18055663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr  = IRTemp_INVALID;
18056663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t1    = IRTemp_INVALID;
18057663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t2    = IRTemp_INVALID;
18058663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t3    = IRTemp_INVALID;
18059663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t4    = IRTemp_INVALID;
18060663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t5    = IRTemp_INVALID;
18061663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRType ty    = Ity_INVALID;
18062663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm = 0;
18063663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    am_sz = 0;
18064663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    d_sz  = 0;
18065663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen  = 0;
18066663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
18067663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18068663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Long   delta = deltaIN;
18069663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  opc   = getUChar(delta);
18070663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   delta++;
18071663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (opc) {
18072663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18073663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x00: /* ADD Gb,Eb */
18074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (haveF2orF3(pfx)) goto decode_failure;
18075663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op2_G_E ( vbi, pfx, False, Iop_Add8, True, 1, delta, "add" );
18076663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18077663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x01: /* ADD Gv,Ev */
18078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (haveF2orF3(pfx)) goto decode_failure;
18079663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op2_G_E ( vbi, pfx, False, Iop_Add8, True, sz, delta, "add" );
18080663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18081663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18082663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x02: /* ADD Eb,Gb */
18083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (haveF2orF3(pfx)) goto decode_failure;
18084663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op2_E_G ( vbi, pfx, False, Iop_Add8, True, 1, delta, "add" );
18085663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18086663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x03: /* ADD Ev,Gv */
18087663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18088663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op2_E_G ( vbi, pfx, False, Iop_Add8, True, sz, delta, "add" );
18089663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18090663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18091663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x04: /* ADD Ib, AL */
18092663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18093663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op_imm_A( 1, False, Iop_Add8, True, delta, "add" );
18094663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18095663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x05: /* ADD Iv, eAX */
18096663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18097663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op_imm_A(sz, False, Iop_Add8, True, delta, "add" );
18098663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18099663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18100663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x08: /* OR Gb,Eb */
18101663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18102663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op2_G_E ( vbi, pfx, False, Iop_Or8, True, 1, delta, "or" );
18103663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18104663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x09: /* OR Gv,Ev */
18105663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18106663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op2_G_E ( vbi, pfx, False, Iop_Or8, True, sz, delta, "or" );
18107663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18108663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18109663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x0A: /* OR Eb,Gb */
18110663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18111663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op2_E_G ( vbi, pfx, False, Iop_Or8, True, 1, delta, "or" );
18112663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18113663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x0B: /* OR Ev,Gv */
18114663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18115663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op2_E_G ( vbi, pfx, False, Iop_Or8, True, sz, delta, "or" );
18116663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18117663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18118663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x0C: /* OR Ib, AL */
18119663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18120663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op_imm_A( 1, False, Iop_Or8, True, delta, "or" );
18121663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18122663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x0D: /* OR Iv, eAX */
18123663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18124663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op_imm_A( sz, False, Iop_Or8, True, delta, "or" );
18125663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18126663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18127663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x10: /* ADC Gb,Eb */
18128663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18129663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op2_G_E ( vbi, pfx, True, Iop_Add8, True, 1, delta, "adc" );
18130663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18131663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x11: /* ADC Gv,Ev */
18132663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18133663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op2_G_E ( vbi, pfx, True, Iop_Add8, True, sz, delta, "adc" );
18134663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18135663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18136663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x12: /* ADC Eb,Gb */
18137663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18138663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op2_E_G ( vbi, pfx, True, Iop_Add8, True, 1, delta, "adc" );
18139663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18140663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x13: /* ADC Ev,Gv */
18141663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18142663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op2_E_G ( vbi, pfx, True, Iop_Add8, True, sz, delta, "adc" );
18143663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18144663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18145663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x14: /* ADC Ib, AL */
18146663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18147663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op_imm_A( 1, True, Iop_Add8, True, delta, "adc" );
18148663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18149663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x15: /* ADC Iv, eAX */
18150663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18151663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op_imm_A( sz, True, Iop_Add8, True, delta, "adc" );
18152663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18153663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18154663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x18: /* SBB Gb,Eb */
18155663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18156663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op2_G_E ( vbi, pfx, True, Iop_Sub8, True, 1, delta, "sbb" );
18157663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18158663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x19: /* SBB Gv,Ev */
18159663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18160663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op2_G_E ( vbi, pfx, True, Iop_Sub8, True, sz, delta, "sbb" );
18161663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18162663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18163663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x1A: /* SBB Eb,Gb */
18164663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18165663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op2_E_G ( vbi, pfx, True, Iop_Sub8, True, 1, delta, "sbb" );
18166663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18167663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x1B: /* SBB Ev,Gv */
18168663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18169663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op2_E_G ( vbi, pfx, True, Iop_Sub8, True, sz, delta, "sbb" );
18170663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18171663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18172663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x1C: /* SBB Ib, AL */
18173663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18174663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op_imm_A( 1, True, Iop_Sub8, True, delta, "sbb" );
18175663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18176663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x1D: /* SBB Iv, eAX */
18177663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18178663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op_imm_A( sz, True, Iop_Sub8, True, delta, "sbb" );
18179663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18180663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18181663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x20: /* AND Gb,Eb */
18182663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18183663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op2_G_E ( vbi, pfx, False, Iop_And8, True, 1, delta, "and" );
18184663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18185663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x21: /* AND Gv,Ev */
18186663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18187663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op2_G_E ( vbi, pfx, False, Iop_And8, True, sz, delta, "and" );
18188663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18189663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18190663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x22: /* AND Eb,Gb */
18191663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18192663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op2_E_G ( vbi, pfx, False, Iop_And8, True, 1, delta, "and" );
18193663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18194663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x23: /* AND Ev,Gv */
18195663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18196663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op2_E_G ( vbi, pfx, False, Iop_And8, True, sz, delta, "and" );
18197663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18198663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18199663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x24: /* AND Ib, AL */
18200663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18201663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op_imm_A( 1, False, Iop_And8, True, delta, "and" );
18202663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18203663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x25: /* AND Iv, eAX */
18204663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18205663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op_imm_A( sz, False, Iop_And8, True, delta, "and" );
18206663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18207663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18208663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x28: /* SUB Gb,Eb */
18209663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18210663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op2_G_E ( vbi, pfx, False, Iop_Sub8, True, 1, delta, "sub" );
18211663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18212663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x29: /* SUB Gv,Ev */
18213663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18214663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op2_G_E ( vbi, pfx, False, Iop_Sub8, True, sz, delta, "sub" );
18215663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18216663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18217663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x2A: /* SUB Eb,Gb */
18218663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18219663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op2_E_G ( vbi, pfx, False, Iop_Sub8, True, 1, delta, "sub" );
18220663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18221663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x2B: /* SUB Ev,Gv */
18222663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18223663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op2_E_G ( vbi, pfx, False, Iop_Sub8, True, sz, delta, "sub" );
18224663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18225663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18226663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x2C: /* SUB Ib, AL */
18227663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18228663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op_imm_A(1, False, Iop_Sub8, True, delta, "sub" );
18229663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18230663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18231663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x2D: /* SUB Iv, eAX */
18232663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18233663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op_imm_A( sz, False, Iop_Sub8, True, delta, "sub" );
18234663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18235663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18236663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x30: /* XOR Gb,Eb */
18237663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18238663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op2_G_E ( vbi, pfx, False, Iop_Xor8, True, 1, delta, "xor" );
18239663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18240663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x31: /* XOR Gv,Ev */
18241663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18242663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op2_G_E ( vbi, pfx, False, Iop_Xor8, True, sz, delta, "xor" );
18243663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18244663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18245663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x32: /* XOR Eb,Gb */
18246663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18247663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op2_E_G ( vbi, pfx, False, Iop_Xor8, True, 1, delta, "xor" );
18248663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18249663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x33: /* XOR Ev,Gv */
18250663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18251663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op2_E_G ( vbi, pfx, False, Iop_Xor8, True, sz, delta, "xor" );
18252663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18253663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18254663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x34: /* XOR Ib, AL */
18255663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18256663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op_imm_A( 1, False, Iop_Xor8, True, delta, "xor" );
18257663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18258663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x35: /* XOR Iv, eAX */
18259663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18260663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op_imm_A( sz, False, Iop_Xor8, True, delta, "xor" );
18261663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18262663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18263663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x38: /* CMP Gb,Eb */
18264663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18265663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op2_G_E ( vbi, pfx, False, Iop_Sub8, False, 1, delta, "cmp" );
18266663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18267663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x39: /* CMP Gv,Ev */
18268663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18269663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op2_G_E ( vbi, pfx, False, Iop_Sub8, False, sz, delta, "cmp" );
18270663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18271663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18272663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x3A: /* CMP Eb,Gb */
18273663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18274663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op2_E_G ( vbi, pfx, False, Iop_Sub8, False, 1, delta, "cmp" );
18275663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18276663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x3B: /* CMP Ev,Gv */
18277663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18278663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op2_E_G ( vbi, pfx, False, Iop_Sub8, False, sz, delta, "cmp" );
18279663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18280663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18281663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x3C: /* CMP Ib, AL */
18282663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18283663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op_imm_A( 1, False, Iop_Sub8, False, delta, "cmp" );
18284663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18285663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x3D: /* CMP Iv, eAX */
18286663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18287663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op_imm_A( sz, False, Iop_Sub8, False, delta, "cmp" );
18288663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18289663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18290663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x50: /* PUSH eAX */
18291663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x51: /* PUSH eCX */
18292663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x52: /* PUSH eDX */
18293663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x53: /* PUSH eBX */
18294663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x55: /* PUSH eBP */
18295663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x56: /* PUSH eSI */
18296663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x57: /* PUSH eDI */
18297663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x54: /* PUSH eSP */
18298663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* This is the Right Way, in that the value to be pushed is
18299663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         established before %rsp is changed, so that pushq %rsp
18300663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         correctly pushes the old value. */
18301663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18302663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(sz == 2 || sz == 4 || sz == 8);
18303663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (sz == 4)
18304663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         sz = 8; /* there is no encoding for 32-bit push in 64-bit mode */
18305663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ty = sz==2 ? Ity_I16 : Ity_I64;
18306663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      t1 = newTemp(ty);
18307663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      t2 = newTemp(Ity_I64);
18308663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(t1, getIRegRexB(sz, pfx, opc-0x50));
18309663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(t2, binop(Iop_Sub64, getIReg64(R_RSP), mkU64(sz)));
18310663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      putIReg64(R_RSP, mkexpr(t2) );
18311663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      storeLE(mkexpr(t2),mkexpr(t1));
18312663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("push%c %s\n", nameISize(sz), nameIRegRexB(sz,pfx,opc-0x50));
18313663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18314663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18315663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x58: /* POP eAX */
18316663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x59: /* POP eCX */
18317663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x5A: /* POP eDX */
18318663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x5B: /* POP eBX */
18319663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x5D: /* POP eBP */
18320663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x5E: /* POP eSI */
18321663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x5F: /* POP eDI */
18322663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x5C: /* POP eSP */
18323663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18324663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(sz == 2 || sz == 4 || sz == 8);
18325663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (sz == 4)
18326663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         sz = 8; /* there is no encoding for 32-bit pop in 64-bit mode */
18327663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      t1 = newTemp(szToITy(sz));
18328663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      t2 = newTemp(Ity_I64);
18329663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(t2, getIReg64(R_RSP));
18330663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(t1, loadLE(szToITy(sz),mkexpr(t2)));
18331663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      putIReg64(R_RSP, binop(Iop_Add64, mkexpr(t2), mkU64(sz)));
18332663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      putIRegRexB(sz, pfx, opc-0x58, mkexpr(t1));
18333663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("pop%c %s\n", nameISize(sz), nameIRegRexB(sz,pfx,opc-0x58));
18334663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18335663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18336663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x63: /* MOVSX */
18337663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18338663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveREX(pfx) && 1==getRexW(pfx)) {
18339663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(sz == 8);
18340663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* movsx r/m32 to r64 */
18341663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
18342663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
18343663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta++;
18344663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putIRegG(8, pfx, modrm,
18345663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             unop(Iop_32Sto64,
18346663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  getIRegE(4, pfx, modrm)));
18347663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movslq %s,%s\n",
18348663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                nameIRegE(4, pfx, modrm),
18349663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                nameIRegG(8, pfx, modrm));
18350663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return delta;
18351663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
18352663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
18353663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
18354663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putIRegG(8, pfx, modrm,
18355663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             unop(Iop_32Sto64,
18356663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  loadLE(Ity_I32, mkexpr(addr))));
18357663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movslq %s,%s\n", dis_buf,
18358663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                nameIRegG(8, pfx, modrm));
18359663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return delta;
18360663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
18361663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      } else {
18362663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_failure;
18363663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
18364663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18365663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x68: /* PUSH Iv */
18366663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18367663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Note, sz==4 is not possible in 64-bit mode.  Hence ... */
18368663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (sz == 4) sz = 8;
18369663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d64 = getSDisp(imin(4,sz),delta);
18370663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += imin(4,sz);
18371663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      goto do_push_I;
18372663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18373663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x69: /* IMUL Iv, Ev, Gv */
18374663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18375663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_imul_I_E_G ( vbi, pfx, sz, delta, sz );
18376663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18377663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18378663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x6A: /* PUSH Ib, sign-extended to sz */
18379663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18380663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Note, sz==4 is not possible in 64-bit mode.  Hence ... */
18381663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (sz == 4) sz = 8;
18382663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d64 = getSDisp8(delta); delta += 1;
18383663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      goto do_push_I;
18384663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   do_push_I:
18385663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ty = szToITy(sz);
18386663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      t1 = newTemp(Ity_I64);
18387663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      t2 = newTemp(ty);
18388663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( t1, binop(Iop_Sub64,getIReg64(R_RSP),mkU64(sz)) );
18389663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      putIReg64(R_RSP, mkexpr(t1) );
18390663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* stop mkU16 asserting if d32 is a negative 16-bit number
18391663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         (bug #132813) */
18392663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (ty == Ity_I16)
18393663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d64 &= 0xFFFF;
18394663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      storeLE( mkexpr(t1), mkU(ty,d64) );
18395663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("push%c $%lld\n", nameISize(sz), (Long)d64);
18396663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18397663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18398663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x6B: /* IMUL Ib, Ev, Gv */
18399663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_imul_I_E_G ( vbi, pfx, sz, delta, 1 );
18400663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18401663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18402663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x70:
18403663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x71:
18404663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x72:   /* JBb/JNAEb (jump below) */
18405663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x73:   /* JNBb/JAEb (jump not below) */
18406663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x74:   /* JZb/JEb (jump zero) */
18407663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x75:   /* JNZb/JNEb (jump not zero) */
18408663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x76:   /* JBEb/JNAb (jump below or equal) */
18409663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x77:   /* JNBEb/JAb (jump not below or equal) */
18410663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x78:   /* JSb (jump negative) */
18411663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x79:   /* JSb (jump not negative) */
18412663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x7A:   /* JP (jump parity even) */
18413663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x7B:   /* JNP/JPO (jump parity odd) */
18414663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x7C:   /* JLb/JNGEb (jump less) */
18415663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x7D:   /* JGEb/JNLb (jump greater or equal) */
18416663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x7E:   /* JLEb/JNGb (jump less or equal) */
18417663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x7F: { /* JGb/JNLEb (jump greater) */
18418663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Long   jmpDelta;
18419663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HChar* comment  = "";
18420663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18421663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      jmpDelta = getSDisp8(delta);
18422663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(-128 <= jmpDelta && jmpDelta < 128);
18423663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d64 = (guest_RIP_bbstart+delta+1) + jmpDelta;
18424663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta++;
18425663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (resteerCisOk
18426663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && vex_control.guest_chase_cond
18427663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (Addr64)d64 != (Addr64)guest_RIP_bbstart
18428663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && jmpDelta < 0
18429663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && resteerOkFn( callback_opaque, d64) ) {
18430663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Speculation: assume this backward branch is taken.  So we
18431663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            need to emit a side-exit to the insn following this one,
18432663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            on the negation of the condition, and continue at the
18433663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            branch target address (d64).  If we wind up back at the
18434663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            first instruction of the trace, just stop; it's better to
18435663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            let the IR loop unroller handle that case. */
18436663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         stmt( IRStmt_Exit(
18437663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  mk_amd64g_calculate_condition(
18438663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     (AMD64Condcode)(1 ^ (opc - 0x70))),
18439663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  Ijk_Boring,
18440663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  IRConst_U64(guest_RIP_bbstart+delta),
18441663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  OFFB_RIP ) );
18442663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dres->whatNext   = Dis_ResteerC;
18443663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dres->continueAt = d64;
18444663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         comment = "(assumed taken)";
18445663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
18446663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      else
18447663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (resteerCisOk
18448663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && vex_control.guest_chase_cond
18449663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (Addr64)d64 != (Addr64)guest_RIP_bbstart
18450663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && jmpDelta >= 0
18451663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && resteerOkFn( callback_opaque, guest_RIP_bbstart+delta ) ) {
18452663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Speculation: assume this forward branch is not taken.  So
18453663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            we need to emit a side-exit to d64 (the dest) and continue
18454663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            disassembling at the insn immediately following this
18455663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            one. */
18456663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         stmt( IRStmt_Exit(
18457663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  mk_amd64g_calculate_condition((AMD64Condcode)(opc - 0x70)),
18458663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  Ijk_Boring,
18459663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  IRConst_U64(d64),
18460663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  OFFB_RIP ) );
18461663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dres->whatNext   = Dis_ResteerC;
18462663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dres->continueAt = guest_RIP_bbstart+delta;
18463663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         comment = "(assumed not taken)";
18464663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
18465663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      else {
18466663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Conservative default translation - end the block at this
18467663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            point. */
18468663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         jcc_01( dres, (AMD64Condcode)(opc - 0x70),
18469663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 guest_RIP_bbstart+delta, d64 );
18470663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(dres->whatNext == Dis_StopHere);
18471663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
18472663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("j%s-8 0x%llx %s\n", name_AMD64Condcode(opc - 0x70), d64, comment);
18473663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18474663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
18475663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18476663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x80: /* Grp1 Ib,Eb */
18477663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18478663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      modrm = getUChar(delta);
18479663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      am_sz = lengthAMode(pfx,delta);
18480663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      sz    = 1;
18481663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d_sz  = 1;
18482663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d64   = getSDisp8(delta + am_sz);
18483663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_Grp1 ( vbi, pfx, delta, modrm, am_sz, d_sz, sz, d64 );
18484663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18485663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18486663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x81: /* Grp1 Iv,Ev */
18487663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18488663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      modrm = getUChar(delta);
18489663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      am_sz = lengthAMode(pfx,delta);
18490663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d_sz  = imin(sz,4);
18491663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d64   = getSDisp(d_sz, delta + am_sz);
18492663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_Grp1 ( vbi, pfx, delta, modrm, am_sz, d_sz, sz, d64 );
18493663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18494663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18495663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x83: /* Grp1 Ib,Ev */
18496663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18497663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      modrm = getUChar(delta);
18498663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      am_sz = lengthAMode(pfx,delta);
18499663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d_sz  = 1;
18500663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d64   = getSDisp8(delta + am_sz);
18501663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_Grp1 ( vbi, pfx, delta, modrm, am_sz, d_sz, sz, d64 );
18502663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18503663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18504663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x84: /* TEST Eb,Gb */
18505663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18506663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op2_E_G ( vbi, pfx, False, Iop_And8, False, 1, delta, "test" );
18507663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18508663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18509663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x85: /* TEST Ev,Gv */
18510663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18511663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op2_E_G ( vbi, pfx, False, Iop_And8, False, sz, delta, "test" );
18512663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18513663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18514663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* XCHG reg,mem automatically asserts LOCK# even without a LOCK
18515663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      prefix.  Therefore, surround it with a IRStmt_MBE(Imbe_BusLock)
18516663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      and IRStmt_MBE(Imbe_BusUnlock) pair.  But be careful; if it is
18517663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      used with an explicit LOCK prefix, we don't want to end up with
18518663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      two IRStmt_MBE(Imbe_BusLock)s -- one made here and one made by
18519663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      the generic LOCK logic at the top of disInstr. */
18520663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x86: /* XCHG Gb,Eb */
18521663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      sz = 1;
18522663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Fall through ... */
18523663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x87: /* XCHG Gv,Ev */
18524663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18525663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      modrm = getUChar(delta);
18526663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ty = szToITy(sz);
18527663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      t1 = newTemp(ty); t2 = newTemp(ty);
18528663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (epartIsReg(modrm)) {
18529663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(t1, getIRegE(sz, pfx, modrm));
18530663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(t2, getIRegG(sz, pfx, modrm));
18531663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putIRegG(sz, pfx, modrm, mkexpr(t1));
18532663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putIRegE(sz, pfx, modrm, mkexpr(t2));
18533663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta++;
18534663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("xchg%c %s, %s\n",
18535663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             nameISize(sz), nameIRegG(sz, pfx, modrm),
18536663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            nameIRegE(sz, pfx, modrm));
18537663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      } else {
18538663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *expect_CAS = True;
18539663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
18540663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( t1, loadLE(ty, mkexpr(addr)) );
18541663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( t2, getIRegG(sz, pfx, modrm) );
18542663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         casLE( mkexpr(addr),
18543663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                mkexpr(t1), mkexpr(t2), guest_RIP_curr_instr );
18544663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putIRegG( sz, pfx, modrm, mkexpr(t1) );
18545663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta += alen;
18546663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("xchg%c %s, %s\n", nameISize(sz),
18547663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                nameIRegG(sz, pfx, modrm), dis_buf);
18548663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
18549663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18550663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18551663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x88: /* MOV Gb,Eb */
18552663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18553663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_mov_G_E(vbi, pfx, 1, delta);
18554663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18555663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18556663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x89: /* MOV Gv,Ev */
18557663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18558663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_mov_G_E(vbi, pfx, sz, delta);
18559663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18560663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18561663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x8A: /* MOV Eb,Gb */
18562663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18563663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_mov_E_G(vbi, pfx, 1, delta);
18564663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18565663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18566663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x8B: /* MOV Ev,Gv */
18567663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18568663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_mov_E_G(vbi, pfx, sz, delta);
18569663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18570663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18571663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x8D: /* LEA M,Gv */
18572663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18573663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (sz != 4 && sz != 8)
18574663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_failure;
18575663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      modrm = getUChar(delta);
18576663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (epartIsReg(modrm))
18577663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_failure;
18578663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* NOTE!  this is the one place where a segment override prefix
18579663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         has no effect on the address calculation.  Therefore we clear
18580663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         any segment override bits in pfx. */
18581663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode ( &alen, vbi, clearSegBits(pfx), delta, dis_buf, 0 );
18582663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen;
18583663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* This is a hack.  But it isn't clear that really doing the
18584663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         calculation at 32 bits is really worth it.  Hence for leal,
18585663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         do the full 64-bit calculation and then truncate it. */
18586663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      putIRegG( sz, pfx, modrm,
18587663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         sz == 4
18588663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            ? unop(Iop_64to32, mkexpr(addr))
18589663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            : mkexpr(addr)
18590663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              );
18591663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("lea%c %s, %s\n", nameISize(sz), dis_buf,
18592663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            nameIRegG(sz,pfx,modrm));
18593663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18594663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18595663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x8F: { /* POPQ m64 / POPW m16 */
18596663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Int   len;
18597663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UChar rm;
18598663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* There is no encoding for 32-bit pop in 64-bit mode.
18599663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         So sz==4 actually means sz==8. */
18600663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18601663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(sz == 2 || sz == 4
18602663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              || /* tolerate redundant REX.W, see #210481 */ sz == 8);
18603663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (sz == 4) sz = 8;
18604663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (sz != 8) goto decode_failure; // until we know a sz==2 test case exists
18605663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18606663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      rm = getUChar(delta);
18607663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18608663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* make sure this instruction is correct POP */
18609663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (epartIsReg(rm) || gregLO3ofRM(rm) != 0)
18610663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_failure;
18611663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* and has correct size */
18612663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(sz == 8);
18613663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18614663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      t1 = newTemp(Ity_I64);
18615663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      t3 = newTemp(Ity_I64);
18616663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( t1, getIReg64(R_RSP) );
18617663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( t3, loadLE(Ity_I64, mkexpr(t1)) );
18618663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18619663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Increase RSP; must be done before the STORE.  Intel manual
18620663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         says: If the RSP register is used as a base register for
18621663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addressing a destination operand in memory, the POP
18622663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         instruction computes the effective address of the operand
18623663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         after it increments the RSP register.  */
18624663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      putIReg64(R_RSP, binop(Iop_Add64, mkexpr(t1), mkU64(sz)) );
18625663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18626663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode ( &len, vbi, pfx, delta, dis_buf, 0 );
18627663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      storeLE( mkexpr(addr), mkexpr(t3) );
18628663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18629663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("popl %s\n", dis_buf);
18630663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18631663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += len;
18632663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18633663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
18634663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18635663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x90: /* XCHG eAX,eAX */
18636663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* detect and handle F3 90 (rep nop) specially */
18637663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (!have66(pfx) && !haveF2(pfx) && haveF3(pfx)) {
18638663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("rep nop (P4 pause)\n");
18639663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* "observe" the hint.  The Vex client needs to be careful not
18640663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            to cause very long delays as a result, though. */
18641663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         jmp_lit(dres, Ijk_Yield, guest_RIP_bbstart+delta);
18642663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(dres->whatNext == Dis_StopHere);
18643663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return delta;
18644663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
18645663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* detect and handle NOPs specially */
18646663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (/* F2/F3 probably change meaning completely */
18647663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          !haveF2orF3(pfx)
18648663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          /* If REX.B is 1, we're not exchanging rAX with itself */
18649663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && getRexB(pfx)==0 ) {
18650663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("nop\n");
18651663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return delta;
18652663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
18653663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* else fall through to normal case. */
18654663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x91: /* XCHG rAX,rCX */
18655663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x92: /* XCHG rAX,rDX */
18656663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x93: /* XCHG rAX,rBX */
18657663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x94: /* XCHG rAX,rSP */
18658663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x95: /* XCHG rAX,rBP */
18659663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x96: /* XCHG rAX,rSI */
18660663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x97: /* XCHG rAX,rDI */
18661663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* guard against mutancy */
18662663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18663663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      codegen_xchg_rAX_Reg ( pfx, sz, opc - 0x90 );
18664663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18665663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18666663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x98: /* CBW */
18667663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18668663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (sz == 8) {
18669663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putIRegRAX( 8, unop(Iop_32Sto64, getIRegRAX(4)) );
18670663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP(/*"cdqe\n"*/"cltq");
18671663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return delta;
18672663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
18673663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (sz == 4) {
18674663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putIRegRAX( 4, unop(Iop_16Sto32, getIRegRAX(2)) );
18675663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("cwtl\n");
18676663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return delta;
18677663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
18678663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (sz == 2) {
18679663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putIRegRAX( 2, unop(Iop_8Sto16, getIRegRAX(1)) );
18680663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("cbw\n");
18681663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return delta;
18682663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
18683663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      goto decode_failure;
18684663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18685663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x99: /* CWD/CDQ/CQO */
18686663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18687663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(sz == 2 || sz == 4 || sz == 8);
18688663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ty = szToITy(sz);
18689663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      putIRegRDX( sz,
18690663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  binop(mkSizedOp(ty,Iop_Sar8),
18691663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        getIRegRAX(sz),
18692663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        mkU8(sz == 2 ? 15 : (sz == 4 ? 31 : 63))) );
18693663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP(sz == 2 ? "cwd\n"
18694663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  : (sz == 4 ? /*"cdq\n"*/ "cltd\n"
18695663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             : "cqo\n"));
18696663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18697663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18698663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x9B: /* FWAIT (X87 insn) */
18699663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* ignore? */
18700663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("fwait\n");
18701663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18702663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18703663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x9C: /* PUSHF */ {
18704663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Note.  There is no encoding for a 32-bit pushf in 64-bit
18705663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         mode.  So sz==4 actually means sz==8. */
18706663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 24 July 06: has also been seen with a redundant REX prefix,
18707663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         so must also allow sz==8. */
18708663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18709663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(sz == 2 || sz == 4 || sz == 8);
18710663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (sz == 4) sz = 8;
18711663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (sz != 8) goto decode_failure; // until we know a sz==2 test case exists
18712663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18713663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      t1 = newTemp(Ity_I64);
18714663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( t1, binop(Iop_Sub64,getIReg64(R_RSP),mkU64(sz)) );
18715663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      putIReg64(R_RSP, mkexpr(t1) );
18716663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18717663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      t2 = newTemp(Ity_I64);
18718663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( t2, mk_amd64g_calculate_rflags_all() );
18719663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18720663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Patch in the D flag.  This can simply be a copy of bit 10 of
18721663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         baseBlock[OFFB_DFLAG]. */
18722663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      t3 = newTemp(Ity_I64);
18723663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( t3, binop(Iop_Or64,
18724663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        mkexpr(t2),
18725663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        binop(Iop_And64,
18726663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              IRExpr_Get(OFFB_DFLAG,Ity_I64),
18727663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              mkU64(1<<10)))
18728663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            );
18729663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18730663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* And patch in the ID flag. */
18731663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      t4 = newTemp(Ity_I64);
18732663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( t4, binop(Iop_Or64,
18733663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        mkexpr(t3),
18734663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        binop(Iop_And64,
18735663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              binop(Iop_Shl64, IRExpr_Get(OFFB_IDFLAG,Ity_I64),
18736663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                               mkU8(21)),
18737663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              mkU64(1<<21)))
18738663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            );
18739663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18740663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* And patch in the AC flag too. */
18741663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      t5 = newTemp(Ity_I64);
18742663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( t5, binop(Iop_Or64,
18743663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        mkexpr(t4),
18744663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        binop(Iop_And64,
18745663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              binop(Iop_Shl64, IRExpr_Get(OFFB_ACFLAG,Ity_I64),
18746663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                               mkU8(18)),
18747663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              mkU64(1<<18)))
18748663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            );
18749663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18750663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* if sz==2, the stored value needs to be narrowed. */
18751663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (sz == 2)
18752663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        storeLE( mkexpr(t1), unop(Iop_32to16,
18753663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             unop(Iop_64to32,mkexpr(t5))) );
18754663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      else
18755663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        storeLE( mkexpr(t1), mkexpr(t5) );
18756663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18757663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("pushf%c\n", nameISize(sz));
18758663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18759663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
18760663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18761663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x9D: /* POPF */
18762663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Note.  There is no encoding for a 32-bit popf in 64-bit mode.
18763663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         So sz==4 actually means sz==8. */
18764663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18765663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(sz == 2 || sz == 4);
18766663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (sz == 4) sz = 8;
18767663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (sz != 8) goto decode_failure; // until we know a sz==2 test case exists
18768663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      t1 = newTemp(Ity_I64); t2 = newTemp(Ity_I64);
18769663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(t2, getIReg64(R_RSP));
18770663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(t1, widenUto64(loadLE(szToITy(sz),mkexpr(t2))));
18771663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      putIReg64(R_RSP, binop(Iop_Add64, mkexpr(t2), mkU64(sz)));
18772663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* t1 is the flag word.  Mask out everything except OSZACP and
18773663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         set the flags thunk to AMD64G_CC_OP_COPY. */
18774663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      stmt( IRStmt_Put( OFFB_CC_OP,   mkU64(AMD64G_CC_OP_COPY) ));
18775663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      stmt( IRStmt_Put( OFFB_CC_DEP2, mkU64(0) ));
18776663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      stmt( IRStmt_Put( OFFB_CC_DEP1,
18777663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        binop(Iop_And64,
18778663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              mkexpr(t1),
18779663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              mkU64( AMD64G_CC_MASK_C | AMD64G_CC_MASK_P
18780663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                     | AMD64G_CC_MASK_A | AMD64G_CC_MASK_Z
18781663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                     | AMD64G_CC_MASK_S| AMD64G_CC_MASK_O )
18782663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             )
18783663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       )
18784663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          );
18785663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18786663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Also need to set the D flag, which is held in bit 10 of t1.
18787663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         If zero, put 1 in OFFB_DFLAG, else -1 in OFFB_DFLAG. */
18788663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      stmt( IRStmt_Put(
18789663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               OFFB_DFLAG,
18790663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               IRExpr_Mux0X(
18791663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  unop(Iop_32to8,
18792663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  unop(Iop_64to32,
18793663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       binop(Iop_And64,
18794663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             binop(Iop_Shr64, mkexpr(t1), mkU8(10)),
18795663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             mkU64(1)))),
18796663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  mkU64(1),
18797663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  mkU64(0xFFFFFFFFFFFFFFFFULL)))
18798663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          );
18799663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18800663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* And set the ID flag */
18801663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      stmt( IRStmt_Put(
18802663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               OFFB_IDFLAG,
18803663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               IRExpr_Mux0X(
18804663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  unop(Iop_32to8,
18805663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  unop(Iop_64to32,
18806663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       binop(Iop_And64,
18807663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             binop(Iop_Shr64, mkexpr(t1), mkU8(21)),
18808663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             mkU64(1)))),
18809663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  mkU64(0),
18810663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  mkU64(1)))
18811663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          );
18812663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18813663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* And set the AC flag too */
18814663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      stmt( IRStmt_Put(
18815663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               OFFB_ACFLAG,
18816663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               IRExpr_Mux0X(
18817663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  unop(Iop_32to8,
18818663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  unop(Iop_64to32,
18819663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       binop(Iop_And64,
18820663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             binop(Iop_Shr64, mkexpr(t1), mkU8(18)),
18821663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             mkU64(1)))),
18822663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  mkU64(0),
18823663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  mkU64(1)))
18824663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          );
18825663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18826663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("popf%c\n", nameISize(sz));
18827663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18828663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18829663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x9E: /* SAHF */
18830663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      codegen_SAHF();
18831663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("sahf\n");
18832663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18833663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18834663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x9F: /* LAHF */
18835663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      codegen_LAHF();
18836663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("lahf\n");
18837663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18838663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18839663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xA0: /* MOV Ob,AL */
18840663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66orF2orF3(pfx)) goto decode_failure;
18841663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      sz = 1;
18842663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Fall through ... */
18843663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xA1: /* MOV Ov,eAX */
18844663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (sz != 8 && sz != 4 && sz != 2 && sz != 1)
18845663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_failure;
18846663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d64 = getDisp64(delta);
18847663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 8;
18848663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ty = szToITy(sz);
18849663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = newTemp(Ity_I64);
18850663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( addr, handleAddrOverrides(vbi, pfx, mkU64(d64)) );
18851663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      putIRegRAX(sz, loadLE( ty, mkexpr(addr) ));
18852663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("mov%c %s0x%llx, %s\n", nameISize(sz),
18853663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  segRegTxt(pfx), d64,
18854663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  nameIRegRAX(sz));
18855663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18856663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18857663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xA2: /* MOV AL,Ob */
18858663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66orF2orF3(pfx)) goto decode_failure;
18859663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      sz = 1;
18860663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Fall through ... */
18861663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xA3: /* MOV eAX,Ov */
18862663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (sz != 8 && sz != 4 && sz != 2 && sz != 1)
18863663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_failure;
18864663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d64 = getDisp64(delta);
18865663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 8;
18866663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ty = szToITy(sz);
18867663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = newTemp(Ity_I64);
18868663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( addr, handleAddrOverrides(vbi, pfx, mkU64(d64)) );
18869663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      storeLE( mkexpr(addr), getIRegRAX(sz) );
18870663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("mov%c %s, %s0x%llx\n", nameISize(sz), nameIRegRAX(sz),
18871663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  segRegTxt(pfx), d64);
18872663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18873663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18874663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xA4:
18875663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xA5:
18876663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F3 A4: rep movsb */
18877663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3(pfx) && !haveF2(pfx)) {
18878663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (opc == 0xA4)
18879663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            sz = 1;
18880663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dis_REP_op ( dres, AMD64CondAlways, dis_MOVS, sz,
18881663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      guest_RIP_curr_instr,
18882663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      guest_RIP_bbstart+delta, "rep movs", pfx );
18883663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        dres->whatNext = Dis_StopHere;
18884663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        return delta;
18885663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
18886663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* A4: movsb */
18887663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (!haveF3(pfx) && !haveF2(pfx)) {
18888663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (opc == 0xA4)
18889663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            sz = 1;
18890663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dis_string_op( dis_MOVS, sz, "movs", pfx );
18891663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return delta;
18892663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
18893663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      goto decode_failure;
18894663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18895663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xA6:
18896663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xA7:
18897663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F3 A6/A7: repe cmps/rep cmps{w,l,q} */
18898663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3(pfx) && !haveF2(pfx)) {
18899663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (opc == 0xA6)
18900663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            sz = 1;
18901663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dis_REP_op ( dres, AMD64CondZ, dis_CMPS, sz,
18902663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      guest_RIP_curr_instr,
18903663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      guest_RIP_bbstart+delta, "repe cmps", pfx );
18904663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dres->whatNext = Dis_StopHere;
18905663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return delta;
18906663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
18907663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      goto decode_failure;
18908663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18909663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xAA:
18910663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xAB:
18911663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F3 AA/AB: rep stosb/rep stos{w,l,q} */
18912663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3(pfx) && !haveF2(pfx)) {
18913663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (opc == 0xAA)
18914663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            sz = 1;
18915663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dis_REP_op ( dres, AMD64CondAlways, dis_STOS, sz,
18916663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      guest_RIP_curr_instr,
18917663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      guest_RIP_bbstart+delta, "rep stos", pfx );
18918663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(dres->whatNext == Dis_StopHere);
18919663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return delta;
18920663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
18921663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* AA/AB: stosb/stos{w,l,q} */
18922663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (!haveF3(pfx) && !haveF2(pfx)) {
18923663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (opc == 0xAA)
18924663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            sz = 1;
18925663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dis_string_op( dis_STOS, sz, "stos", pfx );
18926663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return delta;
18927663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
18928663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      goto decode_failure;
18929663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18930663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xA8: /* TEST Ib, AL */
18931663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18932663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op_imm_A( 1, False, Iop_And8, False, delta, "test" );
18933663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18934663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xA9: /* TEST Iv, eAX */
18935663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18936663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_op_imm_A( sz, False, Iop_And8, False, delta, "test" );
18937663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18938663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18939663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xAC: /* LODS, no REP prefix */
18940663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xAD:
18941663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      dis_string_op( dis_LODS, ( opc == 0xAC ? 1 : sz ), "lods", pfx );
18942663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18943663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18944663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xAE:
18945663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xAF:
18946663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F2 AE/AF: repne scasb/repne scas{w,l,q} */
18947663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2(pfx) && !haveF3(pfx)) {
18948663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (opc == 0xAE)
18949663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            sz = 1;
18950663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dis_REP_op ( dres, AMD64CondNZ, dis_SCAS, sz,
18951663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      guest_RIP_curr_instr,
18952663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      guest_RIP_bbstart+delta, "repne scas", pfx );
18953663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(dres->whatNext == Dis_StopHere);
18954663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return delta;
18955663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
18956663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F3 AE/AF: repe scasb/repe scas{w,l,q} */
18957663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (!haveF2(pfx) && haveF3(pfx)) {
18958663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (opc == 0xAE)
18959663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            sz = 1;
18960663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dis_REP_op ( dres, AMD64CondZ, dis_SCAS, sz,
18961663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      guest_RIP_curr_instr,
18962663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      guest_RIP_bbstart+delta, "repe scas", pfx );
18963663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(dres->whatNext == Dis_StopHere);
18964663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return delta;
18965663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
18966663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* AE/AF: scasb/scas{w,l,q} */
18967663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (!haveF2(pfx) && !haveF3(pfx)) {
18968663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (opc == 0xAE)
18969663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            sz = 1;
18970663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dis_string_op( dis_SCAS, sz, "scas", pfx );
18971663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return delta;
18972663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
18973663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      goto decode_failure;
18974663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18975663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* XXXX be careful here with moves to AH/BH/CH/DH */
18976663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xB0: /* MOV imm,AL */
18977663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xB1: /* MOV imm,CL */
18978663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xB2: /* MOV imm,DL */
18979663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xB3: /* MOV imm,BL */
18980663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xB4: /* MOV imm,AH */
18981663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xB5: /* MOV imm,CH */
18982663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xB6: /* MOV imm,DH */
18983663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xB7: /* MOV imm,BH */
18984663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
18985663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d64 = getUChar(delta);
18986663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1;
18987663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      putIRegRexB(1, pfx, opc-0xB0, mkU8(d64));
18988663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("movb $%lld,%s\n", d64, nameIRegRexB(1,pfx,opc-0xB0));
18989663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
18990663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18991663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xB8: /* MOV imm,eAX */
18992663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xB9: /* MOV imm,eCX */
18993663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xBA: /* MOV imm,eDX */
18994663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xBB: /* MOV imm,eBX */
18995663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xBC: /* MOV imm,eSP */
18996663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xBD: /* MOV imm,eBP */
18997663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xBE: /* MOV imm,eSI */
18998663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xBF: /* MOV imm,eDI */
18999663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* This is the one-and-only place where 64-bit literals are
19000663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         allowed in the instruction stream. */
19001663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
19002663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (sz == 8) {
19003663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d64 = getDisp64(delta);
19004663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta += 8;
19005663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putIRegRexB(8, pfx, opc-0xB8, mkU64(d64));
19006663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("movabsq $%lld,%s\n", (Long)d64,
19007663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   nameIRegRexB(8,pfx,opc-0xB8));
19008663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      } else {
19009663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d64 = getSDisp(imin(4,sz),delta);
19010663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta += imin(4,sz);
19011663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putIRegRexB(sz, pfx, opc-0xB8,
19012663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         mkU(szToITy(sz), d64 & mkSizeMask(sz)));
19013663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("mov%c $%lld,%s\n", nameISize(sz),
19014663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                 (Long)d64,
19015663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                 nameIRegRexB(sz,pfx,opc-0xB8));
19016663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
19017663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
19018663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19019663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xC0: { /* Grp2 Ib,Eb */
19020663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Bool decode_OK = True;
19021663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
19022663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      modrm = getUChar(delta);
19023663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      am_sz = lengthAMode(pfx,delta);
19024663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d_sz  = 1;
19025663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d64   = getUChar(delta + am_sz);
19026663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      sz    = 1;
19027663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_Grp2 ( vbi, pfx, delta, modrm, am_sz, d_sz, sz,
19028663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         mkU8(d64 & 0xFF), NULL, &decode_OK );
19029663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (!decode_OK) goto decode_failure;
19030663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
19031663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
19032663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19033663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xC1: { /* Grp2 Ib,Ev */
19034663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Bool decode_OK = True;
19035663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
19036663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      modrm = getUChar(delta);
19037663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      am_sz = lengthAMode(pfx,delta);
19038663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d_sz  = 1;
19039663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d64   = getUChar(delta + am_sz);
19040663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_Grp2 ( vbi, pfx, delta, modrm, am_sz, d_sz, sz,
19041663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         mkU8(d64 & 0xFF), NULL, &decode_OK );
19042663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (!decode_OK) goto decode_failure;
19043663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
19044663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
19045663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19046663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xC2: /* RET imm16 */
19047663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66orF2orF3(pfx)) goto decode_failure;
19048663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d64 = getUDisp16(delta);
19049663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 2;
19050663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      dis_ret(dres, vbi, d64);
19051663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("ret $%lld\n", d64);
19052663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
19053663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19054663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xC3: /* RET */
19055663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66orF2(pfx)) goto decode_failure;
19056663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* F3 is acceptable on AMD. */
19057663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      dis_ret(dres, vbi, 0);
19058663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP(haveF3(pfx) ? "rep ; ret\n" : "ret\n");
19059663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
19060663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19061663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xC6: /* MOV Ib,Eb */
19062663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      sz = 1;
19063663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      goto do_Mov_I_E;
19064663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xC7: /* MOV Iv,Ev */
19065663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      goto do_Mov_I_E;
19066663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   do_Mov_I_E:
19067663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
19068663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      modrm = getUChar(delta);
19069663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (epartIsReg(modrm)) {
19070663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta++; /* mod/rm byte */
19071663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d64 = getSDisp(imin(4,sz),delta);
19072663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta += imin(4,sz);
19073663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putIRegE(sz, pfx, modrm,
19074663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      mkU(szToITy(sz), d64 & mkSizeMask(sz)));
19075663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("mov%c $%lld, %s\n", nameISize(sz),
19076663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  (Long)d64,
19077663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  nameIRegE(sz,pfx,modrm));
19078663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      } else {
19079663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addr = disAMode ( &alen, vbi, pfx, delta, dis_buf,
19080663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           /*xtra*/imin(4,sz) );
19081663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta += alen;
19082663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d64 = getSDisp(imin(4,sz),delta);
19083663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta += imin(4,sz);
19084663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         storeLE(mkexpr(addr),
19085663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 mkU(szToITy(sz), d64 & mkSizeMask(sz)));
19086663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("mov%c $%lld, %s\n", nameISize(sz), (Long)d64, dis_buf);
19087663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
19088663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
19089663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19090663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xC8: /* ENTER */
19091663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Same comments re operand size as for LEAVE below apply.
19092663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Also, only handles the case "enter $imm16, $0"; other cases
19093663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         for the second operand (nesting depth) are not handled. */
19094663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (sz != 4)
19095663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_failure;
19096663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d64 = getUDisp16(delta);
19097663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 2;
19098663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(d64 >= 0 && d64 <= 0xFFFF);
19099663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (getUChar(delta) != 0)
19100663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_failure;
19101663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta++;
19102663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Intel docs seem to suggest:
19103663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           push rbp
19104663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           temp = rsp
19105663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           rbp = temp
19106663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           rsp = rsp - imm16
19107663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      */
19108663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      t1 = newTemp(Ity_I64);
19109663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(t1, getIReg64(R_RBP));
19110663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      t2 = newTemp(Ity_I64);
19111663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(t2, binop(Iop_Sub64, getIReg64(R_RSP), mkU64(8)));
19112663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      putIReg64(R_RSP, mkexpr(t2));
19113663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      storeLE(mkexpr(t2), mkexpr(t1));
19114663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      putIReg64(R_RBP, mkexpr(t2));
19115663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (d64 > 0) {
19116663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putIReg64(R_RSP, binop(Iop_Sub64, mkexpr(t2), mkU64(d64)));
19117663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
19118663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("enter $%u, $0\n", (UInt)d64);
19119663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
19120663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19121663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xC9: /* LEAVE */
19122663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* In 64-bit mode this defaults to a 64-bit operand size.  There
19123663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         is no way to encode a 32-bit variant.  Hence sz==4 but we do
19124663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         it as if sz=8. */
19125663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (sz != 4)
19126663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_failure;
19127663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      t1 = newTemp(Ity_I64);
19128663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      t2 = newTemp(Ity_I64);
19129663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(t1, getIReg64(R_RBP));
19130663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* First PUT RSP looks redundant, but need it because RSP must
19131663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         always be up-to-date for Memcheck to work... */
19132663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      putIReg64(R_RSP, mkexpr(t1));
19133663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(t2, loadLE(Ity_I64,mkexpr(t1)));
19134663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      putIReg64(R_RBP, mkexpr(t2));
19135663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      putIReg64(R_RSP, binop(Iop_Add64, mkexpr(t1), mkU64(8)) );
19136663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("leave\n");
19137663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
19138663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19139663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xCC: /* INT 3 */
19140663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      jmp_lit(dres, Ijk_SigTRAP, guest_RIP_bbstart + delta);
19141663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(dres->whatNext == Dis_StopHere);
19142663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("int $0x3\n");
19143663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
19144663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19145663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xD0: { /* Grp2 1,Eb */
19146663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Bool decode_OK = True;
19147663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
19148663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      modrm = getUChar(delta);
19149663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      am_sz = lengthAMode(pfx,delta);
19150663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d_sz  = 0;
19151663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d64   = 1;
19152663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      sz    = 1;
19153663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_Grp2 ( vbi, pfx, delta, modrm, am_sz, d_sz, sz,
19154663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         mkU8(d64), NULL, &decode_OK );
19155663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (!decode_OK) goto decode_failure;
19156663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
19157663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
19158663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19159663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xD1: { /* Grp2 1,Ev */
19160663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Bool decode_OK = True;
19161663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
19162663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      modrm = getUChar(delta);
19163663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      am_sz = lengthAMode(pfx,delta);
19164663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d_sz  = 0;
19165663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d64   = 1;
19166663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_Grp2 ( vbi, pfx, delta, modrm, am_sz, d_sz, sz,
19167663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         mkU8(d64), NULL, &decode_OK );
19168663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (!decode_OK) goto decode_failure;
19169663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
19170663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
19171663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19172663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xD2: { /* Grp2 CL,Eb */
19173663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Bool decode_OK = True;
19174663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
19175663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      modrm = getUChar(delta);
19176663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      am_sz = lengthAMode(pfx,delta);
19177663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d_sz  = 0;
19178663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      sz    = 1;
19179663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_Grp2 ( vbi, pfx, delta, modrm, am_sz, d_sz, sz,
19180663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         getIRegCL(), "%cl", &decode_OK );
19181663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (!decode_OK) goto decode_failure;
19182663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
19183663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
19184663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19185663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xD3: { /* Grp2 CL,Ev */
19186663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Bool decode_OK = True;
19187663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
19188663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      modrm = getUChar(delta);
19189663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      am_sz = lengthAMode(pfx,delta);
19190663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d_sz  = 0;
19191663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_Grp2 ( vbi, pfx, delta, modrm, am_sz, d_sz, sz,
19192663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         getIRegCL(), "%cl", &decode_OK );
19193663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (!decode_OK) goto decode_failure;
19194663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
19195663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
19196663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19197663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xD8: /* X87 instructions */
19198663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xD9:
19199663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xDA:
19200663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xDB:
19201663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xDC:
19202663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xDD:
19203663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xDE:
19204663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xDF: {
19205663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Bool redundantREXWok = False;
19206663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19207663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx))
19208663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_failure;
19209663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19210663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* kludge to tolerate redundant rex.w prefixes (should do this
19211663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         properly one day) */
19212663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* mono 1.1.18.1 produces 48 D9 FA, which is rex.w fsqrt */
19213663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if ( (opc == 0xD9 && getUChar(delta+0) == 0xFA)/*fsqrt*/ )
19214663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         redundantREXWok = True;
19215663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19216663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Bool size_OK = False;
19217663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if ( sz == 4 )
19218663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         size_OK = True;
19219663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      else if ( sz == 8 )
19220663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         size_OK = redundantREXWok;
19221663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      else if ( sz == 2 ) {
19222663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         int mod_rm = getUChar(delta+0);
19223663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         int reg = gregLO3ofRM(mod_rm);
19224663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* The HotSpot JVM uses these */
19225663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if ( (opc == 0xDD) && (reg == 0 /* FLDL   */ ||
19226663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                reg == 4 /* FNSAVE */ ||
19227663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                reg == 6 /* FRSTOR */ ) )
19228663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            size_OK = True;
19229663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
19230663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* AMD manual says 0x66 size override is ignored, except where
19231663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         it is meaningful */
19232663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (!size_OK)
19233663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_failure;
19234663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19235663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Bool decode_OK = False;
19236663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_FPU ( &decode_OK, vbi, pfx, delta );
19237663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (!decode_OK)
19238663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_failure;
19239663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19240663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
19241663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
19242663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19243663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xE0: /* LOOPNE disp8: decrement count, jump if count != 0 && ZF==0 */
19244663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xE1: /* LOOPE  disp8: decrement count, jump if count != 0 && ZF==1 */
19245663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xE2: /* LOOP   disp8: decrement count, jump if count != 0 */
19246663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng    { /* The docs say this uses rCX as a count depending on the
19247663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         address size override, not the operand one. */
19248663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRExpr* zbit  = NULL;
19249663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRExpr* count = NULL;
19250663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRExpr* cond  = NULL;
19251663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HChar*  xtra  = NULL;
19252663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19253663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66orF2orF3(pfx) || 1==getRexW(pfx)) goto decode_failure;
19254663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* So at this point we've rejected any variants which appear to
19255663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         be governed by the usual operand-size modifiers.  Hence only
19256663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         the address size prefix can have an effect.  It changes the
19257663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         size from 64 (default) to 32. */
19258663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d64 = guest_RIP_bbstart+delta+1 + getSDisp8(delta);
19259663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta++;
19260663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveASO(pfx)) {
19261663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* 64to32 of 64-bit get is merely a get-put improvement
19262663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            trick. */
19263663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putIReg32(R_RCX, binop(Iop_Sub32,
19264663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                unop(Iop_64to32, getIReg64(R_RCX)),
19265663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                mkU32(1)));
19266663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      } else {
19267663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putIReg64(R_RCX, binop(Iop_Sub64, getIReg64(R_RCX), mkU64(1)));
19268663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
19269663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19270663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* This is correct, both for 32- and 64-bit versions.  If we're
19271663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         doing a 32-bit dec and the result is zero then the default
19272663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         zero extension rule will cause the upper 32 bits to be zero
19273663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         too.  Hence a 64-bit check against zero is OK. */
19274663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      count = getIReg64(R_RCX);
19275663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      cond = binop(Iop_CmpNE64, count, mkU64(0));
19276663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (opc) {
19277663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case 0xE2:
19278663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            xtra = "";
19279663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
19280663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case 0xE1:
19281663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            xtra = "e";
19282663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            zbit = mk_amd64g_calculate_condition( AMD64CondZ );
19283663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            cond = mkAnd1(cond, zbit);
19284663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
19285663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case 0xE0:
19286663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            xtra = "ne";
19287663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            zbit = mk_amd64g_calculate_condition( AMD64CondNZ );
19288663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            cond = mkAnd1(cond, zbit);
19289663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
19290663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         default:
19291663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng	    vassert(0);
19292663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
19293663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      stmt( IRStmt_Exit(cond, Ijk_Boring, IRConst_U64(d64), OFFB_RIP) );
19294663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19295663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("loop%s%s 0x%llx\n", xtra, haveASO(pfx) ? "l" : "", d64);
19296663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
19297663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng    }
19298663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19299663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xE3:
19300663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* JRCXZ or JECXZ, depending address size override. */
19301663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66orF2orF3(pfx)) goto decode_failure;
19302663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d64 = (guest_RIP_bbstart+delta+1) + getSDisp8(delta);
19303663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta++;
19304663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveASO(pfx)) {
19305663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* 32-bit */
19306663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         stmt( IRStmt_Exit( binop(Iop_CmpEQ64,
19307663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  unop(Iop_32Uto64, getIReg32(R_RCX)),
19308663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  mkU64(0)),
19309663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            Ijk_Boring,
19310663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            IRConst_U64(d64),
19311663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            OFFB_RIP
19312663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             ));
19313663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("jecxz 0x%llx\n", d64);
19314663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      } else {
19315663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* 64-bit */
19316663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         stmt( IRStmt_Exit( binop(Iop_CmpEQ64,
19317663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  getIReg64(R_RCX),
19318663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  mkU64(0)),
19319663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            Ijk_Boring,
19320663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            IRConst_U64(d64),
19321663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            OFFB_RIP
19322663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               ));
19323663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("jrcxz 0x%llx\n", d64);
19324663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
19325663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
19326663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19327663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xE4: /* IN imm8, AL */
19328663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      sz = 1;
19329663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      t1 = newTemp(Ity_I64);
19330663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      abyte = getUChar(delta); delta++;
19331663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(t1, mkU64( abyte & 0xFF ));
19332663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("in%c $%d,%s\n", nameISize(sz), (Int)abyte, nameIRegRAX(sz));
19333663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      goto do_IN;
19334663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xE5: /* IN imm8, eAX */
19335663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (!(sz == 2 || sz == 4)) goto decode_failure;
19336663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      t1 = newTemp(Ity_I64);
19337663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      abyte = getUChar(delta); delta++;
19338663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(t1, mkU64( abyte & 0xFF ));
19339663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("in%c $%d,%s\n", nameISize(sz), (Int)abyte, nameIRegRAX(sz));
19340663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      goto do_IN;
19341663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xEC: /* IN %DX, AL */
19342663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      sz = 1;
19343663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      t1 = newTemp(Ity_I64);
19344663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(t1, unop(Iop_16Uto64, getIRegRDX(2)));
19345663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("in%c %s,%s\n", nameISize(sz), nameIRegRDX(2),
19346663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                         nameIRegRAX(sz));
19347663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      goto do_IN;
19348663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xED: /* IN %DX, eAX */
19349663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (!(sz == 2 || sz == 4)) goto decode_failure;
19350663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      t1 = newTemp(Ity_I64);
19351663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(t1, unop(Iop_16Uto64, getIRegRDX(2)));
19352663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("in%c %s,%s\n", nameISize(sz), nameIRegRDX(2),
19353663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                         nameIRegRAX(sz));
19354663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      goto do_IN;
19355663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   do_IN: {
19356663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* At this point, sz indicates the width, and t1 is a 64-bit
19357663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         value giving port number. */
19358663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRDirty* d;
19359663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
19360663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(sz == 1 || sz == 2 || sz == 4);
19361663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ty = szToITy(sz);
19362663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      t2 = newTemp(Ity_I64);
19363663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d = unsafeIRDirty_1_N(
19364663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             t2,
19365663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             0/*regparms*/,
19366663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             "amd64g_dirtyhelper_IN",
19367663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             &amd64g_dirtyhelper_IN,
19368663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             mkIRExprVec_2( mkexpr(t1), mkU64(sz) )
19369663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          );
19370663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* do the call, dumping the result in t2. */
19371663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      stmt( IRStmt_Dirty(d) );
19372663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      putIRegRAX(sz, narrowTo( ty, mkexpr(t2) ) );
19373663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
19374663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
19375663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19376663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xE6: /* OUT AL, imm8 */
19377663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      sz = 1;
19378663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      t1 = newTemp(Ity_I64);
19379663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      abyte = getUChar(delta); delta++;
19380663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( t1, mkU64( abyte & 0xFF ) );
19381663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("out%c %s,$%d\n", nameISize(sz), nameIRegRAX(sz), (Int)abyte);
19382663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      goto do_OUT;
19383663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xE7: /* OUT eAX, imm8 */
19384663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (!(sz == 2 || sz == 4)) goto decode_failure;
19385663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      t1 = newTemp(Ity_I64);
19386663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      abyte = getUChar(delta); delta++;
19387663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( t1, mkU64( abyte & 0xFF ) );
19388663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("out%c %s,$%d\n", nameISize(sz), nameIRegRAX(sz), (Int)abyte);
19389663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      goto do_OUT;
19390663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xEE: /* OUT AL, %DX */
19391663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      sz = 1;
19392663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      t1 = newTemp(Ity_I64);
19393663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( t1, unop(Iop_16Uto64, getIRegRDX(2)) );
19394663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("out%c %s,%s\n", nameISize(sz), nameIRegRAX(sz),
19395663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                          nameIRegRDX(2));
19396663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      goto do_OUT;
19397663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xEF: /* OUT eAX, %DX */
19398663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (!(sz == 2 || sz == 4)) goto decode_failure;
19399663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      t1 = newTemp(Ity_I64);
19400663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( t1, unop(Iop_16Uto64, getIRegRDX(2)) );
19401663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("out%c %s,%s\n", nameISize(sz), nameIRegRAX(sz),
19402663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                          nameIRegRDX(2));
19403663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      goto do_OUT;
19404663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   do_OUT: {
19405663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* At this point, sz indicates the width, and t1 is a 64-bit
19406663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         value giving port number. */
19407663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRDirty* d;
19408663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
19409663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(sz == 1 || sz == 2 || sz == 4);
19410663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ty = szToITy(sz);
19411663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d = unsafeIRDirty_0_N(
19412663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             0/*regparms*/,
19413663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             "amd64g_dirtyhelper_OUT",
19414663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             &amd64g_dirtyhelper_OUT,
19415663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             mkIRExprVec_3( mkexpr(t1),
19416663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            widenUto64( getIRegRAX(sz) ),
19417663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            mkU64(sz) )
19418663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          );
19419663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      stmt( IRStmt_Dirty(d) );
19420663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
19421663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
19422663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19423663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xE8: /* CALL J4 */
19424663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
19425663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d64 = getSDisp32(delta); delta += 4;
19426663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d64 += (guest_RIP_bbstart+delta);
19427663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* (guest_RIP_bbstart+delta) == return-to addr, d64 == call-to addr */
19428663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      t1 = newTemp(Ity_I64);
19429663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(t1, binop(Iop_Sub64, getIReg64(R_RSP), mkU64(8)));
19430663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      putIReg64(R_RSP, mkexpr(t1));
19431663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      storeLE( mkexpr(t1), mkU64(guest_RIP_bbstart+delta));
19432663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      t2 = newTemp(Ity_I64);
19433663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(t2, mkU64((Addr64)d64));
19434663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      make_redzone_AbiHint(vbi, t1, t2/*nia*/, "call-d32");
19435663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (resteerOkFn( callback_opaque, (Addr64)d64) ) {
19436663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* follow into the call target. */
19437663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dres->whatNext   = Dis_ResteerU;
19438663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dres->continueAt = d64;
19439663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      } else {
19440663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         jmp_lit(dres, Ijk_Call, d64);
19441663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(dres->whatNext == Dis_StopHere);
19442663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
19443663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("call 0x%llx\n",d64);
19444663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
19445663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19446663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xE9: /* Jv (jump, 16/32 offset) */
19447663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
19448663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (sz != 4)
19449663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_failure; /* JRS added 2004 July 11 */
19450663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d64 = (guest_RIP_bbstart+delta+sz) + getSDisp(sz,delta);
19451663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += sz;
19452663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (resteerOkFn(callback_opaque,d64)) {
19453663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dres->whatNext   = Dis_ResteerU;
19454663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dres->continueAt = d64;
19455663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      } else {
19456663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         jmp_lit(dres, Ijk_Boring, d64);
19457663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(dres->whatNext == Dis_StopHere);
19458663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
19459663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("jmp 0x%llx\n", d64);
19460663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
19461663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19462663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xEB: /* Jb (jump, byte offset) */
19463663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
19464663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (sz != 4)
19465663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_failure; /* JRS added 2004 July 11 */
19466663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d64 = (guest_RIP_bbstart+delta+1) + getSDisp8(delta);
19467663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta++;
19468663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (resteerOkFn(callback_opaque,d64)) {
19469663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dres->whatNext   = Dis_ResteerU;
19470663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dres->continueAt = d64;
19471663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      } else {
19472663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         jmp_lit(dres, Ijk_Boring, d64);
19473663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(dres->whatNext == Dis_StopHere);
19474663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
19475663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("jmp-8 0x%llx\n", d64);
19476663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
19477663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19478663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xF5: /* CMC */
19479663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xF8: /* CLC */
19480663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xF9: /* STC */
19481663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      t1 = newTemp(Ity_I64);
19482663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      t2 = newTemp(Ity_I64);
19483663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( t1, mk_amd64g_calculate_rflags_all() );
19484663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (opc) {
19485663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case 0xF5:
19486663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( t2, binop(Iop_Xor64, mkexpr(t1),
19487663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                         mkU64(AMD64G_CC_MASK_C)));
19488663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("cmc\n");
19489663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
19490663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case 0xF8:
19491663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( t2, binop(Iop_And64, mkexpr(t1),
19492663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                         mkU64(~AMD64G_CC_MASK_C)));
19493663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("clc\n");
19494663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
19495663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case 0xF9:
19496663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( t2, binop(Iop_Or64, mkexpr(t1),
19497663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        mkU64(AMD64G_CC_MASK_C)));
19498663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("stc\n");
19499663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
19500663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         default:
19501663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            vpanic("disInstr(x64)(cmc/clc/stc)");
19502663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
19503663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      stmt( IRStmt_Put( OFFB_CC_OP,   mkU64(AMD64G_CC_OP_COPY) ));
19504663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      stmt( IRStmt_Put( OFFB_CC_DEP2, mkU64(0) ));
19505663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      stmt( IRStmt_Put( OFFB_CC_DEP1, mkexpr(t2) ));
19506663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Set NDEP even though it isn't used.  This makes redundant-PUT
19507663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         elimination of previous stores to this field work better. */
19508663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      stmt( IRStmt_Put( OFFB_CC_NDEP, mkU64(0) ));
19509663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
19510663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19511663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xF6: { /* Grp3 Eb */
19512663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Bool decode_OK = True;
19513663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
19514663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_Grp3 ( vbi, pfx, 1, delta, &decode_OK );
19515663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (!decode_OK) goto decode_failure;
19516663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
19517663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
19518663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19519663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xF7: { /* Grp3 Ev */
19520663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Bool decode_OK = True;
19521663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
19522663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_Grp3 ( vbi, pfx, sz, delta, &decode_OK );
19523663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (!decode_OK) goto decode_failure;
19524663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
19525663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
19526663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19527663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xFC: /* CLD */
19528663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
19529663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      stmt( IRStmt_Put( OFFB_DFLAG, mkU64(1)) );
19530663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("cld\n");
19531663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
19532663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19533663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xFD: /* STD */
19534663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
19535663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      stmt( IRStmt_Put( OFFB_DFLAG, mkU64(-1ULL)) );
19536663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("std\n");
19537663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
19538663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19539663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xFE: { /* Grp4 Eb */
19540663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Bool decode_OK = True;
19541663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
19542663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_Grp4 ( vbi, pfx, delta, &decode_OK );
19543663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (!decode_OK) goto decode_failure;
19544663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
19545663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
19546663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19547663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xFF: { /* Grp5 Ev */
19548663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Bool decode_OK = True;
19549663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
19550663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_Grp5 ( vbi, pfx, sz, delta, dres, &decode_OK );
19551663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (!decode_OK) goto decode_failure;
19552663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
19553663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
19554663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19555663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   default:
19556663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
19557663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19558663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
19559663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19560663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  decode_failure:
19561663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return deltaIN; /* fail */
19562663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
19563663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19564663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19565663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*------------------------------------------------------------*/
19566663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---                                                      ---*/
19567663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*--- Top-level post-escape decoders: dis_ESC_0F           ---*/
19568663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---                                                      ---*/
19569663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*------------------------------------------------------------*/
19570663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19571663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRTemp math_BSWAP ( IRTemp t1, IRType ty )
19572663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
19573663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t2 = newTemp(ty);
19574663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (ty == Ity_I64) {
19575663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRTemp m8  = newTemp(Ity_I64);
19576663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRTemp s8  = newTemp(Ity_I64);
19577663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRTemp m16 = newTemp(Ity_I64);
19578663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRTemp s16 = newTemp(Ity_I64);
19579663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRTemp m32 = newTemp(Ity_I64);
19580663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( m8, mkU64(0xFF00FF00FF00FF00ULL) );
19581663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( s8,
19582663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              binop(Iop_Or64,
19583663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    binop(Iop_Shr64,
19584663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          binop(Iop_And64,mkexpr(t1),mkexpr(m8)),
19585663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          mkU8(8)),
19586663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    binop(Iop_And64,
19587663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          binop(Iop_Shl64,mkexpr(t1),mkU8(8)),
19588663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          mkexpr(m8))
19589663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   )
19590663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            );
19591663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19592663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( m16, mkU64(0xFFFF0000FFFF0000ULL) );
19593663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( s16,
19594663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              binop(Iop_Or64,
19595663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    binop(Iop_Shr64,
19596663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          binop(Iop_And64,mkexpr(s8),mkexpr(m16)),
19597663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          mkU8(16)),
19598663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    binop(Iop_And64,
19599663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          binop(Iop_Shl64,mkexpr(s8),mkU8(16)),
19600663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          mkexpr(m16))
19601663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   )
19602663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            );
19603663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19604663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( m32, mkU64(0xFFFFFFFF00000000ULL) );
19605663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( t2,
19606663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              binop(Iop_Or64,
19607663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    binop(Iop_Shr64,
19608663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          binop(Iop_And64,mkexpr(s16),mkexpr(m32)),
19609663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          mkU8(32)),
19610663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    binop(Iop_And64,
19611663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          binop(Iop_Shl64,mkexpr(s16),mkU8(32)),
19612663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          mkexpr(m32))
19613663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   )
19614663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            );
19615663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return t2;
19616663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
19617663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (ty == Ity_I32) {
19618663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( t2,
19619663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         binop(
19620663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            Iop_Or32,
19621663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            binop(Iop_Shl32, mkexpr(t1), mkU8(24)),
19622663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            binop(
19623663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               Iop_Or32,
19624663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               binop(Iop_And32, binop(Iop_Shl32, mkexpr(t1), mkU8(8)),
19625663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                mkU32(0x00FF0000)),
19626663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               binop(Iop_Or32,
19627663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     binop(Iop_And32, binop(Iop_Shr32, mkexpr(t1), mkU8(8)),
19628663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                      mkU32(0x0000FF00)),
19629663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     binop(Iop_And32, binop(Iop_Shr32, mkexpr(t1), mkU8(24)),
19630663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                      mkU32(0x000000FF) )
19631663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            )))
19632663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      );
19633663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return t2;
19634663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
19635663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (ty == Ity_I16) {
19636663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(t2,
19637663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             binop(Iop_Or16,
19638663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   binop(Iop_Shl16, mkexpr(t1), mkU8(8)),
19639663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   binop(Iop_Shr16, mkexpr(t1), mkU8(8)) ));
19640663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return t2;
19641663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
19642663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(0);
19643663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /*NOTREACHED*/
19644663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return IRTemp_INVALID;
19645663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
19646663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19647663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19648663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng__attribute__((noinline))
19649663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic
19650663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengLong dis_ESC_0F (
19651663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        /*MB_OUT*/DisResult* dres,
19652663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        /*MB_OUT*/Bool*      expect_CAS,
19653663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        Bool         (*resteerOkFn) ( /*opaque*/void*, Addr64 ),
19654663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        Bool         resteerCisOk,
19655663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        void*        callback_opaque,
19656663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        VexArchInfo* archinfo,
19657663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        VexAbiInfo*  vbi,
19658663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        Prefix pfx, Int sz, Long deltaIN
19659663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     )
19660663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
19661663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Long   d64   = 0;
19662663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr  = IRTemp_INVALID;
19663663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t1    = IRTemp_INVALID;
19664663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t2    = IRTemp_INVALID;
19665663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm = 0;
19666663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    am_sz = 0;
19667663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen  = 0;
19668663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
19669663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19670663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* In the first switch, look for ordinary integer insns. */
19671663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Long   delta = deltaIN;
19672663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  opc   = getUChar(delta);
19673663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   delta++;
19674663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (opc) { /* first switch */
19675663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19676663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x01:
19677663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   {
19678663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      modrm = getUChar(delta);
19679663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 01 /0 -- SGDT */
19680663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 01 /1 -- SIDT */
19681663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (!epartIsReg(modrm)
19682663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (gregLO3ofRM(modrm) == 0 || gregLO3ofRM(modrm) == 1)) {
19683663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* This is really revolting, but ... since each processor
19684663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            (core) only has one IDT and one GDT, just let the guest
19685663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            see it (pass-through semantics).  I can't see any way to
19686663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            construct a faked-up value, so don't bother to try. */
19687663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
19688663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta += alen;
19689663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         switch (gregLO3ofRM(modrm)) {
19690663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 0: DIP("sgdt %s\n", dis_buf); break;
19691663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 1: DIP("sidt %s\n", dis_buf); break;
19692663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            default: vassert(0); /*NOTREACHED*/
19693663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
19694663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRDirty* d = unsafeIRDirty_0_N (
19695663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          0/*regparms*/,
19696663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          "amd64g_dirtyhelper_SxDT",
19697663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          &amd64g_dirtyhelper_SxDT,
19698663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          mkIRExprVec_2( mkexpr(addr),
19699663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                         mkU64(gregLO3ofRM(modrm)) )
19700663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      );
19701663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* declare we're writing memory */
19702663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->mFx   = Ifx_Write;
19703663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->mAddr = mkexpr(addr);
19704663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d->mSize = 6;
19705663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         stmt( IRStmt_Dirty(d) );
19706663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return delta;
19707663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
19708663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 0F 01 D0 = XGETBV */
19709663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (modrm == 0xD0 && (archinfo->hwcaps & VEX_HWCAPS_AMD64_AVX)) {
19710663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta += 1;
19711663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("xgetbv\n");
19712663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Fault (SEGV) if ECX isn't zero.  Intel docs say #GP and I
19713663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            am not sure if that translates in to SEGV or to something
19714663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            else, in user space. */
19715663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         t1 = newTemp(Ity_I32);
19716663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( t1, getIReg32(R_RCX) );
19717663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         stmt( IRStmt_Exit(binop(Iop_CmpNE32, mkexpr(t1), mkU32(0)),
19718663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           Ijk_SigSEGV,
19719663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           IRConst_U64(guest_RIP_curr_instr),
19720663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           OFFB_RIP
19721663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         ));
19722663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putIRegRAX(4, mkU32(7));
19723663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putIRegRDX(4, mkU32(0));
19724663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return delta;
19725663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
19726663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* else decode failed */
19727663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
19728663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
19729663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19730663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x05: /* SYSCALL */
19731663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      guest_RIP_next_mustcheck = True;
19732663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      guest_RIP_next_assumed = guest_RIP_bbstart + delta;
19733663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      putIReg64( R_RCX, mkU64(guest_RIP_next_assumed) );
19734663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* It's important that all guest state is up-to-date
19735663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         at this point.  So we declare an end-of-block here, which
19736663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         forces any cached guest state to be flushed. */
19737663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      jmp_lit(dres, Ijk_Sys_syscall, guest_RIP_next_assumed);
19738663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(dres->whatNext == Dis_StopHere);
19739663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("syscall\n");
19740663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
19741663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19742663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x0B: /* UD2 */
19743663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      stmt( IRStmt_Put( OFFB_RIP, mkU64(guest_RIP_curr_instr) ) );
19744663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      jmp_lit(dres, Ijk_NoDecode, guest_RIP_curr_instr);
19745663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(dres->whatNext == Dis_StopHere);
19746663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("ud2\n");
19747663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
19748663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19749663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x0D: /* 0F 0D /0 -- prefetch mem8 */
19750663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              /* 0F 0D /1 -- prefetchw mem8 */
19751663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66orF2orF3(pfx)) goto decode_failure;
19752663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      modrm = getUChar(delta);
19753663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (epartIsReg(modrm)) goto decode_failure;
19754663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (gregLO3ofRM(modrm) != 0 && gregLO3ofRM(modrm) != 1)
19755663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_failure;
19756663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
19757663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen;
19758663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (gregLO3ofRM(modrm)) {
19759663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case 0: DIP("prefetch %s\n", dis_buf); break;
19760663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case 1: DIP("prefetchw %s\n", dis_buf); break;
19761663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         default: vassert(0); /*NOTREACHED*/
19762663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
19763663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
19764663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19765663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x1F:
19766663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
19767663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      modrm = getUChar(delta);
19768663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (epartIsReg(modrm)) goto decode_failure;
19769663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
19770663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen;
19771663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("nop%c %s\n", nameISize(sz), dis_buf);
19772663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
19773663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19774663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x31: { /* RDTSC */
19775663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRTemp   val  = newTemp(Ity_I64);
19776663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRExpr** args = mkIRExprVec_0();
19777663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRDirty* d    = unsafeIRDirty_1_N (
19778663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         val,
19779663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         0/*regparms*/,
19780663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         "amd64g_dirtyhelper_RDTSC",
19781663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         &amd64g_dirtyhelper_RDTSC,
19782663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         args
19783663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      );
19784663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66orF2orF3(pfx)) goto decode_failure;
19785663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* execute the dirty call, dumping the result in val. */
19786663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      stmt( IRStmt_Dirty(d) );
19787663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      putIRegRDX(4, unop(Iop_64HIto32, mkexpr(val)));
19788663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      putIRegRAX(4, unop(Iop_64to32, mkexpr(val)));
19789663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("rdtsc\n");
19790663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
19791663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
19792663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19793663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x40:
19794663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x41:
19795663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x42: /* CMOVBb/CMOVNAEb (cmov below) */
19796663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x43: /* CMOVNBb/CMOVAEb (cmov not below) */
19797663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x44: /* CMOVZb/CMOVEb (cmov zero) */
19798663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x45: /* CMOVNZb/CMOVNEb (cmov not zero) */
19799663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x46: /* CMOVBEb/CMOVNAb (cmov below or equal) */
19800663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x47: /* CMOVNBEb/CMOVAb (cmov not below or equal) */
19801663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x48: /* CMOVSb (cmov negative) */
19802663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x49: /* CMOVSb (cmov not negative) */
19803663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x4A: /* CMOVP (cmov parity even) */
19804663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x4B: /* CMOVNP (cmov parity odd) */
19805663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x4C: /* CMOVLb/CMOVNGEb (cmov less) */
19806663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x4D: /* CMOVGEb/CMOVNLb (cmov greater or equal) */
19807663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x4E: /* CMOVLEb/CMOVNGb (cmov less or equal) */
19808663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x4F: /* CMOVGb/CMOVNLEb (cmov greater) */
19809663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
19810663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_cmov_E_G(vbi, pfx, sz, (AMD64Condcode)(opc - 0x40), delta);
19811663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
19812663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19813663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x80:
19814663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x81:
19815663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x82:   /* JBb/JNAEb (jump below) */
19816663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x83:   /* JNBb/JAEb (jump not below) */
19817663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x84:   /* JZb/JEb (jump zero) */
19818663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x85:   /* JNZb/JNEb (jump not zero) */
19819663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x86:   /* JBEb/JNAb (jump below or equal) */
19820663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x87:   /* JNBEb/JAb (jump not below or equal) */
19821663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x88:   /* JSb (jump negative) */
19822663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x89:   /* JSb (jump not negative) */
19823663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x8A:   /* JP (jump parity even) */
19824663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x8B:   /* JNP/JPO (jump parity odd) */
19825663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x8C:   /* JLb/JNGEb (jump less) */
19826663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x8D:   /* JGEb/JNLb (jump greater or equal) */
19827663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x8E:   /* JLEb/JNGb (jump less or equal) */
19828663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x8F: { /* JGb/JNLEb (jump greater) */
19829663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Long   jmpDelta;
19830663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HChar* comment  = "";
19831663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
19832663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      jmpDelta = getSDisp32(delta);
19833663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d64 = (guest_RIP_bbstart+delta+4) + jmpDelta;
19834663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 4;
19835663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (resteerCisOk
19836663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && vex_control.guest_chase_cond
19837663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (Addr64)d64 != (Addr64)guest_RIP_bbstart
19838663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && jmpDelta < 0
19839663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && resteerOkFn( callback_opaque, d64) ) {
19840663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Speculation: assume this backward branch is taken.  So
19841663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            we need to emit a side-exit to the insn following this
19842663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            one, on the negation of the condition, and continue at
19843663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            the branch target address (d64).  If we wind up back at
19844663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            the first instruction of the trace, just stop; it's
19845663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            better to let the IR loop unroller handle that case. */
19846663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         stmt( IRStmt_Exit(
19847663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  mk_amd64g_calculate_condition(
19848663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     (AMD64Condcode)(1 ^ (opc - 0x80))),
19849663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  Ijk_Boring,
19850663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  IRConst_U64(guest_RIP_bbstart+delta),
19851663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  OFFB_RIP
19852663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             ));
19853663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dres->whatNext   = Dis_ResteerC;
19854663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dres->continueAt = d64;
19855663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         comment = "(assumed taken)";
19856663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
19857663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      else
19858663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (resteerCisOk
19859663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && vex_control.guest_chase_cond
19860663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (Addr64)d64 != (Addr64)guest_RIP_bbstart
19861663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && jmpDelta >= 0
19862663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && resteerOkFn( callback_opaque, guest_RIP_bbstart+delta ) ) {
19863663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Speculation: assume this forward branch is not taken.
19864663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            So we need to emit a side-exit to d64 (the dest) and
19865663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            continue disassembling at the insn immediately
19866663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            following this one. */
19867663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         stmt( IRStmt_Exit(
19868663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  mk_amd64g_calculate_condition((AMD64Condcode)
19869663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                                (opc - 0x80)),
19870663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  Ijk_Boring,
19871663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  IRConst_U64(d64),
19872663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  OFFB_RIP
19873663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             ));
19874663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dres->whatNext   = Dis_ResteerC;
19875663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dres->continueAt = guest_RIP_bbstart+delta;
19876663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         comment = "(assumed not taken)";
19877663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
19878663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      else {
19879663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Conservative default translation - end the block at
19880663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            this point. */
19881663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         jcc_01( dres, (AMD64Condcode)(opc - 0x80),
19882663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 guest_RIP_bbstart+delta, d64 );
19883663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(dres->whatNext == Dis_StopHere);
19884663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
19885663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("j%s-32 0x%llx %s\n", name_AMD64Condcode(opc - 0x80), d64, comment);
19886663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
19887663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
19888663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19889663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x90:
19890663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x91:
19891663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x92: /* set-Bb/set-NAEb (set if below) */
19892663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x93: /* set-NBb/set-AEb (set if not below) */
19893663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x94: /* set-Zb/set-Eb (set if zero) */
19894663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x95: /* set-NZb/set-NEb (set if not zero) */
19895663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x96: /* set-BEb/set-NAb (set if below or equal) */
19896663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x97: /* set-NBEb/set-Ab (set if not below or equal) */
19897663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x98: /* set-Sb (set if negative) */
19898663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x99: /* set-Sb (set if not negative) */
19899663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x9A: /* set-P (set if parity even) */
19900663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x9B: /* set-NP (set if parity odd) */
19901663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x9C: /* set-Lb/set-NGEb (set if less) */
19902663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x9D: /* set-GEb/set-NLb (set if greater or equal) */
19903663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x9E: /* set-LEb/set-NGb (set if less or equal) */
19904663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x9F: /* set-Gb/set-NLEb (set if greater) */
19905663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
19906663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      t1 = newTemp(Ity_I8);
19907663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( t1, unop(Iop_1Uto8,mk_amd64g_calculate_condition(opc-0x90)) );
19908663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      modrm = getUChar(delta);
19909663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (epartIsReg(modrm)) {
19910663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta++;
19911663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putIRegE(1, pfx, modrm, mkexpr(t1));
19912663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("set%s %s\n", name_AMD64Condcode(opc-0x90),
19913663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           nameIRegE(1,pfx,modrm));
19914663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      } else {
19915663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
19916663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta += alen;
19917663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         storeLE( mkexpr(addr), mkexpr(t1) );
19918663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("set%s %s\n", name_AMD64Condcode(opc-0x90), dis_buf);
19919663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
19920663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
19921663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19922663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xA2: { /* CPUID */
19923663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Uses dirty helper:
19924663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            void amd64g_dirtyhelper_CPUID ( VexGuestAMD64State* )
19925663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         declared to mod rax, wr rbx, rcx, rdx
19926663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      */
19927663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRDirty* d     = NULL;
19928663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HChar*   fName = NULL;
19929663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      void*    fAddr = NULL;
19930663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
19931663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (archinfo->hwcaps == (VEX_HWCAPS_AMD64_SSE3
19932663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               |VEX_HWCAPS_AMD64_CX16
19933663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               |VEX_HWCAPS_AMD64_AVX)) {
19934663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         fName = "amd64g_dirtyhelper_CPUID_avx_and_cx16";
19935663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         fAddr = &amd64g_dirtyhelper_CPUID_avx_and_cx16;
19936663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* This is a Core-i5-2300-like machine */
19937663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
19938663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      else if (archinfo->hwcaps == (VEX_HWCAPS_AMD64_SSE3
19939663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    |VEX_HWCAPS_AMD64_CX16)) {
19940663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         fName = "amd64g_dirtyhelper_CPUID_sse42_and_cx16";
19941663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         fAddr = &amd64g_dirtyhelper_CPUID_sse42_and_cx16;
19942663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* This is a Core-i5-670-like machine */
19943663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
19944663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      else {
19945663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Give a CPUID for at least a baseline machine, SSE2
19946663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            only, and no CX16 */
19947663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         fName = "amd64g_dirtyhelper_CPUID_baseline";
19948663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         fAddr = &amd64g_dirtyhelper_CPUID_baseline;
19949663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
19950663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19951663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(fName); vassert(fAddr);
19952663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d = unsafeIRDirty_0_N ( 0/*regparms*/,
19953663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              fName, fAddr, mkIRExprVec_0() );
19954663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* declare guest state effects */
19955663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d->needsBBP = True;
19956663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d->nFxState = 4;
19957663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vex_bzero(&d->fxState, sizeof(d->fxState));
19958663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d->fxState[0].fx     = Ifx_Modify;
19959663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d->fxState[0].offset = OFFB_RAX;
19960663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d->fxState[0].size   = 8;
19961663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d->fxState[1].fx     = Ifx_Write;
19962663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d->fxState[1].offset = OFFB_RBX;
19963663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d->fxState[1].size   = 8;
19964663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d->fxState[2].fx     = Ifx_Modify;
19965663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d->fxState[2].offset = OFFB_RCX;
19966663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d->fxState[2].size   = 8;
19967663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d->fxState[3].fx     = Ifx_Write;
19968663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d->fxState[3].offset = OFFB_RDX;
19969663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d->fxState[3].size   = 8;
19970663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* execute the dirty call, side-effecting guest state */
19971663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      stmt( IRStmt_Dirty(d) );
19972663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* CPUID is a serialising insn.  So, just in case someone is
19973663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         using it as a memory fence ... */
19974663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      stmt( IRStmt_MBE(Imbe_Fence) );
19975663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("cpuid\n");
19976663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
19977663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
19978663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19979663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xA3: /* BT Gv,Ev */
19980663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
19981663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (sz != 8 && sz != 4 && sz != 2) goto decode_failure;
19982663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_bt_G_E ( vbi, pfx, sz, delta, BtOpNone );
19983663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
19984663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19985663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xA4: /* SHLDv imm8,Gv,Ev */
19986663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      modrm = getUChar(delta);
19987663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d64   = delta + lengthAMode(pfx, delta);
19988663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vex_sprintf(dis_buf, "$%d", (Int)getUChar(d64));
19989663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_SHLRD_Gv_Ev (
19990663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 vbi, pfx, delta, modrm, sz,
19991663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 mkU8(getUChar(d64)), True, /* literal */
19992663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 dis_buf, True /* left */ );
19993663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
19994663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19995663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xA5: /* SHLDv %cl,Gv,Ev */
19996663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      modrm = getUChar(delta);
19997663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_SHLRD_Gv_Ev (
19998663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 vbi, pfx, delta, modrm, sz,
19999663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 getIRegCL(), False, /* not literal */
20000663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 "%cl", True /* left */ );
20001663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
20002663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20003663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xAB: /* BTS Gv,Ev */
20004663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
20005663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (sz != 8 && sz != 4 && sz != 2) goto decode_failure;
20006663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_bt_G_E ( vbi, pfx, sz, delta, BtOpSet );
20007663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
20008663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20009663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xAC: /* SHRDv imm8,Gv,Ev */
20010663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      modrm = getUChar(delta);
20011663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d64   = delta + lengthAMode(pfx, delta);
20012663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vex_sprintf(dis_buf, "$%d", (Int)getUChar(d64));
20013663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_SHLRD_Gv_Ev (
20014663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 vbi, pfx, delta, modrm, sz,
20015663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 mkU8(getUChar(d64)), True, /* literal */
20016663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 dis_buf, False /* right */ );
20017663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
20018663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20019663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xAD: /* SHRDv %cl,Gv,Ev */
20020663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      modrm = getUChar(delta);
20021663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_SHLRD_Gv_Ev (
20022663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 vbi, pfx, delta, modrm, sz,
20023663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 getIRegCL(), False, /* not literal */
20024663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 "%cl", False /* right */);
20025663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
20026663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20027663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xAF: /* IMUL Ev, Gv */
20028663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
20029663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_mul_E_G ( vbi, pfx, sz, delta );
20030663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
20031663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20032663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xB1: { /* CMPXCHG Gv,Ev (allowed in 16,32,64 bit) */
20033663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Bool ok = True;
20034663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
20035663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (sz != 2 && sz != 4 && sz != 8) goto decode_failure;
20036663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_cmpxchg_G_E ( &ok, vbi, pfx, sz, delta );
20037663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (!ok) goto decode_failure;
20038663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
20039663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
20040663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20041663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xB0: { /* CMPXCHG Gb,Eb */
20042663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Bool ok = True;
20043663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
20044663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_cmpxchg_G_E ( &ok, vbi, pfx, 1, delta );
20045663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (!ok) goto decode_failure;
20046663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
20047663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
20048663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20049663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xB3: /* BTR Gv,Ev */
20050663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
20051663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (sz != 8 && sz != 4 && sz != 2) goto decode_failure;
20052663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_bt_G_E ( vbi, pfx, sz, delta, BtOpReset );
20053663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
20054663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20055663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xB6: /* MOVZXb Eb,Gv */
20056663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
20057663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (sz != 2 && sz != 4 && sz != 8)
20058663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_failure;
20059663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_movx_E_G ( vbi, pfx, delta, 1, sz, False );
20060663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
20061663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20062663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xB7: /* MOVZXw Ew,Gv */
20063663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
20064663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (sz != 4 && sz != 8)
20065663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_failure;
20066663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_movx_E_G ( vbi, pfx, delta, 2, sz, False );
20067663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
20068663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20069663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xBA: { /* Grp8 Ib,Ev */
20070663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Bool decode_OK = False;
20071663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
20072663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      modrm = getUChar(delta);
20073663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      am_sz = lengthAMode(pfx,delta);
20074663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d64   = getSDisp8(delta + am_sz);
20075663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_Grp8_Imm ( vbi, pfx, delta, modrm, am_sz, sz, d64,
20076663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             &decode_OK );
20077663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (!decode_OK)
20078663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_failure;
20079663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
20080663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
20081663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20082663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xBB: /* BTC Gv,Ev */
20083663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
20084663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (sz != 8 && sz != 4 && sz != 2) goto decode_failure;
20085663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_bt_G_E ( vbi, pfx, sz, delta, BtOpComp );
20086663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
20087663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20088663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xBC: /* BSF Gv,Ev */
20089663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2(pfx)) goto decode_failure;
20090663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_bs_E_G ( vbi, pfx, sz, delta, True );
20091663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
20092663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20093663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xBD: /* BSR Gv,Ev */
20094663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (!haveF2orF3(pfx)
20095663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          || (haveF3noF2(pfx)
20096663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              && 0 == (archinfo->hwcaps & VEX_HWCAPS_AMD64_LZCNT))) {
20097663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* no-F2 no-F3 0F BD = BSR
20098663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  or F3 0F BD = REP; BSR on older CPUs.  */
20099663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_bs_E_G ( vbi, pfx, sz, delta, False );
20100663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return delta;
20101663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
20102663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Fall through, since F3 0F BD is LZCNT, and needs to
20103663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         be handled by dis_ESC_0F__SSE4. */
20104663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
20105663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20106663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xBE: /* MOVSXb Eb,Gv */
20107663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
20108663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (sz != 2 && sz != 4 && sz != 8)
20109663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_failure;
20110663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_movx_E_G ( vbi, pfx, delta, 1, sz, True );
20111663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
20112663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20113663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xBF: /* MOVSXw Ew,Gv */
20114663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
20115663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (sz != 4 && sz != 8)
20116663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_failure;
20117663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_movx_E_G ( vbi, pfx, delta, 2, sz, True );
20118663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
20119663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20120663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xC1: { /* XADD Gv,Ev */
20121663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Bool decode_OK = False;
20122663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_xadd_G_E ( &decode_OK, vbi, pfx, sz, delta );
20123663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (!decode_OK)
20124663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_failure;
20125663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
20126663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
20127663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20128663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xC7: { /* CMPXCHG8B Ev, CMPXCHG16B Ev */
20129663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRType  elemTy     = sz==4 ? Ity_I32 : Ity_I64;
20130663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRTemp  expdHi     = newTemp(elemTy);
20131663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRTemp  expdLo     = newTemp(elemTy);
20132663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRTemp  dataHi     = newTemp(elemTy);
20133663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRTemp  dataLo     = newTemp(elemTy);
20134663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRTemp  oldHi      = newTemp(elemTy);
20135663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRTemp  oldLo      = newTemp(elemTy);
20136663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRTemp  flags_old  = newTemp(Ity_I64);
20137663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRTemp  flags_new  = newTemp(Ity_I64);
20138663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRTemp  success    = newTemp(Ity_I1);
20139663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IROp    opOR       = sz==4 ? Iop_Or32    : Iop_Or64;
20140663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IROp    opXOR      = sz==4 ? Iop_Xor32   : Iop_Xor64;
20141663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IROp    opCasCmpEQ = sz==4 ? Iop_CasCmpEQ32 : Iop_CasCmpEQ64;
20142663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRExpr* zero       = sz==4 ? mkU32(0)    : mkU64(0);
20143663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRTemp expdHi64    = newTemp(Ity_I64);
20144663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRTemp expdLo64    = newTemp(Ity_I64);
20145663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20146663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Translate this using a DCAS, even if there is no LOCK
20147663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         prefix.  Life is too short to bother with generating two
20148663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         different translations for the with/without-LOCK-prefix
20149663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         cases. */
20150663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      *expect_CAS = True;
20151663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20152663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Decode, and generate address. */
20153663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66orF2orF3(pfx)) goto decode_failure;
20154663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (sz != 4 && sz != 8) goto decode_failure;
20155663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (sz == 8 && !(archinfo->hwcaps & VEX_HWCAPS_AMD64_CX16))
20156663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_failure;
20157663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      modrm = getUChar(delta);
20158663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (epartIsReg(modrm)) goto decode_failure;
20159663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (gregLO3ofRM(modrm) != 1) goto decode_failure;
20160663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
20161663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen;
20162663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20163663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* cmpxchg16b requires an alignment check. */
20164663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (sz == 8)
20165663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         gen_SEGV_if_not_16_aligned( addr );
20166663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20167663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Get the expected and new values. */
20168663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( expdHi64, getIReg64(R_RDX) );
20169663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( expdLo64, getIReg64(R_RAX) );
20170663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20171663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* These are the correctly-sized expected and new values.
20172663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         However, we also get expdHi64/expdLo64 above as 64-bits
20173663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         regardless, because we will need them later in the 32-bit
20174663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case (paradoxically). */
20175663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( expdHi, sz==4 ? unop(Iop_64to32, mkexpr(expdHi64))
20176663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            : mkexpr(expdHi64) );
20177663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( expdLo, sz==4 ? unop(Iop_64to32, mkexpr(expdLo64))
20178663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            : mkexpr(expdLo64) );
20179663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( dataHi, sz==4 ? getIReg32(R_RCX) : getIReg64(R_RCX) );
20180663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( dataLo, sz==4 ? getIReg32(R_RBX) : getIReg64(R_RBX) );
20181663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20182663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Do the DCAS */
20183663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      stmt( IRStmt_CAS(
20184663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               mkIRCAS( oldHi, oldLo,
20185663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        Iend_LE, mkexpr(addr),
20186663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        mkexpr(expdHi), mkexpr(expdLo),
20187663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        mkexpr(dataHi), mkexpr(dataLo)
20188663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            )));
20189663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20190663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* success when oldHi:oldLo == expdHi:expdLo */
20191663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( success,
20192663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              binop(opCasCmpEQ,
20193663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    binop(opOR,
20194663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          binop(opXOR, mkexpr(oldHi), mkexpr(expdHi)),
20195663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          binop(opXOR, mkexpr(oldLo), mkexpr(expdLo))
20196663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    ),
20197663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    zero
20198663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              ));
20199663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20200663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* If the DCAS is successful, that is to say oldHi:oldLo ==
20201663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         expdHi:expdLo, then put expdHi:expdLo back in RDX:RAX,
20202663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         which is where they came from originally.  Both the actual
20203663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         contents of these two regs, and any shadow values, are
20204663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         unchanged.  If the DCAS fails then we're putting into
20205663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         RDX:RAX the value seen in memory. */
20206663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Now of course there's a complication in the 32-bit case
20207663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         (bah!): if the DCAS succeeds, we need to leave RDX:RAX
20208663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         unchanged; but if we use the same scheme as in the 64-bit
20209663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case, we get hit by the standard rule that a write to the
20210663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         bottom 32 bits of an integer register zeros the upper 32
20211663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         bits.  And so the upper halves of RDX and RAX mysteriously
20212663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         become zero.  So we have to stuff back in the original
20213663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         64-bit values which we previously stashed in
20214663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         expdHi64:expdLo64, even if we're doing a cmpxchg8b. */
20215663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* It's just _so_ much fun ... */
20216663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      putIRegRDX( 8,
20217663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(success)),
20218663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                sz == 4 ? unop(Iop_32Uto64, mkexpr(oldHi))
20219663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        : mkexpr(oldHi),
20220663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                mkexpr(expdHi64)
20221663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                ));
20222663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      putIRegRAX( 8,
20223663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(success)),
20224663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                sz == 4 ? unop(Iop_32Uto64, mkexpr(oldLo))
20225663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        : mkexpr(oldLo),
20226663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                mkexpr(expdLo64)
20227663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                ));
20228663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20229663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Copy the success bit into the Z flag and leave the others
20230663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         unchanged */
20231663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( flags_old, widenUto64(mk_amd64g_calculate_rflags_all()));
20232663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(
20233663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         flags_new,
20234663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         binop(Iop_Or64,
20235663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               binop(Iop_And64, mkexpr(flags_old),
20236663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                mkU64(~AMD64G_CC_MASK_Z)),
20237663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               binop(Iop_Shl64,
20238663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     binop(Iop_And64,
20239663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           unop(Iop_1Uto64, mkexpr(success)), mkU64(1)),
20240663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     mkU8(AMD64G_CC_SHIFT_Z)) ));
20241663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20242663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      stmt( IRStmt_Put( OFFB_CC_OP,   mkU64(AMD64G_CC_OP_COPY) ));
20243663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      stmt( IRStmt_Put( OFFB_CC_DEP1, mkexpr(flags_new) ));
20244663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      stmt( IRStmt_Put( OFFB_CC_DEP2, mkU64(0) ));
20245663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Set NDEP even though it isn't used.  This makes
20246663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         redundant-PUT elimination of previous stores to this field
20247663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         work better. */
20248663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      stmt( IRStmt_Put( OFFB_CC_NDEP, mkU64(0) ));
20249663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20250663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Sheesh.  Aren't you glad it was me and not you that had to
20251663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         write and validate all this grunge? */
20252663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20253663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("cmpxchg8b %s\n", dis_buf);
20254663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
20255663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
20256663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20257663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xC8: /* BSWAP %eax */
20258663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xC9:
20259663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xCA:
20260663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xCB:
20261663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xCC:
20262663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xCD:
20263663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xCE:
20264663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xCF: /* BSWAP %edi */
20265663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2orF3(pfx)) goto decode_failure;
20266663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* According to the AMD64 docs, this insn can have size 4 or
20267663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         8. */
20268663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (sz == 4) {
20269663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         t1 = newTemp(Ity_I32);
20270663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( t1, getIRegRexB(4, pfx, opc-0xC8) );
20271663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         t2 = math_BSWAP( t1, Ity_I32 );
20272663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putIRegRexB(4, pfx, opc-0xC8, mkexpr(t2));
20273663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("bswapl %s\n", nameIRegRexB(4, pfx, opc-0xC8));
20274663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return delta;
20275663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
20276663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (sz == 8) {
20277663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         t1 = newTemp(Ity_I64);
20278663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         t2 = newTemp(Ity_I64);
20279663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( t1, getIRegRexB(8, pfx, opc-0xC8) );
20280663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         t2 = math_BSWAP( t1, Ity_I64 );
20281663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putIRegRexB(8, pfx, opc-0xC8, mkexpr(t2));
20282663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("bswapq %s\n", nameIRegRexB(8, pfx, opc-0xC8));
20283663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return delta;
20284663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
20285663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      goto decode_failure;
20286663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20287663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   default:
20288663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
20289663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20290663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } /* first switch */
20291663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20292663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20293663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* =-=-=-=-=-=-=-=-= MMXery =-=-=-=-=-=-=-=-= */
20294663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* In the second switch, pick off MMX insns. */
20295663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20296663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (!have66orF2orF3(pfx)) {
20297663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* So there's no SIMD prefix. */
20298663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20299663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(sz == 4 || sz == 8);
20300663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20301663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (opc) { /* second switch */
20302663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20303663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x71:
20304663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x72:
20305663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x73: /* PSLLgg/PSRAgg/PSRLgg mmxreg by imm8 */
20306663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20307663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x6E: /* MOVD (src)ireg-or-mem, (dst)mmxreg */
20308663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x7E: /* MOVD (src)mmxreg, (dst)ireg-or-mem */
20309663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x7F: /* MOVQ (src)mmxreg, (dst)mmxreg-or-mem */
20310663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x6F: /* MOVQ (src)mmxreg-or-mem, (dst)mmxreg */
20311663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20312663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0xFC:
20313663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0xFD:
20314663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0xFE: /* PADDgg (src)mmxreg-or-mem, (dst)mmxreg */
20315663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20316663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0xEC:
20317663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0xED: /* PADDSgg (src)mmxreg-or-mem, (dst)mmxreg */
20318663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20319663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0xDC:
20320663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0xDD: /* PADDUSgg (src)mmxreg-or-mem, (dst)mmxreg */
20321663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20322663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0xF8:
20323663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0xF9:
20324663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0xFA: /* PSUBgg (src)mmxreg-or-mem, (dst)mmxreg */
20325663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20326663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0xE8:
20327663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0xE9: /* PSUBSgg (src)mmxreg-or-mem, (dst)mmxreg */
20328663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20329663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0xD8:
20330663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0xD9: /* PSUBUSgg (src)mmxreg-or-mem, (dst)mmxreg */
20331663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20332663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0xE5: /* PMULHW (src)mmxreg-or-mem, (dst)mmxreg */
20333663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0xD5: /* PMULLW (src)mmxreg-or-mem, (dst)mmxreg */
20334663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20335663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0xF5: /* PMADDWD (src)mmxreg-or-mem, (dst)mmxreg */
20336663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20337663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x74:
20338663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x75:
20339663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x76: /* PCMPEQgg (src)mmxreg-or-mem, (dst)mmxreg */
20340663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20341663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x64:
20342663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x65:
20343663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x66: /* PCMPGTgg (src)mmxreg-or-mem, (dst)mmxreg */
20344663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20345663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x6B: /* PACKSSDW (src)mmxreg-or-mem, (dst)mmxreg */
20346663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x63: /* PACKSSWB (src)mmxreg-or-mem, (dst)mmxreg */
20347663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x67: /* PACKUSWB (src)mmxreg-or-mem, (dst)mmxreg */
20348663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20349663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x68:
20350663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x69:
20351663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x6A: /* PUNPCKHgg (src)mmxreg-or-mem, (dst)mmxreg */
20352663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20353663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x60:
20354663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x61:
20355663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0x62: /* PUNPCKLgg (src)mmxreg-or-mem, (dst)mmxreg */
20356663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20357663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0xDB: /* PAND (src)mmxreg-or-mem, (dst)mmxreg */
20358663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0xDF: /* PANDN (src)mmxreg-or-mem, (dst)mmxreg */
20359663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0xEB: /* POR (src)mmxreg-or-mem, (dst)mmxreg */
20360663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0xEF: /* PXOR (src)mmxreg-or-mem, (dst)mmxreg */
20361663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20362663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0xF1: /* PSLLgg (src)mmxreg-or-mem, (dst)mmxreg */
20363663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0xF2:
20364663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0xF3:
20365663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20366663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0xD1: /* PSRLgg (src)mmxreg-or-mem, (dst)mmxreg */
20367663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0xD2:
20368663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0xD3:
20369663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20370663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0xE1: /* PSRAgg (src)mmxreg-or-mem, (dst)mmxreg */
20371663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0xE2: {
20372663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Bool decode_OK = False;
20373663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_MMX ( &decode_OK, vbi, pfx, sz, deltaIN );
20374663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (decode_OK)
20375663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return delta;
20376663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_failure;
20377663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
20378663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20379663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default:
20380663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
20381663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      } /* second switch */
20382663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20383663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
20384663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20385663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* A couple of MMX corner cases */
20386663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (opc == 0x0E/* FEMMS */ || opc == 0x77/* EMMS */) {
20387663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (sz != 4)
20388663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_failure;
20389663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      do_EMMS_preamble();
20390663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("{f}emms\n");
20391663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return delta;
20392663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
20393663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20394663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* =-=-=-=-=-=-=-=-= SSE2ery =-=-=-=-=-=-=-=-= */
20395663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Perhaps it's an SSE or SSE2 instruction.  We can try this
20396663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      without checking the guest hwcaps because SSE2 is a baseline
20397663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      facility in 64 bit mode. */
20398663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   {
20399663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Bool decode_OK = False;
20400663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_ESC_0F__SSE2 ( &decode_OK, vbi, pfx, sz, deltaIN, dres );
20401663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (decode_OK)
20402663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return delta;
20403663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
20404663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20405663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* =-=-=-=-=-=-=-=-= SSE3ery =-=-=-=-=-=-=-=-= */
20406663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Perhaps it's a SSE3 instruction.  FIXME: check guest hwcaps
20407663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      first. */
20408663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   {
20409663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Bool decode_OK = False;
20410663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_ESC_0F__SSE3 ( &decode_OK, vbi, pfx, sz, deltaIN );
20411663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (decode_OK)
20412663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return delta;
20413663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
20414663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20415663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* =-=-=-=-=-=-=-=-= SSE4ery =-=-=-=-=-=-=-=-= */
20416663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Perhaps it's a SSE4 instruction.  FIXME: check guest hwcaps
20417663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      first. */
20418663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   {
20419663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Bool decode_OK = False;
20420663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_ESC_0F__SSE4 ( &decode_OK,
20421663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                 archinfo, vbi, pfx, sz, deltaIN );
20422663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (decode_OK)
20423663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return delta;
20424663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
20425663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20426663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  decode_failure:
20427663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return deltaIN; /* fail */
20428663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
20429663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20430663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20431663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*------------------------------------------------------------*/
20432663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---                                                      ---*/
20433663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*--- Top-level post-escape decoders: dis_ESC_0F38         ---*/
20434663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---                                                      ---*/
20435663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*------------------------------------------------------------*/
20436663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20437663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng__attribute__((noinline))
20438663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic
20439663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengLong dis_ESC_0F38 (
20440663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        /*MB_OUT*/DisResult* dres,
20441663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        Bool         (*resteerOkFn) ( /*opaque*/void*, Addr64 ),
20442663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        Bool         resteerCisOk,
20443663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        void*        callback_opaque,
20444663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        VexArchInfo* archinfo,
20445663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        VexAbiInfo*  vbi,
20446663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        Prefix pfx, Int sz, Long deltaIN
20447663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     )
20448663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
20449663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Long   delta = deltaIN;
20450663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  opc   = getUChar(delta);
20451663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   delta++;
20452663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (opc) {
20453663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20454663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xF0:   /* 0F 38 F0 = MOVBE m16/32/64(E), r16/32/64(G) */
20455663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xF1: { /* 0F 38 F1 = MOVBE r16/32/64(G), m16/32/64(E) */
20456663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (!haveF2orF3(pfx) && !haveVEX(pfx)
20457663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && (sz == 2 || sz == 4 || sz == 8)) {
20458663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp addr  = IRTemp_INVALID;
20459663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm = 0;
20460663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int    alen  = 0;
20461663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HChar  dis_buf[50];
20462663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
20463663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) break;
20464663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
20465663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta += alen;
20466663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRType ty = szToITy(sz);
20467663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp src = newTemp(ty);
20468663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (opc == 0xF0) { /* LOAD */
20469663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(src, loadLE(ty, mkexpr(addr)));
20470663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            IRTemp dst = math_BSWAP(src, ty);
20471663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putIRegG(sz, pfx, modrm, mkexpr(dst));
20472663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movbe %s,%s\n", dis_buf, nameIRegG(sz, pfx, modrm));
20473663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else { /* STORE */
20474663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(src, getIRegG(sz, pfx, modrm));
20475663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            IRTemp dst = math_BSWAP(src, ty);
20476663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            storeLE(mkexpr(addr), mkexpr(dst));
20477663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("movbe %s,%s\n", nameIRegG(sz, pfx, modrm), dis_buf);
20478663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
20479663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return delta;
20480663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
20481663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* else fall through; maybe one of the decoders below knows what
20482663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         it is. */
20483663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
20484663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
20485663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20486663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   default:
20487663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
20488663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20489663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
20490663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20491663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* =-=-=-=-=-=-=-=-= SSSE3ery =-=-=-=-=-=-=-=-= */
20492663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Perhaps it's an SSSE3 instruction.  FIXME: consult guest hwcaps
20493663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      rather than proceeding indiscriminately. */
20494663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   {
20495663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Bool decode_OK = False;
20496663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_ESC_0F38__SupSSE3 ( &decode_OK, vbi, pfx, sz, deltaIN );
20497663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (decode_OK)
20498663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return delta;
20499663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
20500663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20501663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* =-=-=-=-=-=-=-=-= SSE4ery =-=-=-=-=-=-=-=-= */
20502663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Perhaps it's an SSE4 instruction.  FIXME: consult guest hwcaps
20503663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      rather than proceeding indiscriminately. */
20504663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   {
20505663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Bool decode_OK = False;
20506663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_ESC_0F38__SSE4 ( &decode_OK, vbi, pfx, sz, deltaIN );
20507663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (decode_OK)
20508663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return delta;
20509663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
20510663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20511663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  /*decode_failure:*/
20512663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return deltaIN; /* fail */
20513663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
20514663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20515663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20516663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*------------------------------------------------------------*/
20517663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---                                                      ---*/
20518663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*--- Top-level post-escape decoders: dis_ESC_0F3A         ---*/
20519663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---                                                      ---*/
20520663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*------------------------------------------------------------*/
20521663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20522663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng__attribute__((noinline))
20523663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic
20524663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengLong dis_ESC_0F3A (
20525663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        /*MB_OUT*/DisResult* dres,
20526663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        Bool         (*resteerOkFn) ( /*opaque*/void*, Addr64 ),
20527663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        Bool         resteerCisOk,
20528663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        void*        callback_opaque,
20529663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        VexArchInfo* archinfo,
20530663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        VexAbiInfo*  vbi,
20531663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        Prefix pfx, Int sz, Long deltaIN
20532663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     )
20533663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
20534663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Long   delta = deltaIN;
20535663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  opc   = getUChar(delta);
20536663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   delta++;
20537663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (opc) {
20538663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20539663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   default:
20540663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
20541663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20542663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
20543663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20544663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* =-=-=-=-=-=-=-=-= SSSE3ery =-=-=-=-=-=-=-=-= */
20545663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Perhaps it's an SSSE3 instruction.  FIXME: consult guest hwcaps
20546663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      rather than proceeding indiscriminately. */
20547663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   {
20548663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Bool decode_OK = False;
20549663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_ESC_0F3A__SupSSE3 ( &decode_OK, vbi, pfx, sz, deltaIN );
20550663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (decode_OK)
20551663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return delta;
20552663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
20553663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20554663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* =-=-=-=-=-=-=-=-= SSE4ery =-=-=-=-=-=-=-=-= */
20555663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Perhaps it's an SSE4 instruction.  FIXME: consult guest hwcaps
20556663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      rather than proceeding indiscriminately. */
20557663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   {
20558663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Bool decode_OK = False;
20559663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = dis_ESC_0F3A__SSE4 ( &decode_OK, vbi, pfx, sz, deltaIN );
20560663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (decode_OK)
20561663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return delta;
20562663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
20563663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20564663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return deltaIN; /* fail */
20565663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
20566663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20567663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20568663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*------------------------------------------------------------*/
20569663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---                                                      ---*/
20570663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*--- Top-level post-escape decoders: dis_ESC_0F__VEX      ---*/
20571663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---                                                      ---*/
20572663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*------------------------------------------------------------*/
20573663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20574663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* FIXME: common up with the _256_ version below? */
20575663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic
20576663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengLong dis_VEX_NDS_128_AnySimdPfx_0F_WIG (
20577663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        /*OUT*/Bool* uses_vvvv, VexAbiInfo* vbi,
20578663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        Prefix pfx, Long delta, HChar* name,
20579663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        /* The actual operation.  Use either 'op' or 'opfn',
20580663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           but not both. */
20581663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        IROp op, IRTemp(*opFn)(IRTemp,IRTemp),
20582663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        Bool invertLeftArg,
20583663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        Bool swapArgs
20584663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     )
20585663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
20586663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm = getUChar(delta);
20587663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rD    = gregOfRexRM(pfx, modrm);
20588663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rSL   = getVexNvvvv(pfx);
20589663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp tSL   = newTemp(Ity_V128);
20590663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp tSR   = newTemp(Ity_V128);
20591663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr  = IRTemp_INVALID;
20592663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
20593663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen  = 0;
20594663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(0==getVexL(pfx)/*128*/ && 0==getRexW(pfx)/*WIG?*/);
20595663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20596663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(tSL, invertLeftArg ? unop(Iop_NotV128, getXMMReg(rSL))
20597663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             : getXMMReg(rSL));
20598663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20599663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (epartIsReg(modrm)) {
20600663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt rSR = eregOfRexRM(pfx, modrm);
20601663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1;
20602663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(tSR, getXMMReg(rSR));
20603663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%s %s,%s,%s\n",
20604663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          name, nameXMMReg(rSR), nameXMMReg(rSL), nameXMMReg(rD));
20605663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
20606663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 0 );
20607663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen;
20608663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(tSR, loadLE(Ity_V128, mkexpr(addr)));
20609663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%s %s,%s,%s\n",
20610663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          name, dis_buf, nameXMMReg(rSL), nameXMMReg(rD));
20611663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
20612663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20613663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp res = IRTemp_INVALID;
20614663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (op != Iop_INVALID) {
20615663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(opFn == NULL);
20616663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      res = newTemp(Ity_V128);
20617663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(res, swapArgs ? binop(op, mkexpr(tSR), mkexpr(tSL))
20618663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           : binop(op, mkexpr(tSL), mkexpr(tSR)));
20619663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
20620663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(opFn != NULL);
20621663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      res = swapArgs ? opFn(tSR, tSL) : opFn(tSL, tSR);
20622663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
20623663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20624663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putYMMRegLoAndZU(rD, mkexpr(res));
20625663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20626663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *uses_vvvv = True;
20627663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
20628663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
20629663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20630663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20631663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Handle a VEX_NDS_128_66_0F_WIG (3-addr) insn, with a simple IROp
20632663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   for the operation, no inversion of the left arg, and no swapping of
20633663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   args. */
20634663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic
20635663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengLong dis_VEX_NDS_128_AnySimdPfx_0F_WIG_simple (
20636663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        /*OUT*/Bool* uses_vvvv, VexAbiInfo* vbi,
20637663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        Prefix pfx, Long delta, HChar* name,
20638663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        IROp op
20639663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     )
20640663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
20641663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return dis_VEX_NDS_128_AnySimdPfx_0F_WIG(
20642663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             uses_vvvv, vbi, pfx, delta, name, op, NULL, False, False);
20643663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
20644663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20645663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20646663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Handle a VEX_NDS_128_66_0F_WIG (3-addr) insn, using the given IR
20647663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   generator to compute the result, no inversion of the left
20648663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   arg, and no swapping of args. */
20649663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic
20650663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengLong dis_VEX_NDS_128_AnySimdPfx_0F_WIG_complex (
20651663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        /*OUT*/Bool* uses_vvvv, VexAbiInfo* vbi,
20652663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        Prefix pfx, Long delta, HChar* name,
20653663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        IRTemp(*opFn)(IRTemp,IRTemp)
20654663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     )
20655663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
20656663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return dis_VEX_NDS_128_AnySimdPfx_0F_WIG(
20657663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             uses_vvvv, vbi, pfx, delta, name,
20658663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             Iop_INVALID, opFn, False, False );
20659663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
20660663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20661663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20662663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Vector by scalar shift of V by the amount specified at the bottom
20663663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   of E. */
20664663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic ULong dis_AVX128_shiftV_byE ( VexAbiInfo* vbi,
20665663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                     Prefix pfx, Long delta,
20666663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                     HChar* opname, IROp op )
20667663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
20668663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar   dis_buf[50];
20669663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int     alen, size;
20670663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp  addr;
20671663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Bool    shl, shr, sar;
20672663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar   modrm = getUChar(delta);
20673663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt    rG    = gregOfRexRM(pfx,modrm);
20674663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt    rV    = getVexNvvvv(pfx);;
20675663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp  g0    = newTemp(Ity_V128);
20676663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp  g1    = newTemp(Ity_V128);
20677663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp  amt   = newTemp(Ity_I64);
20678663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp  amt8  = newTemp(Ity_I8);
20679663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (epartIsReg(modrm)) {
20680663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt rE = eregOfRexRM(pfx,modrm);
20681663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( amt, getXMMRegLane64(rE, 0) );
20682663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%s %s,%s,%s\n", opname, nameXMMReg(rE),
20683663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          nameXMMReg(rV), nameXMMReg(rG) );
20684663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta++;
20685663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
20686663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
20687663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( amt, loadLE(Ity_I64, mkexpr(addr)) );
20688663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%s %s,%s,%s\n", opname, dis_buf, nameXMMReg(rV), nameXMMReg(rG) );
20689663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen;
20690663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
20691663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( g0, getXMMReg(rV) );
20692663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( amt8, unop(Iop_64to8, mkexpr(amt)) );
20693663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20694663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   shl = shr = sar = False;
20695663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   size = 0;
20696663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (op) {
20697663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_ShlN16x8: shl = True; size = 32; break;
20698663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_ShlN32x4: shl = True; size = 32; break;
20699663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_ShlN64x2: shl = True; size = 64; break;
20700663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_SarN16x8: sar = True; size = 16; break;
20701663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_SarN32x4: sar = True; size = 32; break;
20702663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_ShrN16x8: shr = True; size = 16; break;
20703663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_ShrN32x4: shr = True; size = 32; break;
20704663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_ShrN64x2: shr = True; size = 64; break;
20705663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default: vassert(0);
20706663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
20707663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20708663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (shl || shr) {
20709663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     assign(
20710663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        g1,
20711663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        IRExpr_Mux0X(
20712663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           unop(Iop_1Uto8,
20713663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                binop(Iop_CmpLT64U, mkexpr(amt), mkU64(size))),
20714663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           mkV128(0x0000),
20715663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           binop(op, mkexpr(g0), mkexpr(amt8))
20716663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        )
20717663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     );
20718663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else
20719663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (sar) {
20720663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     assign(
20721663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        g1,
20722663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        IRExpr_Mux0X(
20723663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           unop(Iop_1Uto8,
20724663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                binop(Iop_CmpLT64U, mkexpr(amt), mkU64(size))),
20725663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           binop(op, mkexpr(g0), mkU8(size-1)),
20726663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           binop(op, mkexpr(g0), mkexpr(amt8))
20727663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        )
20728663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     );
20729663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
20730663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(0);
20731663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
20732663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20733663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putYMMRegLoAndZU( rG, mkexpr(g1) );
20734663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
20735663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
20736663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20737663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20738663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Vector by scalar shift of E into V, by an immediate byte.  Modified
20739663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   version of dis_SSE_shiftE_imm. */
20740663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic
20741663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengLong dis_AVX128_shiftE_to_V_imm( Prefix pfx,
20742663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                 Long delta, HChar* opname, IROp op )
20743663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
20744663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Bool    shl, shr, sar;
20745663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar   rm   = getUChar(delta);
20746663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp  e0   = newTemp(Ity_V128);
20747663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp  e1   = newTemp(Ity_V128);
20748663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt    rD   = getVexNvvvv(pfx);
20749663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar   amt, size;
20750663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(epartIsReg(rm));
20751663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(gregLO3ofRM(rm) == 2
20752663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           || gregLO3ofRM(rm) == 4 || gregLO3ofRM(rm) == 6);
20753663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   amt = getUChar(delta+1);
20754663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   delta += 2;
20755663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   DIP("%s $%d,%s,%s\n", opname,
20756663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         (Int)amt,
20757663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         nameXMMReg(eregOfRexRM(pfx,rm)),
20758663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         nameXMMReg(rD));
20759663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( e0, getXMMReg(eregOfRexRM(pfx,rm)) );
20760663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20761663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   shl = shr = sar = False;
20762663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   size = 0;
20763663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (op) {
20764663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_ShlN16x8: shl = True; size = 16; break;
20765663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_ShlN32x4: shl = True; size = 32; break;
20766663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_ShlN64x2: shl = True; size = 64; break;
20767663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_SarN16x8: sar = True; size = 16; break;
20768663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_SarN32x4: sar = True; size = 32; break;
20769663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_ShrN16x8: shr = True; size = 16; break;
20770663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_ShrN32x4: shr = True; size = 32; break;
20771663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_ShrN64x2: shr = True; size = 64; break;
20772663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default: vassert(0);
20773663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
20774663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20775663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (shl || shr) {
20776663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     assign( e1, amt >= size
20777663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    ? mkV128(0x0000)
20778663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    : binop(op, mkexpr(e0), mkU8(amt))
20779663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     );
20780663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else
20781663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (sar) {
20782663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     assign( e1, amt >= size
20783663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    ? binop(op, mkexpr(e0), mkU8(size-1))
20784663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    : binop(op, mkexpr(e0), mkU8(amt))
20785663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     );
20786663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
20787663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(0);
20788663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
20789663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20790663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putYMMRegLoAndZU( rD, mkexpr(e1) );
20791663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
20792663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
20793663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20794663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20795663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Lower 64-bit lane only AVX128 binary operation:
20796663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   G[63:0]    = V[63:0] `op` E[63:0]
20797663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   G[127:64]  = V[127:64]
20798663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   G[255:128] = 0.
20799663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   The specified op must be of the 64F0x2 kind, so that it
20800663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   copies the upper half of the left operand to the result.
20801663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng*/
20802663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_AVX128_E_V_to_G_lo64 ( /*OUT*/Bool* uses_vvvv,
20803663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                       VexAbiInfo* vbi,
20804663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                       Prefix pfx, Long delta,
20805663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                       HChar* opname, IROp op )
20806663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
20807663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar   dis_buf[50];
20808663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int     alen;
20809663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp  addr;
20810663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar   rm    = getUChar(delta);
20811663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt    rG    = gregOfRexRM(pfx,rm);
20812663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt    rV    = getVexNvvvv(pfx);
20813663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRExpr* vpart = getXMMReg(rV);
20814663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (epartIsReg(rm)) {
20815663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt rE = eregOfRexRM(pfx,rm);
20816663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      putXMMReg( rG, binop(op, vpart, getXMMReg(rE)) );
20817663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%s %s,%s,%s\n", opname,
20818663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          nameXMMReg(rE), nameXMMReg(rV), nameXMMReg(rG));
20819663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = delta+1;
20820663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
20821663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* We can only do a 64-bit memory read, so the upper half of the
20822663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         E operand needs to be made simply of zeroes. */
20823663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRTemp epart = newTemp(Ity_V128);
20824663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
20825663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( epart, unop( Iop_64UtoV128,
20826663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           loadLE(Ity_I64, mkexpr(addr))) );
20827663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      putXMMReg( rG, binop(op, vpart, mkexpr(epart)) );
20828663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%s %s,%s,%s\n", opname,
20829663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          dis_buf, nameXMMReg(rV), nameXMMReg(rG));
20830663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = delta+alen;
20831663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
20832663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putYMMRegLane128( rG, 1, mkV128(0) );
20833663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *uses_vvvv = True;
20834663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
20835663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
20836663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20837663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20838663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Lower 64-bit lane only AVX128 unary operation:
20839663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   G[63:0]    = op(E[63:0])
20840663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   G[127:64]  = V[127:64]
20841663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   G[255:128] = 0
20842663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   The specified op must be of the 64F0x2 kind, so that it
20843663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   copies the upper half of the operand to the result.
20844663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng*/
20845663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_AVX128_E_V_to_G_lo64_unary ( /*OUT*/Bool* uses_vvvv,
20846663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                             VexAbiInfo* vbi,
20847663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                             Prefix pfx, Long delta,
20848663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                             HChar* opname, IROp op )
20849663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
20850663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar   dis_buf[50];
20851663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int     alen;
20852663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp  addr;
20853663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar   rm  = getUChar(delta);
20854663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt    rG  = gregOfRexRM(pfx,rm);
20855663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt    rV  = getVexNvvvv(pfx);
20856663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp  e64 = newTemp(Ity_I64);
20857663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20858663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Fetch E[63:0] */
20859663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (epartIsReg(rm)) {
20860663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt rE = eregOfRexRM(pfx,rm);
20861663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(e64, getXMMRegLane64(rE, 0));
20862663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%s %s,%s,%s\n", opname,
20863663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          nameXMMReg(rE), nameXMMReg(rV), nameXMMReg(rG));
20864663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1;
20865663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
20866663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
20867663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(e64, loadLE(Ity_I64, mkexpr(addr)));
20868663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%s %s,%s,%s\n", opname,
20869663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          dis_buf, nameXMMReg(rV), nameXMMReg(rG));
20870663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen;
20871663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
20872663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20873663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Create a value 'arg' as V[127:64]++E[63:0] */
20874663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp arg = newTemp(Ity_V128);
20875663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(arg,
20876663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          binop(Iop_SetV128lo64,
20877663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                getXMMReg(rV), mkexpr(e64)));
20878663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* and apply op to it */
20879663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putYMMRegLoAndZU( rG, unop(op, mkexpr(arg)) );
20880663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *uses_vvvv = True;
20881663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
20882663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
20883663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20884663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20885663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Lower 32-bit lane only AVX128 unary operation:
20886663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   G[31:0]    = op(E[31:0])
20887663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   G[127:32]  = V[127:32]
20888663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   G[255:128] = 0
20889663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   The specified op must be of the 32F0x4 kind, so that it
20890663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   copies the upper 3/4 of the operand to the result.
20891663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng*/
20892663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_AVX128_E_V_to_G_lo32_unary ( /*OUT*/Bool* uses_vvvv,
20893663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                             VexAbiInfo* vbi,
20894663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                             Prefix pfx, Long delta,
20895663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                             HChar* opname, IROp op )
20896663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
20897663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar   dis_buf[50];
20898663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int     alen;
20899663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp  addr;
20900663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar   rm  = getUChar(delta);
20901663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt    rG  = gregOfRexRM(pfx,rm);
20902663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt    rV  = getVexNvvvv(pfx);
20903663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp  e32 = newTemp(Ity_I32);
20904663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20905663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Fetch E[31:0] */
20906663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (epartIsReg(rm)) {
20907663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt rE = eregOfRexRM(pfx,rm);
20908663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(e32, getXMMRegLane32(rE, 0));
20909663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%s %s,%s,%s\n", opname,
20910663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          nameXMMReg(rE), nameXMMReg(rV), nameXMMReg(rG));
20911663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1;
20912663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
20913663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
20914663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(e32, loadLE(Ity_I32, mkexpr(addr)));
20915663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%s %s,%s,%s\n", opname,
20916663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          dis_buf, nameXMMReg(rV), nameXMMReg(rG));
20917663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen;
20918663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
20919663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20920663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Create a value 'arg' as V[127:32]++E[31:0] */
20921663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp arg = newTemp(Ity_V128);
20922663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(arg,
20923663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          binop(Iop_SetV128lo32,
20924663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                getXMMReg(rV), mkexpr(e32)));
20925663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* and apply op to it */
20926663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putYMMRegLoAndZU( rG, unop(op, mkexpr(arg)) );
20927663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *uses_vvvv = True;
20928663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
20929663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
20930663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20931663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20932663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Lower 32-bit lane only AVX128 binary operation:
20933663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   G[31:0]    = V[31:0] `op` E[31:0]
20934663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   G[127:32]  = V[127:32]
20935663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   G[255:128] = 0.
20936663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   The specified op must be of the 32F0x4 kind, so that it
20937663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   copies the upper 3/4 of the left operand to the result.
20938663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng*/
20939663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_AVX128_E_V_to_G_lo32 ( /*OUT*/Bool* uses_vvvv,
20940663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                       VexAbiInfo* vbi,
20941663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                       Prefix pfx, Long delta,
20942663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                       HChar* opname, IROp op )
20943663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
20944663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar   dis_buf[50];
20945663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int     alen;
20946663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp  addr;
20947663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar   rm    = getUChar(delta);
20948663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt    rG    = gregOfRexRM(pfx,rm);
20949663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt    rV    = getVexNvvvv(pfx);
20950663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRExpr* vpart = getXMMReg(rV);
20951663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (epartIsReg(rm)) {
20952663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt rE = eregOfRexRM(pfx,rm);
20953663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      putXMMReg( rG, binop(op, vpart, getXMMReg(rE)) );
20954663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%s %s,%s,%s\n", opname,
20955663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          nameXMMReg(rE), nameXMMReg(rV), nameXMMReg(rG));
20956663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = delta+1;
20957663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
20958663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* We can only do a 32-bit memory read, so the upper 3/4 of the
20959663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         E operand needs to be made simply of zeroes. */
20960663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRTemp epart = newTemp(Ity_V128);
20961663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
20962663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( epart, unop( Iop_32UtoV128,
20963663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           loadLE(Ity_I32, mkexpr(addr))) );
20964663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      putXMMReg( rG, binop(op, vpart, mkexpr(epart)) );
20965663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%s %s,%s,%s\n", opname,
20966663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          dis_buf, nameXMMReg(rV), nameXMMReg(rG));
20967663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta = delta+alen;
20968663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
20969663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putYMMRegLane128( rG, 1, mkV128(0) );
20970663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *uses_vvvv = True;
20971663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
20972663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
20973663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20974663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20975663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* All-lanes AVX128 binary operation:
20976663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   G[127:0]   = V[127:0] `op` E[127:0]
20977663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   G[255:128] = 0.
20978663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng*/
20979663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_AVX128_E_V_to_G ( /*OUT*/Bool* uses_vvvv,
20980663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  VexAbiInfo* vbi,
20981663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  Prefix pfx, Long delta,
20982663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  HChar* opname, IROp op )
20983663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
20984663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return dis_VEX_NDS_128_AnySimdPfx_0F_WIG(
20985663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             uses_vvvv, vbi, pfx, delta, opname, op,
20986663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             NULL, False/*!invertLeftArg*/, False/*!swapArgs*/
20987663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   );
20988663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
20989663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20990663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20991663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Handles AVX128 32F/64F comparisons.  A derivative of
20992663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   dis_SSEcmp_E_to_G.  It can fail, in which case it returns the
20993663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   original delta to indicate failure. */
20994663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic
20995663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengLong dis_AVX128_cmp_V_E_to_G ( /*OUT*/Bool* uses_vvvv,
20996663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               VexAbiInfo* vbi,
20997663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               Prefix pfx, Long delta,
20998663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               HChar* opname, Bool all_lanes, Int sz )
20999663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
21000663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(sz == 4 || sz == 8);
21001663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Long    deltaIN = delta;
21002663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar   dis_buf[50];
21003663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int     alen;
21004663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt    imm8;
21005663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp  addr;
21006663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Bool    preSwap = False;
21007663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IROp    op      = Iop_INVALID;
21008663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Bool    postNot = False;
21009663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp  plain   = newTemp(Ity_V128);
21010663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar   rm      = getUChar(delta);
21011663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt    rG      = gregOfRexRM(pfx, rm);
21012663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt    rV      = getVexNvvvv(pfx);
21013663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp argL     = newTemp(Ity_V128);
21014663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp argR     = newTemp(Ity_V128);
21015663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
21016663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(argL, getXMMReg(rV));
21017663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (epartIsReg(rm)) {
21018663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      imm8 = getUChar(delta+1);
21019663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Bool ok = findSSECmpOp(&preSwap, &op, &postNot, imm8, all_lanes, sz);
21020663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (!ok) return deltaIN; /* FAIL */
21021663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt rE = eregOfRexRM(pfx,rm);
21022663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(argR, getXMMReg(rE));
21023663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1+1;
21024663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%s $%d,%s,%s,%s\n",
21025663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          opname, (Int)imm8,
21026663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          nameXMMReg(rE), nameXMMReg(rV), nameXMMReg(rG));
21027663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
21028663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 1 );
21029663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      imm8 = getUChar(delta+alen);
21030663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Bool ok = findSSECmpOp(&preSwap, &op, &postNot, imm8, all_lanes, sz);
21031663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (!ok) return deltaIN; /* FAIL */
21032663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(argR,
21033663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             all_lanes   ? loadLE(Ity_V128, mkexpr(addr))
21034663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             : sz == 8   ? unop( Iop_64UtoV128, loadLE(Ity_I64, mkexpr(addr)))
21035663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             : /*sz==4*/   unop( Iop_32UtoV128, loadLE(Ity_I32, mkexpr(addr))));
21036663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen+1;
21037663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%s $%d,%s,%s,%s\n",
21038663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          opname, (Int)imm8, dis_buf, nameXMMReg(rV), nameXMMReg(rG));
21039663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
21040663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
21041663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(plain, preSwap ? binop(op, mkexpr(argR), mkexpr(argL))
21042663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         : binop(op, mkexpr(argL), mkexpr(argR)));
21043663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
21044663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (all_lanes) {
21045663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* This is simple: just invert the result, if necessary, and
21046663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         have done. */
21047663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (postNot) {
21048663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLoAndZU( rG, unop(Iop_NotV128, mkexpr(plain)) );
21049663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      } else {
21050663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLoAndZU( rG, mkexpr(plain) );
21051663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
21052663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
21053663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   else
21054663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (!preSwap) {
21055663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* More complex.  It's a one-lane-only, hence need to possibly
21056663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         invert only that one lane.  But at least the other lanes are
21057663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         correctly "in" the result, having been copied from the left
21058663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         operand (argL). */
21059663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (postNot) {
21060663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRExpr* mask = mkV128(sz==4 ? 0x000F : 0x00FF);
21061663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLoAndZU( rG, binop(Iop_XorV128, mkexpr(plain),
21062663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                                  mask) );
21063663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      } else {
21064663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLoAndZU( rG, mkexpr(plain) );
21065663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
21066663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
21067663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   else {
21068663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* This is the most complex case.  One-lane-only, but the args
21069663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         were swapped.  So we have to possibly invert the bottom lane,
21070663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         and (definitely) we have to copy the upper lane(s) from argL
21071663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         since, due to the swapping, what's currently there is from
21072663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         argR, which is not correct. */
21073663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRTemp res     = newTemp(Ity_V128);
21074663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRTemp mask    = newTemp(Ity_V128);
21075663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRTemp notMask = newTemp(Ity_V128);
21076663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(mask,    mkV128(sz==4 ? 0x000F : 0x00FF));
21077663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(notMask, mkV128(sz==4 ? 0xFFF0 : 0xFF00));
21078663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (postNot) {
21079663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(res,
21080663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                binop(Iop_OrV128,
21081663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      binop(Iop_AndV128,
21082663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            unop(Iop_NotV128, mkexpr(plain)),
21083663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            mkexpr(mask)),
21084663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      binop(Iop_AndV128, mkexpr(argL), mkexpr(notMask))));
21085663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      } else {
21086663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(res,
21087663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                binop(Iop_OrV128,
21088663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      binop(Iop_AndV128,
21089663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            mkexpr(plain),
21090663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            mkexpr(mask)),
21091663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      binop(Iop_AndV128, mkexpr(argL), mkexpr(notMask))));
21092663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
21093663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      putYMMRegLoAndZU( rG, mkexpr(res) );
21094663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
21095663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
21096663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *uses_vvvv = True;
21097663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
21098663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
21099663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
21100663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
21101663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Handles AVX256 32F/64F comparisons.  A derivative of
21102663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   dis_SSEcmp_E_to_G.  It can fail, in which case it returns the
21103663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   original delta to indicate failure. */
21104663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic
21105663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengLong dis_AVX256_cmp_V_E_to_G ( /*OUT*/Bool* uses_vvvv,
21106663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               VexAbiInfo* vbi,
21107663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               Prefix pfx, Long delta,
21108663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               HChar* opname, Int sz )
21109663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
21110663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(sz == 4 || sz == 8);
21111663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Long    deltaIN = delta;
21112663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar   dis_buf[50];
21113663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int     alen;
21114663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt    imm8;
21115663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp  addr;
21116663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Bool    preSwap = False;
21117663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IROp    op      = Iop_INVALID;
21118663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Bool    postNot = False;
21119663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp  plain   = newTemp(Ity_V256);
21120663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar   rm      = getUChar(delta);
21121663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt    rG      = gregOfRexRM(pfx, rm);
21122663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt    rV      = getVexNvvvv(pfx);
21123663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp argL     = newTemp(Ity_V256);
21124663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp argR     = newTemp(Ity_V256);
21125663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp argLhi   = IRTemp_INVALID;
21126663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp argLlo   = IRTemp_INVALID;
21127663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp argRhi   = IRTemp_INVALID;
21128663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp argRlo   = IRTemp_INVALID;
21129663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
21130663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(argL, getYMMReg(rV));
21131663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (epartIsReg(rm)) {
21132663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      imm8 = getUChar(delta+1);
21133663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Bool ok = findSSECmpOp(&preSwap, &op, &postNot, imm8,
21134663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             True/*all_lanes*/, sz);
21135663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (!ok) return deltaIN; /* FAIL */
21136663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt rE = eregOfRexRM(pfx,rm);
21137663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(argR, getYMMReg(rE));
21138663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1+1;
21139663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%s $%d,%s,%s,%s\n",
21140663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          opname, (Int)imm8,
21141663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          nameYMMReg(rE), nameYMMReg(rV), nameYMMReg(rG));
21142663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
21143663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 1 );
21144663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      imm8 = getUChar(delta+alen);
21145663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Bool ok = findSSECmpOp(&preSwap, &op, &postNot, imm8,
21146663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             True/*all_lanes*/, sz);
21147663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (!ok) return deltaIN; /* FAIL */
21148663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(argR, loadLE(Ity_V256, mkexpr(addr)) );
21149663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen+1;
21150663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%s $%d,%s,%s,%s\n",
21151663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          opname, (Int)imm8, dis_buf, nameYMMReg(rV), nameYMMReg(rG));
21152663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
21153663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
21154663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV256toV128s( preSwap ? argR : argL, &argLhi, &argLlo );
21155663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV256toV128s( preSwap ? argL : argR, &argRhi, &argRlo );
21156663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(plain, binop( Iop_V128HLtoV256,
21157663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        binop(op, mkexpr(argLhi), mkexpr(argRhi)),
21158663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        binop(op, mkexpr(argLlo), mkexpr(argRlo)) ) );
21159663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
21160663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* This is simple: just invert the result, if necessary, and
21161663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      have done. */
21162663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (postNot) {
21163663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      putYMMReg( rG, unop(Iop_NotV256, mkexpr(plain)) );
21164663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
21165663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      putYMMReg( rG, mkexpr(plain) );
21166663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
21167663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
21168663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *uses_vvvv = True;
21169663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
21170663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
21171663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
21172663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
21173663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Handles AVX128 unary E-to-G all-lanes operations. */
21174663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic
21175663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengLong dis_AVX128_E_to_G_unary ( /*OUT*/Bool* uses_vvvv,
21176663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               VexAbiInfo* vbi,
21177663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               Prefix pfx, Long delta,
21178663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               HChar* opname,
21179663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               IRTemp (*opFn)(IRTemp) )
21180663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
21181663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
21182663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen;
21183663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr;
21184663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp res  = newTemp(Ity_V128);
21185663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp arg  = newTemp(Ity_V128);
21186663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  rm   = getUChar(delta);
21187663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rG   = gregOfRexRM(pfx, rm);
21188663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (epartIsReg(rm)) {
21189663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt rE = eregOfRexRM(pfx,rm);
21190663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(arg, getXMMReg(rE));
21191663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1;
21192663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%s %s,%s\n", opname, nameXMMReg(rE), nameXMMReg(rG));
21193663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
21194663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
21195663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(arg, loadLE(Ity_V128, mkexpr(addr)));
21196663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen;
21197663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%s %s,%s\n", opname, dis_buf, nameXMMReg(rG));
21198663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
21199663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   res = opFn(arg);
21200663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putYMMRegLoAndZU( rG, mkexpr(res) );
21201663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *uses_vvvv = False;
21202663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
21203663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
21204663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
21205663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
21206663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Handles AVX128 unary E-to-G all-lanes operations. */
21207663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic
21208663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengLong dis_AVX128_E_to_G_unary_all ( /*OUT*/Bool* uses_vvvv,
21209663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   VexAbiInfo* vbi,
21210663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   Prefix pfx, Long delta,
21211663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   HChar* opname, IROp op )
21212663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
21213663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
21214663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen;
21215663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr;
21216663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp arg  = newTemp(Ity_V128);
21217663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  rm   = getUChar(delta);
21218663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rG   = gregOfRexRM(pfx, rm);
21219663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (epartIsReg(rm)) {
21220663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt rE = eregOfRexRM(pfx,rm);
21221663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(arg, getXMMReg(rE));
21222663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1;
21223663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%s %s,%s\n", opname, nameXMMReg(rE), nameXMMReg(rG));
21224663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
21225663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
21226663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(arg, loadLE(Ity_V128, mkexpr(addr)));
21227663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen;
21228663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%s %s,%s\n", opname, dis_buf, nameXMMReg(rG));
21229663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
21230663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putYMMRegLoAndZU( rG, unop(op, mkexpr(arg)) );
21231663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *uses_vvvv = False;
21232663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
21233663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
21234663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
21235663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
21236663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* FIXME: common up with the _128_ version above? */
21237663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic
21238663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengLong dis_VEX_NDS_256_AnySimdPfx_0F_WIG (
21239663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        /*OUT*/Bool* uses_vvvv, VexAbiInfo* vbi,
21240663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        Prefix pfx, Long delta, HChar* name,
21241663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        /* The actual operation.  Use either 'op' or 'opfn',
21242663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           but not both. */
21243663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        IROp op, IRTemp(*opFn)(IRTemp,IRTemp),
21244663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        Bool invertLeftArg,
21245663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        Bool swapArgs
21246663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     )
21247663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
21248663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm = getUChar(delta);
21249663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rD    = gregOfRexRM(pfx, modrm);
21250663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rSL   = getVexNvvvv(pfx);
21251663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp tSL   = newTemp(Ity_V256);
21252663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp tSR   = newTemp(Ity_V256);
21253663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr  = IRTemp_INVALID;
21254663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
21255663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen  = 0;
21256663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(1==getVexL(pfx)/*256*/ && 0==getRexW(pfx)/*WIG?*/);
21257663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
21258663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(tSL, invertLeftArg ? unop(Iop_NotV256, getYMMReg(rSL))
21259663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             : getYMMReg(rSL));
21260663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
21261663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (epartIsReg(modrm)) {
21262663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt rSR = eregOfRexRM(pfx, modrm);
21263663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1;
21264663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(tSR, getYMMReg(rSR));
21265663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%s %s,%s,%s\n",
21266663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          name, nameYMMReg(rSR), nameYMMReg(rSL), nameYMMReg(rD));
21267663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
21268663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 0 );
21269663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen;
21270663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(tSR, loadLE(Ity_V256, mkexpr(addr)));
21271663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%s %s,%s,%s\n",
21272663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          name, dis_buf, nameYMMReg(rSL), nameYMMReg(rD));
21273663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
21274663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
21275663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp res = IRTemp_INVALID;
21276663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (op != Iop_INVALID) {
21277663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(opFn == NULL);
21278663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      res = newTemp(Ity_V256);
21279663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(res, swapArgs ? binop(op, mkexpr(tSR), mkexpr(tSL))
21280663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           : binop(op, mkexpr(tSL), mkexpr(tSR)));
21281663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
21282663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(opFn != NULL);
21283663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      res = swapArgs ? opFn(tSR, tSL) : opFn(tSL, tSR);
21284663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
21285663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
21286663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putYMMReg(rD, mkexpr(res));
21287663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
21288663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *uses_vvvv = True;
21289663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
21290663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
21291663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
21292663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
21293663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* All-lanes AVX256 binary operation:
21294663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   G[255:0] = V[255:0] `op` E[255:0]
21295663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng*/
21296663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_AVX256_E_V_to_G ( /*OUT*/Bool* uses_vvvv,
21297663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  VexAbiInfo* vbi,
21298663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  Prefix pfx, Long delta,
21299663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  HChar* opname, IROp op )
21300663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
21301663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return dis_VEX_NDS_256_AnySimdPfx_0F_WIG(
21302663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             uses_vvvv, vbi, pfx, delta, opname, op,
21303663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             NULL, False/*!invertLeftArg*/, False/*!swapArgs*/
21304663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   );
21305663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
21306663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
21307663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
21308663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Handle a VEX_NDS_256_66_0F_WIG (3-addr) insn, using the given IR
21309663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   generator to compute the result, no inversion of the left
21310663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   arg, and no swapping of args. */
21311663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic
21312663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengLong dis_VEX_NDS_256_AnySimdPfx_0F_WIG_complex (
21313663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        /*OUT*/Bool* uses_vvvv, VexAbiInfo* vbi,
21314663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        Prefix pfx, Long delta, HChar* name,
21315663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        IRTemp(*opFn)(IRTemp,IRTemp)
21316663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     )
21317663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
21318663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return dis_VEX_NDS_256_AnySimdPfx_0F_WIG(
21319663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             uses_vvvv, vbi, pfx, delta, name,
21320663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             Iop_INVALID, opFn, False, False );
21321663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
21322663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
21323663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
21324663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Handles AVX256 unary E-to-G all-lanes operations. */
21325663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic
21326663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengLong dis_AVX256_E_to_G_unary_all ( /*OUT*/Bool* uses_vvvv,
21327663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   VexAbiInfo* vbi,
21328663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   Prefix pfx, Long delta,
21329663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   HChar* opname, IROp op )
21330663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
21331663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
21332663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen;
21333663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr;
21334663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp arg  = newTemp(Ity_V256);
21335663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  rm   = getUChar(delta);
21336663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rG   = gregOfRexRM(pfx, rm);
21337663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (epartIsReg(rm)) {
21338663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt rE = eregOfRexRM(pfx,rm);
21339663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(arg, getYMMReg(rE));
21340663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1;
21341663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%s %s,%s\n", opname, nameYMMReg(rE), nameYMMReg(rG));
21342663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
21343663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
21344663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign(arg, loadLE(Ity_V256, mkexpr(addr)));
21345663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen;
21346663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("%s %s,%s\n", opname, dis_buf, nameYMMReg(rG));
21347663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
21348663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putYMMReg( rG, unop(op, mkexpr(arg)) );
21349663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *uses_vvvv = False;
21350663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
21351663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
21352663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
21353663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
21354663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* The use of ReinterpF64asI64 is ugly.  Surely could do better if we
21355663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   had a variant of Iop_64x4toV256 that took F64s as args instead. */
21356663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_CVTDQ2PD_256 ( VexAbiInfo* vbi, Prefix pfx,
21357663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               Long delta )
21358663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
21359663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr  = IRTemp_INVALID;
21360663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen  = 0;
21361663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
21362663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm = getUChar(delta);
21363663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp sV    = newTemp(Ity_V128);
21364663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rG    = gregOfRexRM(pfx,modrm);
21365663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (epartIsReg(modrm)) {
21366663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt rE = eregOfRexRM(pfx,modrm);
21367663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( sV, getXMMReg(rE) );
21368663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1;
21369663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("vcvtdq2pd %s,%s\n", nameXMMReg(rE), nameYMMReg(rG));
21370663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
21371663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
21372663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
21373663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen;
21374663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("vcvtdq2pd %s,%s\n", dis_buf, nameYMMReg(rG) );
21375663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
21376663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp s3, s2, s1, s0;
21377663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   s3 = s2 = s1 = s0 = IRTemp_INVALID;
21378663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV128to32s( sV, &s3, &s2, &s1, &s0 );
21379663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRExpr* res
21380663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      = IRExpr_Qop(
21381663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           Iop_64x4toV256,
21382663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           unop(Iop_ReinterpF64asI64, unop(Iop_I32StoF64, mkexpr(s3))),
21383663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           unop(Iop_ReinterpF64asI64, unop(Iop_I32StoF64, mkexpr(s2))),
21384663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           unop(Iop_ReinterpF64asI64, unop(Iop_I32StoF64, mkexpr(s1))),
21385663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           unop(Iop_ReinterpF64asI64, unop(Iop_I32StoF64, mkexpr(s0)))
21386663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        );
21387663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putYMMReg(rG, res);
21388663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
21389663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
21390663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
21391663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
21392663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Long dis_CVTPD2PS_256 ( VexAbiInfo* vbi, Prefix pfx,
21393663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               Long delta )
21394663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
21395663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr  = IRTemp_INVALID;
21396663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen  = 0;
21397663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
21398663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  modrm = getUChar(delta);
21399663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt   rG    = gregOfRexRM(pfx,modrm);
21400663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp argV  = newTemp(Ity_V256);
21401663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp rmode = newTemp(Ity_I32);
21402663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (epartIsReg(modrm)) {
21403663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt rE = eregOfRexRM(pfx,modrm);
21404663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( argV, getYMMReg(rE) );
21405663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += 1;
21406663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("vcvtpd2psy %s,%s\n", nameYMMReg(rE), nameXMMReg(rG));
21407663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
21408663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
21409663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( argV, loadLE(Ity_V256, mkexpr(addr)) );
21410663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta += alen;
21411663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("vcvtpd2psy %s,%s\n", dis_buf, nameXMMReg(rG) );
21412663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
21413663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
21414663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign( rmode, get_sse_roundingmode() );
21415663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp t3, t2, t1, t0;
21416663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t3 = t2 = t1 = t0 = IRTemp_INVALID;
21417663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV256to64s( argV, &t3, &t2, &t1, &t0 );
21418663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  define CVT(_t)  binop( Iop_F64toF32, mkexpr(rmode), \
21419663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          unop(Iop_ReinterpI64asF64, mkexpr(_t)) )
21420663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putXMMRegLane32F( rG, 3, CVT(t3) );
21421663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putXMMRegLane32F( rG, 2, CVT(t2) );
21422663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putXMMRegLane32F( rG, 1, CVT(t1) );
21423663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putXMMRegLane32F( rG, 0, CVT(t0) );
21424663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  undef CVT
21425663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   putYMMRegLane128( rG, 1, mkV128(0) );
21426663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
21427663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
21428663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
21429663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
21430663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng__attribute__((noinline))
21431663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic
21432663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengLong dis_ESC_0F__VEX (
21433663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        /*MB_OUT*/DisResult* dres,
21434663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        /*OUT*/   Bool*      uses_vvvv,
21435663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        Bool         (*resteerOkFn) ( /*opaque*/void*, Addr64 ),
21436663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        Bool         resteerCisOk,
21437663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        void*        callback_opaque,
21438663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        VexArchInfo* archinfo,
21439663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        VexAbiInfo*  vbi,
21440663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        Prefix pfx, Int sz, Long deltaIN
21441663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     )
21442663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
21443663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr  = IRTemp_INVALID;
21444663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen  = 0;
21445663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
21446663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Long   delta = deltaIN;
21447663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  opc   = getUChar(delta);
21448663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   delta++;
21449663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *uses_vvvv = False;
21450663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
21451663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (opc) {
21452663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
21453663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x10:
21454663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVSD m64, xmm1 = VEX.LIG.F2.0F.WIG 10 /r */
21455663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Move 64 bits from E (mem only) to G (lo half xmm).
21456663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Bits 255-64 of the dest are zeroed out. */
21457663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2no66noF3(pfx) && !epartIsReg(getUChar(delta))) {
21458663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar modrm = getUChar(delta);
21459663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
21460663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG   = gregOfRexRM(pfx,modrm);
21461663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp z128 = newTemp(Ity_V128);
21462663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(z128, mkV128(0));
21463663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMReg( rG, mkexpr(z128) );
21464663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* FIXME: ALIGNMENT CHECK? */
21465663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMRegLane64( rG, 0, loadLE(Ity_I64, mkexpr(addr)) );
21466663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLane128( rG, 1, mkexpr(z128) );
21467663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("vmovsd %s,%s\n", dis_buf, nameXMMReg(rG));
21468663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta += alen;
21469663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
21470663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
21471663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVSD xmm3, xmm2, xmm1 = VEX.LIG.F2.0F.WIG 10 /r */
21472663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Reg form. */
21473663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2no66noF3(pfx) && epartIsReg(getUChar(delta))) {
21474663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar modrm = getUChar(delta);
21475663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rG    = gregOfRexRM(pfx, modrm);
21476663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rE    = eregOfRexRM(pfx, modrm);
21477663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rV    = getVexNvvvv(pfx);
21478663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta++;
21479663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("vmovsd %s,%s,%s\n",
21480663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             nameXMMReg(rE), nameXMMReg(rV), nameXMMReg(rG));
21481663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp res = newTemp(Ity_V128);
21482663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(res, binop(Iop_64HLtoV128,
21483663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           getXMMRegLane64(rV, 1),
21484663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           getXMMRegLane64(rE, 0)));
21485663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLoAndZU(rG, mkexpr(res));
21486663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
21487663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
21488663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
21489663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVSS m32, xmm1 = VEX.LIG.F3.0F.WIG 10 /r */
21490663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Move 32 bits from E (mem only) to G (lo half xmm).
21491663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Bits 255-32 of the dest are zeroed out. */
21492663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx) && !epartIsReg(getUChar(delta))) {
21493663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar modrm = getUChar(delta);
21494663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
21495663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG   = gregOfRexRM(pfx,modrm);
21496663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp z128 = newTemp(Ity_V128);
21497663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(z128, mkV128(0));
21498663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMReg( rG, mkexpr(z128) );
21499663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* FIXME: ALIGNMENT CHECK? */
21500663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMRegLane32( rG, 0, loadLE(Ity_I32, mkexpr(addr)) );
21501663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLane128( rG, 1, mkexpr(z128) );
21502663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("vmovss %s,%s\n", dis_buf, nameXMMReg(rG));
21503663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta += alen;
21504663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
21505663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
21506663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVSS xmm3, xmm2, xmm1 = VEX.LIG.F3.0F.WIG 10 /r */
21507663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Reg form. */
21508663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx) && epartIsReg(getUChar(delta))) {
21509663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar modrm = getUChar(delta);
21510663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rG    = gregOfRexRM(pfx, modrm);
21511663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rE    = eregOfRexRM(pfx, modrm);
21512663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rV    = getVexNvvvv(pfx);
21513663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta++;
21514663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("vmovss %s,%s,%s\n",
21515663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             nameXMMReg(rE), nameXMMReg(rV), nameXMMReg(rG));
21516663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp res = newTemp(Ity_V128);
21517663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( res, binop( Iop_64HLtoV128,
21518663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             getXMMRegLane64(rV, 1),
21519663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             binop(Iop_32HLto64,
21520663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   getXMMRegLane32(rV, 1),
21521663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   getXMMRegLane32(rE, 0)) ) );
21522663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLoAndZU(rG, mkexpr(res));
21523663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
21524663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
21525663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
21526663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVUPD xmm2/m128, xmm1 = VEX.128.66.0F.WIG 10 /r */
21527663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
21528663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar modrm = getUChar(delta);
21529663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rG    = gregOfRexRM(pfx, modrm);
21530663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
21531663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
21532663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putYMMRegLoAndZU( rG, getXMMReg( rE ));
21533663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovupd %s,%s\n", nameXMMReg(rE), nameXMMReg(rG));
21534663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
21535663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
21536663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
21537663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putYMMRegLoAndZU( rG, loadLE(Ity_V128, mkexpr(addr)) );
21538663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovupd %s,%s\n", dis_buf, nameXMMReg(rG));
21539663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
21540663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
21541663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
21542663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
21543663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVUPD ymm2/m256, ymm1 = VEX.256.66.0F.WIG 10 /r */
21544663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
21545663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar modrm = getUChar(delta);
21546663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rG    = gregOfRexRM(pfx, modrm);
21547663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
21548663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
21549663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putYMMReg( rG, getYMMReg( rE ));
21550663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovupd %s,%s\n", nameYMMReg(rE), nameYMMReg(rG));
21551663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
21552663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
21553663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
21554663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putYMMReg( rG, loadLE(Ity_V256, mkexpr(addr)) );
21555663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovupd %s,%s\n", dis_buf, nameYMMReg(rG));
21556663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
21557663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
21558663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
21559663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
21560663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVUPS xmm2/m128, xmm1 = VEX.128.0F.WIG 10 /r */
21561663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
21562663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar modrm = getUChar(delta);
21563663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rG    = gregOfRexRM(pfx, modrm);
21564663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
21565663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
21566663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putYMMRegLoAndZU( rG, getXMMReg( rE ));
21567663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovups %s,%s\n", nameXMMReg(rE), nameXMMReg(rG));
21568663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
21569663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
21570663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
21571663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putYMMRegLoAndZU( rG, loadLE(Ity_V128, mkexpr(addr)) );
21572663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovups %s,%s\n", dis_buf, nameXMMReg(rG));
21573663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
21574663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
21575663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
21576663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
21577663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVUPS ymm2/m256, ymm1 = VEX.256.0F.WIG 10 /r */
21578663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
21579663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar modrm = getUChar(delta);
21580663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rG    = gregOfRexRM(pfx, modrm);
21581663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
21582663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
21583663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putYMMReg( rG, getYMMReg( rE ));
21584663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovups %s,%s\n", nameYMMReg(rE), nameYMMReg(rG));
21585663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
21586663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
21587663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
21588663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putYMMReg( rG, loadLE(Ity_V256, mkexpr(addr)) );
21589663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovups %s,%s\n", dis_buf, nameYMMReg(rG));
21590663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
21591663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
21592663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
21593663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
21594663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
21595663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
21596663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x11:
21597663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVSD xmm1, m64 = VEX.LIG.F2.0F.WIG 11 /r */
21598663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Move 64 bits from G (low half xmm) to mem only. */
21599663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2no66noF3(pfx) && !epartIsReg(getUChar(delta))) {
21600663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar modrm = getUChar(delta);
21601663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
21602663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG   = gregOfRexRM(pfx,modrm);
21603663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* FIXME: ALIGNMENT CHECK? */
21604663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         storeLE( mkexpr(addr), getXMMRegLane64(rG, 0));
21605663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("vmovsd %s,%s\n", nameXMMReg(rG), dis_buf);
21606663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta += alen;
21607663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
21608663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
21609663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVSD xmm3, xmm2, xmm1 = VEX.LIG.F2.0F.WIG 11 /r */
21610663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Reg form. */
21611663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2no66noF3(pfx) && epartIsReg(getUChar(delta))) {
21612663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar modrm = getUChar(delta);
21613663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rG    = gregOfRexRM(pfx, modrm);
21614663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rE    = eregOfRexRM(pfx, modrm);
21615663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rV    = getVexNvvvv(pfx);
21616663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta++;
21617663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("vmovsd %s,%s,%s\n",
21618663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             nameXMMReg(rE), nameXMMReg(rV), nameXMMReg(rG));
21619663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp res = newTemp(Ity_V128);
21620663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(res, binop(Iop_64HLtoV128,
21621663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           getXMMRegLane64(rV, 1),
21622663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           getXMMRegLane64(rE, 0)));
21623663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLoAndZU(rG, mkexpr(res));
21624663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
21625663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
21626663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
21627663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVSS xmm1, m64 = VEX.LIG.F3.0F.WIG 11 /r */
21628663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Move 32 bits from G (low 1/4 xmm) to mem only. */
21629663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx) && !epartIsReg(getUChar(delta))) {
21630663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar modrm = getUChar(delta);
21631663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
21632663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG   = gregOfRexRM(pfx,modrm);
21633663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* FIXME: ALIGNMENT CHECK? */
21634663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         storeLE( mkexpr(addr), getXMMRegLane32(rG, 0));
21635663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("vmovss %s,%s\n", nameXMMReg(rG), dis_buf);
21636663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta += alen;
21637663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
21638663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
21639663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVSS xmm3, xmm2, xmm1 = VEX.LIG.F3.0F.WIG 11 /r */
21640663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Reg form. */
21641663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx) && epartIsReg(getUChar(delta))) {
21642663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar modrm = getUChar(delta);
21643663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rG    = gregOfRexRM(pfx, modrm);
21644663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rE    = eregOfRexRM(pfx, modrm);
21645663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rV    = getVexNvvvv(pfx);
21646663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta++;
21647663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("vmovss %s,%s,%s\n",
21648663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             nameXMMReg(rE), nameXMMReg(rV), nameXMMReg(rG));
21649663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp res = newTemp(Ity_V128);
21650663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( res, binop( Iop_64HLtoV128,
21651663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             getXMMRegLane64(rV, 1),
21652663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             binop(Iop_32HLto64,
21653663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   getXMMRegLane32(rV, 1),
21654663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   getXMMRegLane32(rE, 0)) ) );
21655663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLoAndZU(rG, mkexpr(res));
21656663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
21657663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
21658663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
21659663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVUPD xmm1, xmm2/m128 = VEX.128.66.0F.WIG 11 /r */
21660663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
21661663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar modrm = getUChar(delta);
21662663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rG    = gregOfRexRM(pfx,modrm);
21663663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
21664663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
21665663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putYMMRegLoAndZU( rE, getXMMReg(rG) );
21666663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovupd %s,%s\n", nameXMMReg(rG), nameXMMReg(rE));
21667663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
21668663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
21669663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
21670663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            storeLE( mkexpr(addr), getXMMReg(rG) );
21671663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovupd %s,%s\n", nameXMMReg(rG), dis_buf);
21672663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
21673663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
21674663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
21675663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
21676663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVUPD ymm1, ymm2/m256 = VEX.256.66.0F.WIG 11 /r */
21677663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
21678663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar modrm = getUChar(delta);
21679663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rG    = gregOfRexRM(pfx,modrm);
21680663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
21681663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
21682663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putYMMReg( rE, getYMMReg(rG) );
21683663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovupd %s,%s\n", nameYMMReg(rG), nameYMMReg(rE));
21684663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
21685663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
21686663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
21687663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            storeLE( mkexpr(addr), getYMMReg(rG) );
21688663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovupd %s,%s\n", nameYMMReg(rG), dis_buf);
21689663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
21690663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
21691663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
21692663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
21693663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVUPS xmm1, xmm2/m128 = VEX.128.0F.WIG 11 /r */
21694663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
21695663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar modrm = getUChar(delta);
21696663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rG    = gregOfRexRM(pfx,modrm);
21697663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
21698663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
21699663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putYMMRegLoAndZU( rE, getXMMReg(rG) );
21700663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovups %s,%s\n", nameXMMReg(rG), nameXMMReg(rE));
21701663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
21702663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
21703663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
21704663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            storeLE( mkexpr(addr), getXMMReg(rG) );
21705663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovups %s,%s\n", nameXMMReg(rG), dis_buf);
21706663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
21707663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
21708663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
21709663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
21710663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVUPS ymm1, ymm2/m256 = VEX.256.0F.WIG 11 /r */
21711663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
21712663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar modrm = getUChar(delta);
21713663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rG    = gregOfRexRM(pfx,modrm);
21714663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
21715663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
21716663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putYMMReg( rE, getYMMReg(rG) );
21717663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovups %s,%s\n", nameYMMReg(rG), nameYMMReg(rE));
21718663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
21719663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
21720663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
21721663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            storeLE( mkexpr(addr), getYMMReg(rG) );
21722663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovups %s,%s\n", nameYMMReg(rG), dis_buf);
21723663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
21724663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
21725663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
21726663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
21727663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
21728663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
21729663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x12:
21730663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVDDUP xmm2/m64, xmm1 = VEX.128.F2.0F.WIG /12 r */
21731663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2no66noF3(pfx) && 0==getVexL(pfx)/*128*/) {
21732663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_MOVDDUP_128( vbi, pfx, delta, True/*isAvx*/ );
21733663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
21734663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
21735663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVDDUP ymm2/m256, ymm1 = VEX.256.F2.0F.WIG /12 r */
21736663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2no66noF3(pfx) && 1==getVexL(pfx)/*256*/) {
21737663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_MOVDDUP_256( vbi, pfx, delta );
21738663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
21739663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
21740663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVHLPS xmm3, xmm2, xmm1 = VEX.NDS.128.0F.WIG 12 /r */
21741663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Insn only exists in reg form */
21742663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/
21743663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && epartIsReg(getUChar(delta))) {
21744663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar modrm = getUChar(delta);
21745663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rG    = gregOfRexRM(pfx, modrm);
21746663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rE    = eregOfRexRM(pfx, modrm);
21747663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rV    = getVexNvvvv(pfx);
21748663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta++;
21749663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("vmovhlps %s,%s,%s\n",
21750663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             nameXMMReg(rE), nameXMMReg(rV), nameXMMReg(rG));
21751663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp res = newTemp(Ity_V128);
21752663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(res, binop(Iop_64HLtoV128,
21753663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           getXMMRegLane64(rV, 1),
21754663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           getXMMRegLane64(rE, 1)));
21755663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLoAndZU(rG, mkexpr(res));
21756663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
21757663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
21758663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
21759663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVLPS m64, xmm1, xmm2 = VEX.NDS.128.0F.WIG 12 /r */
21760663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Insn exists only in mem form, it appears. */
21761663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVLPD m64, xmm1, xmm2 = VEX.NDS.128.66.0F.WIG 12 /r */
21762663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Insn exists only in mem form, it appears. */
21763663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if ((have66noF2noF3(pfx) || haveNo66noF2noF3(pfx))
21764663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && 0==getVexL(pfx)/*128*/ && !epartIsReg(getUChar(delta))) {
21765663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar modrm = getUChar(delta);
21766663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rG    = gregOfRexRM(pfx, modrm);
21767663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rV    = getVexNvvvv(pfx);
21768663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
21769663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta += alen;
21770663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("vmovlpd %s,%s,%s\n",
21771663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             dis_buf, nameXMMReg(rV), nameXMMReg(rG));
21772663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp res = newTemp(Ity_V128);
21773663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(res, binop(Iop_64HLtoV128,
21774663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           getXMMRegLane64(rV, 1),
21775663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           loadLE(Ity_I64, mkexpr(addr))));
21776663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLoAndZU(rG, mkexpr(res));
21777663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
21778663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
21779663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
21780663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVSLDUP xmm2/m128, xmm1 = VEX.NDS.128.F3.0F.WIG 12 /r */
21781663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx) && 0==getVexL(pfx)/*128*/) {
21782663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_MOVSxDUP_128( vbi, pfx, delta, True/*isAvx*/,
21783663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   True/*isL*/ );
21784663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
21785663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
21786663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVSLDUP ymm2/m256, ymm1 = VEX.NDS.256.F3.0F.WIG 12 /r */
21787663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx) && 1==getVexL(pfx)/*256*/) {
21788663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_MOVSxDUP_256( vbi, pfx, delta, True/*isL*/ );
21789663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
21790663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
21791663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
21792663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
21793663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x13:
21794663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVLPS xmm1, m64 = VEX.128.0F.WIG 13 /r */
21795663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Insn exists only in mem form, it appears. */
21796663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVLPD xmm1, m64 = VEX.128.66.0F.WIG 13 /r */
21797663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Insn exists only in mem form, it appears. */
21798663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if ((have66noF2noF3(pfx) || haveNo66noF2noF3(pfx))
21799663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && 0==getVexL(pfx)/*128*/ && !epartIsReg(getUChar(delta))) {
21800663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar modrm = getUChar(delta);
21801663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rG    = gregOfRexRM(pfx, modrm);
21802663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
21803663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta += alen;
21804663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         storeLE( mkexpr(addr), getXMMRegLane64( rG, 0));
21805663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("vmovlpd %s,%s\n", nameXMMReg(rG), dis_buf);
21806663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
21807663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
21808663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
21809663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
21810663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x14:
21811663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x15:
21812663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VUNPCKLPS xmm3/m128, xmm2, xmm1 = VEX.NDS.128.0F.WIG 14 /r */
21813663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VUNPCKHPS xmm3/m128, xmm2, xmm1 = VEX.NDS.128.0F.WIG 15 /r */
21814663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
21815663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Bool   hi    = opc == 0x15;
21816663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm = getUChar(delta);
21817663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG    = gregOfRexRM(pfx,modrm);
21818663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rV    = getVexNvvvv(pfx);
21819663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp eV    = newTemp(Ity_V128);
21820663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp vV    = newTemp(Ity_V128);
21821663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( vV, getXMMReg(rV) );
21822663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
21823663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
21824663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( eV, getXMMReg(rE) );
21825663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
21826663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vunpck%sps %s,%s\n", hi ? "h" : "l",
21827663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                nameXMMReg(rE), nameXMMReg(rG));
21828663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
21829663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
21830663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( eV, loadLE(Ity_V128, mkexpr(addr)) );
21831663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
21832663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vunpck%sps %s,%s\n", hi ? "h" : "l",
21833663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                dis_buf, nameXMMReg(rG));
21834663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
21835663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp res = math_UNPCKxPS_128( eV, vV, hi );
21836663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLoAndZU( rG, mkexpr(res) );
21837663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
21838663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
21839663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
21840663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VUNPCKLPS ymm3/m256, ymm2, ymm1 = VEX.NDS.256.0F.WIG 14 /r */
21841663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VUNPCKHPS ymm3/m256, ymm2, ymm1 = VEX.NDS.256.0F.WIG 15 /r */
21842663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
21843663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Bool   hi    = opc == 0x15;
21844663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm = getUChar(delta);
21845663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG    = gregOfRexRM(pfx,modrm);
21846663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rV    = getVexNvvvv(pfx);
21847663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp eV    = newTemp(Ity_V256);
21848663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp vV    = newTemp(Ity_V256);
21849663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( vV, getYMMReg(rV) );
21850663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
21851663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
21852663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( eV, getYMMReg(rE) );
21853663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
21854663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vunpck%sps %s,%s\n", hi ? "h" : "l",
21855663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                nameYMMReg(rE), nameYMMReg(rG));
21856663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
21857663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
21858663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( eV, loadLE(Ity_V256, mkexpr(addr)) );
21859663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
21860663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vunpck%sps %s,%s\n", hi ? "h" : "l",
21861663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                dis_buf, nameYMMReg(rG));
21862663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
21863663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp res = math_UNPCKxPS_256( eV, vV, hi );
21864663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMReg( rG, mkexpr(res) );
21865663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
21866663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
21867663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
21868663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VUNPCKLPD xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F.WIG 14 /r */
21869663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VUNPCKHPD xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F.WIG 15 /r */
21870663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
21871663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Bool   hi    = opc == 0x15;
21872663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm = getUChar(delta);
21873663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG    = gregOfRexRM(pfx,modrm);
21874663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rV    = getVexNvvvv(pfx);
21875663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp eV    = newTemp(Ity_V128);
21876663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp vV    = newTemp(Ity_V128);
21877663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( vV, getXMMReg(rV) );
21878663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
21879663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
21880663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( eV, getXMMReg(rE) );
21881663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
21882663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vunpck%spd %s,%s\n", hi ? "h" : "l",
21883663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                nameXMMReg(rE), nameXMMReg(rG));
21884663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
21885663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
21886663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( eV, loadLE(Ity_V128, mkexpr(addr)) );
21887663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
21888663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vunpck%spd %s,%s\n", hi ? "h" : "l",
21889663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                dis_buf, nameXMMReg(rG));
21890663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
21891663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp res = math_UNPCKxPD_128( eV, vV, hi );
21892663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLoAndZU( rG, mkexpr(res) );
21893663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
21894663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
21895663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
21896663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VUNPCKLPD ymm3/m256, ymm2, ymm1 = VEX.NDS.256.66.0F.WIG 14 /r */
21897663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VUNPCKHPD ymm3/m256, ymm2, ymm1 = VEX.NDS.256.66.0F.WIG 15 /r */
21898663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
21899663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Bool   hi    = opc == 0x15;
21900663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm = getUChar(delta);
21901663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG    = gregOfRexRM(pfx,modrm);
21902663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rV    = getVexNvvvv(pfx);
21903663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp eV    = newTemp(Ity_V256);
21904663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp vV    = newTemp(Ity_V256);
21905663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( vV, getYMMReg(rV) );
21906663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
21907663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
21908663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( eV, getYMMReg(rE) );
21909663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
21910663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vunpck%spd %s,%s\n", hi ? "h" : "l",
21911663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                nameYMMReg(rE), nameYMMReg(rG));
21912663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
21913663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
21914663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( eV, loadLE(Ity_V256, mkexpr(addr)) );
21915663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
21916663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vunpck%spd %s,%s\n", hi ? "h" : "l",
21917663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                dis_buf, nameYMMReg(rG));
21918663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
21919663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp res = math_UNPCKxPD_256( eV, vV, hi );
21920663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMReg( rG, mkexpr(res) );
21921663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
21922663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
21923663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
21924663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
21925663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
21926663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x16:
21927663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVLHPS xmm3, xmm2, xmm1 = VEX.NDS.128.0F.WIG 16 /r */
21928663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Insn only exists in reg form */
21929663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/
21930663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && epartIsReg(getUChar(delta))) {
21931663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar modrm = getUChar(delta);
21932663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rG    = gregOfRexRM(pfx, modrm);
21933663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rE    = eregOfRexRM(pfx, modrm);
21934663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rV    = getVexNvvvv(pfx);
21935663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta++;
21936663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("vmovlhps %s,%s,%s\n",
21937663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             nameXMMReg(rE), nameXMMReg(rV), nameXMMReg(rG));
21938663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp res = newTemp(Ity_V128);
21939663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(res, binop(Iop_64HLtoV128,
21940663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           getXMMRegLane64(rE, 0),
21941663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           getXMMRegLane64(rV, 0)));
21942663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLoAndZU(rG, mkexpr(res));
21943663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
21944663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
21945663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
21946663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVHPS m64, xmm1, xmm2 = VEX.NDS.128.0F.WIG 16 /r */
21947663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Insn exists only in mem form, it appears. */
21948663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVHPD m64, xmm1, xmm2 = VEX.NDS.128.66.0F.WIG 16 /r */
21949663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Insn exists only in mem form, it appears. */
21950663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if ((have66noF2noF3(pfx) || haveNo66noF2noF3(pfx))
21951663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && 0==getVexL(pfx)/*128*/ && !epartIsReg(getUChar(delta))) {
21952663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar modrm = getUChar(delta);
21953663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rG    = gregOfRexRM(pfx, modrm);
21954663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rV    = getVexNvvvv(pfx);
21955663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
21956663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta += alen;
21957663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("vmovhp%c %s,%s,%s\n", have66(pfx) ? 'd' : 's',
21958663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             dis_buf, nameXMMReg(rV), nameXMMReg(rG));
21959663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp res = newTemp(Ity_V128);
21960663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(res, binop(Iop_64HLtoV128,
21961663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           loadLE(Ity_I64, mkexpr(addr)),
21962663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           getXMMRegLane64(rV, 0)));
21963663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLoAndZU(rG, mkexpr(res));
21964663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
21965663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
21966663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
21967663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVSHDUP xmm2/m128, xmm1 = VEX.NDS.128.F3.0F.WIG 16 /r */
21968663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx) && 0==getVexL(pfx)/*128*/) {
21969663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_MOVSxDUP_128( vbi, pfx, delta, True/*isAvx*/,
21970663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   False/*!isL*/ );
21971663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
21972663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
21973663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVSHDUP ymm2/m256, ymm1 = VEX.NDS.256.F3.0F.WIG 16 /r */
21974663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx) && 1==getVexL(pfx)/*256*/) {
21975663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_MOVSxDUP_256( vbi, pfx, delta, False/*!isL*/ );
21976663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
21977663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
21978663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
21979663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
21980663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x17:
21981663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVHPS xmm1, m64 = VEX.128.0F.WIG 17 /r */
21982663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Insn exists only in mem form, it appears. */
21983663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVHPD xmm1, m64 = VEX.128.66.0F.WIG 17 /r */
21984663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Insn exists only in mem form, it appears. */
21985663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if ((have66noF2noF3(pfx) || haveNo66noF2noF3(pfx))
21986663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && 0==getVexL(pfx)/*128*/ && !epartIsReg(getUChar(delta))) {
21987663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar modrm = getUChar(delta);
21988663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rG    = gregOfRexRM(pfx, modrm);
21989663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
21990663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta += alen;
21991663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         storeLE( mkexpr(addr), getXMMRegLane64( rG, 1));
21992663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("vmovhp%c %s,%s\n", have66(pfx) ? 'd' : 's',
21993663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             nameXMMReg(rG), dis_buf);
21994663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
21995663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
21996663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
21997663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
21998663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x28:
21999663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVAPD xmm2/m128, xmm1 = VEX.128.66.0F.WIG 28 /r */
22000663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
22001663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar modrm = getUChar(delta);
22002663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rG    = gregOfRexRM(pfx, modrm);
22003663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
22004663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
22005663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putYMMRegLoAndZU( rG, getXMMReg( rE ));
22006663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovapd %s,%s\n", nameXMMReg(rE), nameXMMReg(rG));
22007663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
22008663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
22009663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
22010663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gen_SEGV_if_not_16_aligned( addr );
22011663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putYMMRegLoAndZU( rG, loadLE(Ity_V128, mkexpr(addr)) );
22012663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovapd %s,%s\n", dis_buf, nameXMMReg(rG));
22013663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
22014663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
22015663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22016663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22017663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVAPD ymm2/m256, ymm1 = VEX.256.66.0F.WIG 28 /r */
22018663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
22019663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar modrm = getUChar(delta);
22020663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rG    = gregOfRexRM(pfx, modrm);
22021663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
22022663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
22023663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putYMMReg( rG, getYMMReg( rE ));
22024663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovapd %s,%s\n", nameYMMReg(rE), nameYMMReg(rG));
22025663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
22026663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
22027663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
22028663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gen_SEGV_if_not_32_aligned( addr );
22029663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putYMMReg( rG, loadLE(Ity_V256, mkexpr(addr)) );
22030663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovapd %s,%s\n", dis_buf, nameYMMReg(rG));
22031663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
22032663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
22033663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22034663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22035663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVAPS xmm2/m128, xmm1 = VEX.128.0F.WIG 28 /r */
22036663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
22037663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar modrm = getUChar(delta);
22038663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rG    = gregOfRexRM(pfx, modrm);
22039663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
22040663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
22041663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putYMMRegLoAndZU( rG, getXMMReg( rE ));
22042663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovaps %s,%s\n", nameXMMReg(rE), nameXMMReg(rG));
22043663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
22044663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
22045663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
22046663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gen_SEGV_if_not_16_aligned( addr );
22047663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putYMMRegLoAndZU( rG, loadLE(Ity_V128, mkexpr(addr)) );
22048663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovaps %s,%s\n", dis_buf, nameXMMReg(rG));
22049663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
22050663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
22051663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22052663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22053663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVAPS ymm2/m256, ymm1 = VEX.256.0F.WIG 28 /r */
22054663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
22055663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar modrm = getUChar(delta);
22056663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rG    = gregOfRexRM(pfx, modrm);
22057663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
22058663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
22059663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putYMMReg( rG, getYMMReg( rE ));
22060663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovaps %s,%s\n", nameYMMReg(rE), nameYMMReg(rG));
22061663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
22062663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
22063663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
22064663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gen_SEGV_if_not_32_aligned( addr );
22065663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putYMMReg( rG, loadLE(Ity_V256, mkexpr(addr)) );
22066663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovaps %s,%s\n", dis_buf, nameYMMReg(rG));
22067663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
22068663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
22069663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22070663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22071663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
22072663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
22073663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x29:
22074663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVAPD xmm1, xmm2/m128 = VEX.128.66.0F.WIG 29 /r */
22075663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
22076663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar modrm = getUChar(delta);
22077663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rG    = gregOfRexRM(pfx,modrm);
22078663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
22079663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
22080663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putYMMRegLoAndZU( rE, getXMMReg(rG) );
22081663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovapd %s,%s\n", nameXMMReg(rG), nameXMMReg(rE));
22082663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
22083663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
22084663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
22085663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gen_SEGV_if_not_16_aligned( addr );
22086663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            storeLE( mkexpr(addr), getXMMReg(rG) );
22087663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovapd %s,%s\n", nameXMMReg(rG), dis_buf );
22088663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
22089663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
22090663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22091663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22092663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVAPD ymm1, ymm2/m256 = VEX.256.66.0F.WIG 29 /r */
22093663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
22094663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar modrm = getUChar(delta);
22095663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rG    = gregOfRexRM(pfx,modrm);
22096663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
22097663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
22098663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putYMMReg( rE, getYMMReg(rG) );
22099663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovapd %s,%s\n", nameYMMReg(rG), nameYMMReg(rE));
22100663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
22101663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
22102663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
22103663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gen_SEGV_if_not_32_aligned( addr );
22104663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            storeLE( mkexpr(addr), getYMMReg(rG) );
22105663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovapd %s,%s\n", nameYMMReg(rG), dis_buf );
22106663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
22107663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
22108663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22109663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22110663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVAPS xmm1, xmm2/m128 = VEX.128.0F.WIG 29 /r */
22111663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
22112663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar modrm = getUChar(delta);
22113663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rG    = gregOfRexRM(pfx,modrm);
22114663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
22115663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
22116663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putYMMRegLoAndZU( rE, getXMMReg(rG) );
22117663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovaps %s,%s\n", nameXMMReg(rG), nameXMMReg(rE));
22118663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
22119663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            goto decode_success;
22120663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
22121663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
22122663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gen_SEGV_if_not_16_aligned( addr );
22123663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            storeLE( mkexpr(addr), getXMMReg(rG) );
22124663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovaps %s,%s\n", nameXMMReg(rG), dis_buf );
22125663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
22126663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            goto decode_success;
22127663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
22128663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22129663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVAPS ymm1, ymm2/m256 = VEX.256.0F.WIG 29 /r */
22130663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
22131663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar modrm = getUChar(delta);
22132663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rG    = gregOfRexRM(pfx,modrm);
22133663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
22134663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
22135663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putYMMReg( rE, getYMMReg(rG) );
22136663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovaps %s,%s\n", nameYMMReg(rG), nameYMMReg(rE));
22137663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
22138663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            goto decode_success;
22139663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
22140663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
22141663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gen_SEGV_if_not_32_aligned( addr );
22142663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            storeLE( mkexpr(addr), getYMMReg(rG) );
22143663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovaps %s,%s\n", nameYMMReg(rG), dis_buf );
22144663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
22145663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            goto decode_success;
22146663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
22147663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22148663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
22149663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
22150663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x2A: {
22151663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRTemp rmode = newTemp(Ity_I32);
22152663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      assign( rmode, get_sse_roundingmode() );
22153663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VCVTSI2SD r/m32, xmm2, xmm1 = VEX.NDS.LIG.F2.0F.W0 2A /r */
22154663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2no66noF3(pfx) && 0==getRexW(pfx)/*W0*/) {
22155663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm = getUChar(delta);
22156663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rV    = getVexNvvvv(pfx);
22157663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rD    = gregOfRexRM(pfx, modrm);
22158663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp arg32 = newTemp(Ity_I32);
22159663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
22160663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rS = eregOfRexRM(pfx,modrm);
22161663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( arg32, getIReg32(rS) );
22162663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
22163663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vcvtsi2sdl %s,%s,%s\n",
22164663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                nameIReg32(rS), nameXMMReg(rV), nameXMMReg(rD));
22165663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
22166663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
22167663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( arg32, loadLE(Ity_I32, mkexpr(addr)) );
22168663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
22169663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vcvtsi2sdl %s,%s,%s\n",
22170663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                dis_buf, nameXMMReg(rV), nameXMMReg(rD));
22171663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
22172663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMRegLane64F( rD, 0,
22173663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           unop(Iop_I32StoF64, mkexpr(arg32)));
22174663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMRegLane64( rD, 1, getXMMRegLane64( rV, 1 ));
22175663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLane128( rD, 1, mkV128(0) );
22176663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
22177663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22178663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22179663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VCVTSI2SD r/m64, xmm2, xmm1 = VEX.NDS.LIG.F2.0F.W1 2A /r */
22180663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2no66noF3(pfx) && 1==getRexW(pfx)/*W1*/) {
22181663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm = getUChar(delta);
22182663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rV    = getVexNvvvv(pfx);
22183663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rD    = gregOfRexRM(pfx, modrm);
22184663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp arg64 = newTemp(Ity_I64);
22185663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
22186663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rS = eregOfRexRM(pfx,modrm);
22187663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( arg64, getIReg64(rS) );
22188663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
22189663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vcvtsi2sdq %s,%s,%s\n",
22190663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                nameIReg64(rS), nameXMMReg(rV), nameXMMReg(rD));
22191663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
22192663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
22193663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( arg64, loadLE(Ity_I64, mkexpr(addr)) );
22194663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
22195663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vcvtsi2sdq %s,%s,%s\n",
22196663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                dis_buf, nameXMMReg(rV), nameXMMReg(rD));
22197663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
22198663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMRegLane64F( rD, 0,
22199663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           binop( Iop_I64StoF64,
22200663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  get_sse_roundingmode(),
22201663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  mkexpr(arg64)) );
22202663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMRegLane64( rD, 1, getXMMRegLane64( rV, 1 ));
22203663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLane128( rD, 1, mkV128(0) );
22204663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
22205663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22206663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22207663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VCVTSI2SS r/m64, xmm2, xmm1 = VEX.NDS.LIG.F3.0F.W1 2A /r */
22208663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx) && 1==getRexW(pfx)/*W1*/) {
22209663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm = getUChar(delta);
22210663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rV    = getVexNvvvv(pfx);
22211663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rD    = gregOfRexRM(pfx, modrm);
22212663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp arg64 = newTemp(Ity_I64);
22213663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
22214663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rS = eregOfRexRM(pfx,modrm);
22215663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( arg64, getIReg64(rS) );
22216663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
22217663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vcvtsi2ssq %s,%s,%s\n",
22218663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                nameIReg64(rS), nameXMMReg(rV), nameXMMReg(rD));
22219663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
22220663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
22221663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( arg64, loadLE(Ity_I64, mkexpr(addr)) );
22222663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
22223663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vcvtsi2ssq %s,%s,%s\n",
22224663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                dis_buf, nameXMMReg(rV), nameXMMReg(rD));
22225663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
22226663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMRegLane32F( rD, 0,
22227663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           binop(Iop_F64toF32,
22228663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                 mkexpr(rmode),
22229663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                 binop(Iop_I64StoF64, mkexpr(rmode),
22230663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                                      mkexpr(arg64)) ) );
22231663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMRegLane32( rD, 1, getXMMRegLane32( rV, 1 ));
22232663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMRegLane64( rD, 1, getXMMRegLane64( rV, 1 ));
22233663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLane128( rD, 1, mkV128(0) );
22234663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
22235663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22236663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22237663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VCVTSI2SS r/m32, xmm2, xmm1 = VEX.NDS.LIG.F3.0F.W0 2A /r */
22238663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx) && 0==getRexW(pfx)/*W0*/) {
22239663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm = getUChar(delta);
22240663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rV    = getVexNvvvv(pfx);
22241663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rD    = gregOfRexRM(pfx, modrm);
22242663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp arg32 = newTemp(Ity_I32);
22243663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
22244663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rS = eregOfRexRM(pfx,modrm);
22245663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( arg32, getIReg32(rS) );
22246663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
22247663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vcvtsi2ssl %s,%s,%s\n",
22248663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                nameIReg32(rS), nameXMMReg(rV), nameXMMReg(rD));
22249663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
22250663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
22251663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( arg32, loadLE(Ity_I32, mkexpr(addr)) );
22252663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
22253663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vcvtsi2ssl %s,%s,%s\n",
22254663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                dis_buf, nameXMMReg(rV), nameXMMReg(rD));
22255663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
22256663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMRegLane32F( rD, 0,
22257663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           binop(Iop_F64toF32,
22258663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                 mkexpr(rmode),
22259663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                 unop(Iop_I32StoF64, mkexpr(arg32)) ) );
22260663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMRegLane32( rD, 1, getXMMRegLane32( rV, 1 ));
22261663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMRegLane64( rD, 1, getXMMRegLane64( rV, 1 ));
22262663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLane128( rD, 1, mkV128(0) );
22263663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
22264663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22265663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22266663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
22267663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
22268663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
22269663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x2B:
22270663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVNTPD xmm1, m128 = VEX.128.66.0F.WIG 2B /r */
22271663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVNTPS xmm1, m128 = VEX.128.0F.WIG 2B /r */
22272663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if ((have66noF2noF3(pfx) || haveNo66noF2noF3(pfx))
22273663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && 0==getVexL(pfx)/*128*/ && !epartIsReg(getUChar(delta))) {
22274663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm = getUChar(delta);
22275663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rS    = gregOfRexRM(pfx, modrm);
22276663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp tS    = newTemp(Ity_V128);
22277663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(tS, getXMMReg(rS));
22278663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 0 );
22279663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta += alen;
22280663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         gen_SEGV_if_not_16_aligned(addr);
22281663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         storeLE(mkexpr(addr), mkexpr(tS));
22282663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("vmovntp%c %s,%s\n", have66(pfx) ? 'd' : 's',
22283663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             nameXMMReg(rS), dis_buf);
22284663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22285663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22286663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVNTPD ymm1, m256 = VEX.256.66.0F.WIG 2B /r */
22287663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVNTPS ymm1, m256 = VEX.256.0F.WIG 2B /r */
22288663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if ((have66noF2noF3(pfx) || haveNo66noF2noF3(pfx))
22289663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && 1==getVexL(pfx)/*256*/ && !epartIsReg(getUChar(delta))) {
22290663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm = getUChar(delta);
22291663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rS    = gregOfRexRM(pfx, modrm);
22292663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp tS    = newTemp(Ity_V256);
22293663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(tS, getYMMReg(rS));
22294663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 0 );
22295663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta += alen;
22296663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         gen_SEGV_if_not_32_aligned(addr);
22297663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         storeLE(mkexpr(addr), mkexpr(tS));
22298663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("vmovntp%c %s,%s\n", have66(pfx) ? 'd' : 's',
22299663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             nameYMMReg(rS), dis_buf);
22300663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22301663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22302663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
22303663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
22304663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x2C:
22305663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VCVTTSD2SI xmm1/m32, r32 = VEX.LIG.F2.0F.W0 2C /r */
22306663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2no66noF3(pfx) && 0==getRexW(pfx)/*W0*/) {
22307663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_CVTxSD2SI( vbi, pfx, delta, True/*isAvx*/, opc, 4);
22308663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22309663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22310663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VCVTTSD2SI xmm1/m64, r64 = VEX.LIG.F2.0F.W1 2C /r */
22311663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2no66noF3(pfx) && 1==getRexW(pfx)/*W1*/) {
22312663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_CVTxSD2SI( vbi, pfx, delta, True/*isAvx*/, opc, 8);
22313663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22314663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22315663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VCVTTSS2SI xmm1/m32, r32 = VEX.LIG.F3.0F.W0 2C /r */
22316663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx) && 0==getRexW(pfx)/*W0*/) {
22317663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_CVTxSS2SI( vbi, pfx, delta, True/*isAvx*/, opc, 4);
22318663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22319663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22320663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VCVTTSS2SI xmm1/m64, r64 = VEX.LIG.F3.0F.W1 2C /r */
22321663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx) && 1==getRexW(pfx)/*W1*/) {
22322663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_CVTxSS2SI( vbi, pfx, delta, True/*isAvx*/, opc, 8);
22323663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22324663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22325663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
22326663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
22327663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x2D:
22328663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VCVTSD2SI xmm1/m32, r32 = VEX.LIG.F2.0F.W0 2D /r */
22329663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2no66noF3(pfx) && 0==getRexW(pfx)/*W0*/) {
22330663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_CVTxSD2SI( vbi, pfx, delta, True/*isAvx*/, opc, 4);
22331663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22332663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22333663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VCVTSD2SI xmm1/m64, r64 = VEX.LIG.F2.0F.W1 2D /r */
22334663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2no66noF3(pfx) && 1==getRexW(pfx)/*W1*/) {
22335663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_CVTxSD2SI( vbi, pfx, delta, True/*isAvx*/, opc, 8);
22336663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22337663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22338663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VCVTSS2SI xmm1/m32, r32 = VEX.LIG.F3.0F.W0 2D /r */
22339663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx) && 0==getRexW(pfx)/*W0*/) {
22340663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_CVTxSS2SI( vbi, pfx, delta, True/*isAvx*/, opc, 4);
22341663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22342663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22343663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VCVTSS2SI xmm1/m64, r64 = VEX.LIG.F3.0F.W1 2D /r */
22344663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx) && 1==getRexW(pfx)/*W1*/) {
22345663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_CVTxSS2SI( vbi, pfx, delta, True/*isAvx*/, opc, 8);
22346663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22347663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22348663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
22349663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
22350663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x2E:
22351663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x2F:
22352663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VUCOMISD xmm2/m64, xmm1 = VEX.LIG.66.0F.WIG 2E /r */
22353663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VCOMISD  xmm2/m64, xmm1 = VEX.LIG.66.0F.WIG 2F /r */
22354663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)) {
22355663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_COMISD( vbi, pfx, delta, True/*isAvx*/, opc );
22356663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22357663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22358663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VUCOMISS xmm2/m32, xmm1 = VEX.LIG.0F.WIG 2E /r */
22359663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VCOMISS xmm2/m32, xmm1  = VEX.LIG.0F.WIG 2F /r */
22360663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx)) {
22361663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_COMISS( vbi, pfx, delta, True/*isAvx*/, opc );
22362663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22363663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22364663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
22365663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
22366663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x50:
22367663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVMSKPD xmm2, r32 = VEX.128.66.0F.WIG 50 /r */
22368663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
22369663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_MOVMSKPD_128( vbi, pfx, delta, True/*isAvx*/ );
22370663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22371663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22372663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVMSKPD ymm2, r32 = VEX.256.66.0F.WIG 50 /r */
22373663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
22374663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_MOVMSKPD_256( vbi, pfx, delta );
22375663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22376663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22377663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVMSKPS xmm2, r32 = VEX.128.0F.WIG 50 /r */
22378663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
22379663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_MOVMSKPS_128( vbi, pfx, delta, True/*isAvx*/ );
22380663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22381663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22382663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVMSKPS ymm2, r32 = VEX.256.0F.WIG 50 /r */
22383663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
22384663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_MOVMSKPS_256( vbi, pfx, delta );
22385663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22386663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22387663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
22388663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
22389663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x51:
22390663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VSQRTSS xmm3/m64(E), xmm2(V), xmm1(G) = VEX.NDS.LIG.F3.0F.WIG 51 /r */
22391663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx)) {
22392663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_E_V_to_G_lo32_unary(
22393663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vsqrtss", Iop_Sqrt32F0x4 );
22394663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22395663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22396663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VSQRTPS xmm2/m128(E), xmm1(G) = VEX.NDS.128.0F.WIG 51 /r */
22397663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
22398663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_E_to_G_unary_all(
22399663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vsqrtps", Iop_Sqrt32Fx4 );
22400663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22401663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22402663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VSQRTPS ymm2/m256(E), ymm1(G) = VEX.NDS.256.0F.WIG 51 /r */
22403663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
22404663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX256_E_to_G_unary_all(
22405663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vsqrtps", Iop_Sqrt32Fx8 );
22406663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22407663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22408663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VSQRTSD xmm3/m64(E), xmm2(V), xmm1(G) = VEX.NDS.LIG.F2.0F.WIG 51 /r */
22409663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2no66noF3(pfx)) {
22410663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_E_V_to_G_lo64_unary(
22411663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vsqrtsd", Iop_Sqrt64F0x2 );
22412663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22413663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22414663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VSQRTPD xmm2/m128(E), xmm1(G) = VEX.NDS.128.66.0F.WIG 51 /r */
22415663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
22416663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_E_to_G_unary_all(
22417663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vsqrtpd", Iop_Sqrt64Fx2 );
22418663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22419663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22420663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VSQRTPD ymm2/m256(E), ymm1(G) = VEX.NDS.256.66.0F.WIG 51 /r */
22421663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
22422663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX256_E_to_G_unary_all(
22423663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vsqrtpd", Iop_Sqrt64Fx4 );
22424663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22425663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22426663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
22427663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
22428663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x52:
22429663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VRSQRTSS xmm3/m64(E), xmm2(V), xmm1(G) = VEX.NDS.LIG.F3.0F.WIG 52 /r */
22430663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx)) {
22431663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_E_V_to_G_lo32_unary(
22432663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vrsqrtss", Iop_RSqrt32F0x4 );
22433663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22434663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22435663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VRSQRTPS xmm2/m128(E), xmm1(G) = VEX.NDS.128.0F.WIG 52 /r */
22436663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
22437663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_E_to_G_unary_all(
22438663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vrsqrtps", Iop_RSqrt32Fx4 );
22439663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22440663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22441663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VRSQRTPS ymm2/m256(E), ymm1(G) = VEX.NDS.256.0F.WIG 52 /r */
22442663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
22443663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX256_E_to_G_unary_all(
22444663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vrsqrtps", Iop_RSqrt32Fx8 );
22445663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22446663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22447663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
22448663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
22449663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x53:
22450663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VRCPSS xmm3/m64(E), xmm2(V), xmm1(G) = VEX.NDS.LIG.F3.0F.WIG 53 /r */
22451663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx)) {
22452663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_E_V_to_G_lo32_unary(
22453663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vrcpss", Iop_Recip32F0x4 );
22454663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22455663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22456663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VRCPPS xmm2/m128(E), xmm1(G) = VEX.NDS.128.0F.WIG 53 /r */
22457663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
22458663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_E_to_G_unary_all(
22459663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vrcpps", Iop_Recip32Fx4 );
22460663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22461663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22462663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VRCPPS ymm2/m256(E), ymm1(G) = VEX.NDS.256.0F.WIG 53 /r */
22463663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
22464663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX256_E_to_G_unary_all(
22465663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vrcpps", Iop_Recip32Fx8 );
22466663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22467663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22468663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
22469663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
22470663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x54:
22471663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VANDPD r/m, rV, r ::: r = rV & r/m */
22472663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VANDPD = VEX.NDS.128.66.0F.WIG 54 /r */
22473663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
22474663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG_simple(
22475663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vandpd", Iop_AndV128 );
22476663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22477663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22478663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VANDPD r/m, rV, r ::: r = rV & r/m */
22479663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VANDPD = VEX.NDS.256.66.0F.WIG 54 /r */
22480663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
22481663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX256_E_V_to_G(
22482663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vandpd", Iop_AndV256 );
22483663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22484663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22485663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VANDPS = VEX.NDS.128.0F.WIG 54 /r */
22486663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
22487663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG_simple(
22488663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vandps", Iop_AndV128 );
22489663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22490663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22491663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VANDPS = VEX.NDS.256.0F.WIG 54 /r */
22492663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
22493663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX256_E_V_to_G(
22494663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vandps", Iop_AndV256 );
22495663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22496663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22497663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
22498663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
22499663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x55:
22500663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VANDNPD r/m, rV, r ::: r = (not rV) & r/m */
22501663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VANDNPD = VEX.NDS.128.66.0F.WIG 55 /r */
22502663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
22503663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG(
22504663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vandpd", Iop_AndV128,
22505663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    NULL, True/*invertLeftArg*/, False/*swapArgs*/ );
22506663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22507663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22508663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VANDNPD = VEX.NDS.256.66.0F.WIG 55 /r */
22509663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
22510663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_256_AnySimdPfx_0F_WIG(
22511663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vandpd", Iop_AndV256,
22512663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    NULL, True/*invertLeftArg*/, False/*swapArgs*/ );
22513663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22514663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22515663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VANDNPS = VEX.NDS.128.0F.WIG 55 /r */
22516663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
22517663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG(
22518663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vandps", Iop_AndV128,
22519663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    NULL, True/*invertLeftArg*/, False/*swapArgs*/ );
22520663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22521663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22522663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VANDNPS = VEX.NDS.256.0F.WIG 55 /r */
22523663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
22524663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_256_AnySimdPfx_0F_WIG(
22525663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vandps", Iop_AndV256,
22526663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    NULL, True/*invertLeftArg*/, False/*swapArgs*/ );
22527663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22528663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22529663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
22530663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
22531663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x56:
22532663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VORPD r/m, rV, r ::: r = rV | r/m */
22533663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VORPD = VEX.NDS.128.66.0F.WIG 56 /r */
22534663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
22535663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG_simple(
22536663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vorpd", Iop_OrV128 );
22537663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22538663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22539663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VORPD r/m, rV, r ::: r = rV | r/m */
22540663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VORPD = VEX.NDS.256.66.0F.WIG 56 /r */
22541663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
22542663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX256_E_V_to_G(
22543663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vorpd", Iop_OrV256 );
22544663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22545663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22546663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VORPS r/m, rV, r ::: r = rV | r/m */
22547663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VORPS = VEX.NDS.128.0F.WIG 56 /r */
22548663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
22549663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG_simple(
22550663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vorps", Iop_OrV128 );
22551663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22552663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22553663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VORPS r/m, rV, r ::: r = rV | r/m */
22554663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VORPS = VEX.NDS.256.0F.WIG 56 /r */
22555663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
22556663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX256_E_V_to_G(
22557663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vorps", Iop_OrV256 );
22558663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22559663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22560663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
22561663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
22562663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x57:
22563663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VXORPD r/m, rV, r ::: r = rV ^ r/m */
22564663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VXORPD = VEX.NDS.128.66.0F.WIG 57 /r */
22565663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
22566663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG_simple(
22567663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vxorpd", Iop_XorV128 );
22568663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22569663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22570663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VXORPD r/m, rV, r ::: r = rV ^ r/m */
22571663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VXORPD = VEX.NDS.256.66.0F.WIG 57 /r */
22572663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
22573663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX256_E_V_to_G(
22574663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vxorpd", Iop_XorV256 );
22575663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22576663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22577663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VXORPS r/m, rV, r ::: r = rV ^ r/m */
22578663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VXORPS = VEX.NDS.128.0F.WIG 57 /r */
22579663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
22580663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG_simple(
22581663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vxorps", Iop_XorV128 );
22582663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22583663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22584663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VXORPS r/m, rV, r ::: r = rV ^ r/m */
22585663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VXORPS = VEX.NDS.256.0F.WIG 57 /r */
22586663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
22587663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX256_E_V_to_G(
22588663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vxorps", Iop_XorV256 );
22589663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22590663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22591663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
22592663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
22593663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x58:
22594663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VADDSD xmm3/m64, xmm2, xmm1 = VEX.NDS.LIG.F2.0F.WIG 58 /r */
22595663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2no66noF3(pfx)) {
22596663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_E_V_to_G_lo64(
22597663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vaddsd", Iop_Add64F0x2 );
22598663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22599663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22600663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VADDSS xmm3/m32, xmm2, xmm1 = VEX.NDS.LIG.F3.0F.WIG 58 /r */
22601663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx)) {
22602663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_E_V_to_G_lo32(
22603663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vaddss", Iop_Add32F0x4 );
22604663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22605663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22606663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VADDPS xmm3/m128, xmm2, xmm1 = VEX.NDS.128.0F.WIG 58 /r */
22607663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
22608663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_E_V_to_G(
22609663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vaddps", Iop_Add32Fx4 );
22610663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22611663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22612663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VADDPS ymm3/m256, ymm2, ymm1 = VEX.NDS.256.0F.WIG 58 /r */
22613663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
22614663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX256_E_V_to_G(
22615663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vaddps", Iop_Add32Fx8 );
22616663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22617663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22618663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VADDPD xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F.WIG 58 /r */
22619663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
22620663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_E_V_to_G(
22621663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vaddpd", Iop_Add64Fx2 );
22622663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22623663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22624663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VADDPD ymm3/m256, ymm2, ymm1 = VEX.NDS.256.66.0F.WIG 58 /r */
22625663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
22626663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX256_E_V_to_G(
22627663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vaddpd", Iop_Add64Fx4 );
22628663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22629663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22630663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
22631663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
22632663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x59:
22633663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMULSD xmm3/m64, xmm2, xmm1 = VEX.NDS.LIG.F2.0F.WIG 59 /r */
22634663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2no66noF3(pfx)) {
22635663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_E_V_to_G_lo64(
22636663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vmulsd", Iop_Mul64F0x2 );
22637663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22638663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22639663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMULSS xmm3/m32, xmm2, xmm1 = VEX.NDS.LIG.F3.0F.WIG 59 /r */
22640663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx)) {
22641663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_E_V_to_G_lo32(
22642663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vmulss", Iop_Mul32F0x4 );
22643663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22644663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22645663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMULPS xmm3/m128, xmm2, xmm1 = VEX.NDS.128.0F.WIG 59 /r */
22646663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
22647663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_E_V_to_G(
22648663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vmulps", Iop_Mul32Fx4 );
22649663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22650663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22651663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMULPS ymm3/m256, ymm2, ymm1 = VEX.NDS.256.0F.WIG 59 /r */
22652663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
22653663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX256_E_V_to_G(
22654663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vmulps", Iop_Mul32Fx8 );
22655663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22656663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22657663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMULPD xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F.WIG 59 /r */
22658663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
22659663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_E_V_to_G(
22660663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vmulpd", Iop_Mul64Fx2 );
22661663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22662663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22663663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMULPD ymm3/m256, ymm2, ymm1 = VEX.NDS.256.66.0F.WIG 59 /r */
22664663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
22665663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX256_E_V_to_G(
22666663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vmulpd", Iop_Mul64Fx4 );
22667663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22668663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22669663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
22670663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
22671663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x5A:
22672663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VCVTPS2PD xmm2/m64, xmm1 = VEX.128.0F.WIG 5A /r */
22673663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
22674663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_CVTPS2PD_128( vbi, pfx, delta, True/*isAvx*/ );
22675663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22676663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22677663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VCVTPS2PD xmm2/m128, ymm1 = VEX.256.0F.WIG 5A /r */
22678663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
22679663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_CVTPS2PD_256( vbi, pfx, delta );
22680663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22681663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22682663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VCVTPD2PS xmm2/m128, xmm1 = VEX.128.66.0F.WIG 5A /r */
22683663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
22684663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_CVTPD2PS_128( vbi, pfx, delta, True/*isAvx*/ );
22685663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22686663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22687663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VCVTPD2PS ymm2/m256, xmm1 = VEX.256.66.0F.WIG 5A /r */
22688663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
22689663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_CVTPD2PS_256( vbi, pfx, delta );
22690663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22691663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22692663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VCVTSD2SS xmm3/m64, xmm2, xmm1 = VEX.NDS.LIG.F2.0F.WIG 5A /r */
22693663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2no66noF3(pfx)) {
22694663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm = getUChar(delta);
22695663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rV    = getVexNvvvv(pfx);
22696663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rD    = gregOfRexRM(pfx, modrm);
22697663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp f64lo = newTemp(Ity_F64);
22698663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp rmode = newTemp(Ity_I32);
22699663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( rmode, get_sse_roundingmode() );
22700663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
22701663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rS = eregOfRexRM(pfx,modrm);
22702663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(f64lo, getXMMRegLane64F(rS, 0));
22703663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
22704663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vcvtsd2ss %s,%s,%s\n",
22705663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                nameXMMReg(rS), nameXMMReg(rV), nameXMMReg(rD));
22706663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
22707663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
22708663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(f64lo, loadLE(Ity_F64, mkexpr(addr)) );
22709663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
22710663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vcvtsd2ss %s,%s,%s\n",
22711663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                dis_buf, nameXMMReg(rV), nameXMMReg(rD));
22712663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
22713663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMRegLane32F( rD, 0,
22714663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           binop( Iop_F64toF32, mkexpr(rmode),
22715663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                                mkexpr(f64lo)) );
22716663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMRegLane32( rD, 1, getXMMRegLane32( rV, 1 ));
22717663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMRegLane64( rD, 1, getXMMRegLane64( rV, 1 ));
22718663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLane128( rD, 1, mkV128(0) );
22719663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
22720663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22721663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22722663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VCVTSS2SD xmm3/m32, xmm2, xmm1 = VEX.NDS.LIG.F3.0F.WIG 5A /r */
22723663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx)) {
22724663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm = getUChar(delta);
22725663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rV    = getVexNvvvv(pfx);
22726663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rD    = gregOfRexRM(pfx, modrm);
22727663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp f32lo = newTemp(Ity_F32);
22728663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
22729663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rS = eregOfRexRM(pfx,modrm);
22730663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(f32lo, getXMMRegLane32F(rS, 0));
22731663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
22732663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vcvtss2sd %s,%s,%s\n",
22733663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                nameXMMReg(rS), nameXMMReg(rV), nameXMMReg(rD));
22734663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
22735663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
22736663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(f32lo, loadLE(Ity_F32, mkexpr(addr)) );
22737663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
22738663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vcvtss2sd %s,%s,%s\n",
22739663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                dis_buf, nameXMMReg(rV), nameXMMReg(rD));
22740663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
22741663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMRegLane64F( rD, 0,
22742663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           unop( Iop_F32toF64, mkexpr(f32lo)) );
22743663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMRegLane64( rD, 1, getXMMRegLane64( rV, 1 ));
22744663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLane128( rD, 1, mkV128(0) );
22745663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
22746663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22747663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22748663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
22749663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
22750663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x5B:
22751663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VCVTPS2DQ xmm2/m128, xmm1 = VEX.128.66.0F.WIG 5B /r */
22752663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
22753663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_CVTxPS2DQ_128( vbi, pfx, delta,
22754663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    True/*isAvx*/, False/*!r2zero*/ );
22755663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22756663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22757663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VCVTPS2DQ ymm2/m256, ymm1 = VEX.256.66.0F.WIG 5B /r */
22758663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
22759663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_CVTxPS2DQ_256( vbi, pfx, delta,
22760663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    False/*!r2zero*/ );
22761663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22762663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22763663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VCVTTPS2DQ xmm2/m128, xmm1 = VEX.128.F3.0F.WIG 5B /r */
22764663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx) && 0==getVexL(pfx)/*128*/) {
22765663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_CVTxPS2DQ_128( vbi, pfx, delta,
22766663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    True/*isAvx*/, True/*r2zero*/ );
22767663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22768663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22769663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VCVTTPS2DQ ymm2/m256, ymm1 = VEX.256.F3.0F.WIG 5B /r */
22770663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx) && 1==getVexL(pfx)/*256*/) {
22771663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_CVTxPS2DQ_256( vbi, pfx, delta,
22772663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    True/*r2zero*/ );
22773663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22774663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22775663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VCVTDQ2PS xmm2/m128, xmm1 = VEX.128.0F.WIG 5B /r */
22776663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
22777663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_CVTDQ2PS_128 ( vbi, pfx, delta, True/*isAvx*/ );
22778663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22779663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22780663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VCVTDQ2PS ymm2/m256, ymm1 = VEX.256.0F.WIG 5B /r */
22781663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
22782663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_CVTDQ2PS_256 ( vbi, pfx, delta );
22783663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22784663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22785663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
22786663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
22787663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x5C:
22788663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VSUBSD xmm3/m64, xmm2, xmm1 = VEX.NDS.LIG.F2.0F.WIG 5C /r */
22789663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2no66noF3(pfx)) {
22790663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_E_V_to_G_lo64(
22791663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vsubsd", Iop_Sub64F0x2 );
22792663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22793663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22794663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VSUBSS xmm3/m32, xmm2, xmm1 = VEX.NDS.LIG.F3.0F.WIG 5C /r */
22795663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx)) {
22796663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_E_V_to_G_lo32(
22797663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vsubss", Iop_Sub32F0x4 );
22798663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22799663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22800663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VSUBPS xmm3/m128, xmm2, xmm1 = VEX.NDS.128.0F.WIG 5C /r */
22801663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
22802663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_E_V_to_G(
22803663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vsubps", Iop_Sub32Fx4 );
22804663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22805663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22806663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VSUBPS ymm3/m256, ymm2, ymm1 = VEX.NDS.256.0F.WIG 5C /r */
22807663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
22808663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX256_E_V_to_G(
22809663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vsubps", Iop_Sub32Fx8 );
22810663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22811663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22812663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VSUBPD xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F.WIG 5C /r */
22813663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
22814663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_E_V_to_G(
22815663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vsubpd", Iop_Sub64Fx2 );
22816663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22817663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22818663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VSUBPD ymm3/m256, ymm2, ymm1 = VEX.NDS.256.66.0F.WIG 5C /r */
22819663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
22820663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX256_E_V_to_G(
22821663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vsubpd", Iop_Sub64Fx4 );
22822663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22823663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22824663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
22825663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
22826663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x5D:
22827663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMINSD xmm3/m64, xmm2, xmm1 = VEX.NDS.LIG.F2.0F.WIG 5D /r */
22828663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2no66noF3(pfx)) {
22829663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_E_V_to_G_lo64(
22830663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vminsd", Iop_Min64F0x2 );
22831663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22832663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22833663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMINSS xmm3/m32, xmm2, xmm1 = VEX.NDS.LIG.F3.0F.WIG 5D /r */
22834663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx)) {
22835663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_E_V_to_G_lo32(
22836663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vminss", Iop_Min32F0x4 );
22837663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22838663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22839663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMINPS xmm3/m128, xmm2, xmm1 = VEX.NDS.128.0F.WIG 5D /r */
22840663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
22841663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_E_V_to_G(
22842663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vminps", Iop_Min32Fx4 );
22843663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22844663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22845663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMINPS ymm3/m256, ymm2, ymm1 = VEX.NDS.256.0F.WIG 5D /r */
22846663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
22847663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX256_E_V_to_G(
22848663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vminps", Iop_Min32Fx8 );
22849663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22850663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22851663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMINPD xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F.WIG 5D /r */
22852663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
22853663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_E_V_to_G(
22854663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vminpd", Iop_Min64Fx2 );
22855663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22856663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22857663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMINPD ymm3/m256, ymm2, ymm1 = VEX.NDS.256.66.0F.WIG 5D /r */
22858663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
22859663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX256_E_V_to_G(
22860663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vminpd", Iop_Min64Fx4 );
22861663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22862663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22863663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
22864663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
22865663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x5E:
22866663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VDIVSD xmm3/m64, xmm2, xmm1 = VEX.NDS.LIG.F2.0F.WIG 5E /r */
22867663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2no66noF3(pfx)) {
22868663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_E_V_to_G_lo64(
22869663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vdivsd", Iop_Div64F0x2 );
22870663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22871663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22872663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VDIVSS xmm3/m32, xmm2, xmm1 = VEX.NDS.LIG.F3.0F.WIG 5E /r */
22873663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx)) {
22874663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_E_V_to_G_lo32(
22875663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vdivss", Iop_Div32F0x4 );
22876663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22877663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22878663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VDIVPS xmm3/m128, xmm2, xmm1 = VEX.NDS.128.0F.WIG 5E /r */
22879663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
22880663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_E_V_to_G(
22881663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vdivps", Iop_Div32Fx4 );
22882663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22883663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22884663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VDIVPS ymm3/m256, ymm2, ymm1 = VEX.NDS.256.0F.WIG 5E /r */
22885663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
22886663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX256_E_V_to_G(
22887663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vdivps", Iop_Div32Fx8 );
22888663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22889663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22890663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VDIVPD xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F.WIG 5E /r */
22891663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
22892663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_E_V_to_G(
22893663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vdivpd", Iop_Div64Fx2 );
22894663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22895663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22896663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VDIVPD ymm3/m256, ymm2, ymm1 = VEX.NDS.256.66.0F.WIG 5E /r */
22897663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
22898663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX256_E_V_to_G(
22899663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vdivpd", Iop_Div64Fx4 );
22900663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22901663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22902663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
22903663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
22904663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x5F:
22905663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMAXSD xmm3/m64, xmm2, xmm1 = VEX.NDS.LIG.F2.0F.WIG 5F /r */
22906663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2no66noF3(pfx)) {
22907663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_E_V_to_G_lo64(
22908663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vmaxsd", Iop_Max64F0x2 );
22909663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22910663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22911663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMAXSS xmm3/m32, xmm2, xmm1 = VEX.NDS.LIG.F3.0F.WIG 5F /r */
22912663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx)) {
22913663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_E_V_to_G_lo32(
22914663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vmaxss", Iop_Max32F0x4 );
22915663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22916663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22917663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMAXPS xmm3/m128, xmm2, xmm1 = VEX.NDS.128.0F.WIG 5F /r */
22918663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
22919663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_E_V_to_G(
22920663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vmaxps", Iop_Max32Fx4 );
22921663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22922663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22923663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMAXPS ymm3/m256, ymm2, ymm1 = VEX.NDS.256.0F.WIG 5F /r */
22924663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
22925663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX256_E_V_to_G(
22926663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vmaxps", Iop_Max32Fx8 );
22927663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22928663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22929663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMAXPD xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F.WIG 5F /r */
22930663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
22931663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_E_V_to_G(
22932663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vmaxpd", Iop_Max64Fx2 );
22933663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22934663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22935663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMAXPD ymm3/m256, ymm2, ymm1 = VEX.NDS.256.66.0F.WIG 5F /r */
22936663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
22937663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX256_E_V_to_G(
22938663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vmaxpd", Iop_Max64Fx4 );
22939663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22940663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22941663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
22942663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
22943663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x60:
22944663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPUNPCKLBW r/m, rV, r ::: r = interleave-lo-bytes(rV, r/m) */
22945663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPUNPCKLBW = VEX.NDS.128.66.0F.WIG 60 /r */
22946663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
22947663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG(
22948663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpunpcklbw",
22949663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    Iop_InterleaveLO8x16, NULL,
22950663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    False/*!invertLeftArg*/, True/*swapArgs*/ );
22951663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22952663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22953663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
22954663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
22955663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x61:
22956663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPUNPCKLWD r/m, rV, r ::: r = interleave-lo-words(rV, r/m) */
22957663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPUNPCKLWD = VEX.NDS.128.66.0F.WIG 61 /r */
22958663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
22959663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG(
22960663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpunpcklwd",
22961663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    Iop_InterleaveLO16x8, NULL,
22962663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    False/*!invertLeftArg*/, True/*swapArgs*/ );
22963663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22964663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22965663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
22966663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
22967663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x62:
22968663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPUNPCKLDQ r/m, rV, r ::: r = interleave-lo-dwords(rV, r/m) */
22969663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPUNPCKLDQ = VEX.NDS.128.66.0F.WIG 62 /r */
22970663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
22971663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG(
22972663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpunpckldq",
22973663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    Iop_InterleaveLO32x4, NULL,
22974663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    False/*!invertLeftArg*/, True/*swapArgs*/ );
22975663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22976663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22977663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
22978663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
22979663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x63:
22980663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPACKSSWB r/m, rV, r ::: r = QNarrowBin16Sto8Sx16(rV, r/m) */
22981663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPACKSSWB = VEX.NDS.128.66.0F.WIG 63 /r */
22982663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
22983663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG(
22984663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpacksswb",
22985663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    Iop_QNarrowBin16Sto8Sx16, NULL,
22986663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    False/*!invertLeftArg*/, True/*swapArgs*/ );
22987663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22988663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22989663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
22990663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
22991663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x64:
22992663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPCMPGTB r/m, rV, r ::: r = rV `>s-by-8s` r/m */
22993663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPCMPGTB = VEX.NDS.128.66.0F.WIG 64 /r */
22994663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
22995663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG_simple(
22996663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpcmpgtb", Iop_CmpGT8Sx16 );
22997663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
22998663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
22999663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
23000663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
23001663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x65:
23002663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPCMPGTW r/m, rV, r ::: r = rV `>s-by-16s` r/m */
23003663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPCMPGTW = VEX.NDS.128.66.0F.WIG 65 /r */
23004663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
23005663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG_simple(
23006663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpcmpgtw", Iop_CmpGT16Sx8 );
23007663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
23008663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23009663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
23010663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
23011663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x66:
23012663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPCMPGTD r/m, rV, r ::: r = rV `>s-by-32s` r/m */
23013663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPCMPGTD = VEX.NDS.128.66.0F.WIG 66 /r */
23014663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
23015663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG_simple(
23016663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpcmpgtd", Iop_CmpGT32Sx4 );
23017663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
23018663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23019663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
23020663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
23021663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x67:
23022663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPACKUSWB r/m, rV, r ::: r = QNarrowBin16Sto8Ux16(rV, r/m) */
23023663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPACKUSWB = VEX.NDS.128.66.0F.WIG 67 /r */
23024663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
23025663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG(
23026663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpackuswb",
23027663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    Iop_QNarrowBin16Sto8Ux16, NULL,
23028663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    False/*!invertLeftArg*/, True/*swapArgs*/ );
23029663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
23030663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23031663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
23032663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
23033663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x68:
23034663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPUNPCKHBW r/m, rV, r ::: r = interleave-hi-bytes(rV, r/m) */
23035663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPUNPCKHBW = VEX.NDS.128.0F.WIG 68 /r */
23036663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
23037663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG(
23038663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpunpckhbw",
23039663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    Iop_InterleaveHI8x16, NULL,
23040663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    False/*!invertLeftArg*/, True/*swapArgs*/ );
23041663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
23042663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23043663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
23044663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
23045663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x69:
23046663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPUNPCKHWD r/m, rV, r ::: r = interleave-hi-words(rV, r/m) */
23047663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPUNPCKHWD = VEX.NDS.128.0F.WIG 69 /r */
23048663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
23049663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG(
23050663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpunpckhwd",
23051663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    Iop_InterleaveHI16x8, NULL,
23052663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    False/*!invertLeftArg*/, True/*swapArgs*/ );
23053663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
23054663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23055663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
23056663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
23057663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x6A:
23058663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPUNPCKHDQ r/m, rV, r ::: r = interleave-hi-dwords(rV, r/m) */
23059663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPUNPCKHDQ = VEX.NDS.128.66.0F.WIG 6A /r */
23060663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
23061663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG(
23062663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpunpckhdq",
23063663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    Iop_InterleaveHI32x4, NULL,
23064663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    False/*!invertLeftArg*/, True/*swapArgs*/ );
23065663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
23066663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23067663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
23068663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
23069663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x6B:
23070663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPACKSSDW r/m, rV, r ::: r = QNarrowBin32Sto16Sx8(rV, r/m) */
23071663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPACKSSDW = VEX.NDS.128.66.0F.WIG 6B /r */
23072663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
23073663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG(
23074663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpackssdw",
23075663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    Iop_QNarrowBin32Sto16Sx8, NULL,
23076663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    False/*!invertLeftArg*/, True/*swapArgs*/ );
23077663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
23078663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23079663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
23080663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
23081663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x6C:
23082663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPUNPCKLQDQ r/m, rV, r ::: r = interleave-lo-64bitses(rV, r/m) */
23083663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPUNPCKLQDQ = VEX.NDS.128.0F.WIG 6C /r */
23084663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
23085663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG(
23086663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpunpcklqdq",
23087663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    Iop_InterleaveLO64x2, NULL,
23088663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    False/*!invertLeftArg*/, True/*swapArgs*/ );
23089663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
23090663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23091663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
23092663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
23093663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x6D:
23094663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPUNPCKHQDQ r/m, rV, r ::: r = interleave-hi-64bitses(rV, r/m) */
23095663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPUNPCKHQDQ = VEX.NDS.128.0F.WIG 6D /r */
23096663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
23097663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG(
23098663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpunpckhqdq",
23099663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    Iop_InterleaveHI64x2, NULL,
23100663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    False/*!invertLeftArg*/, True/*swapArgs*/ );
23101663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
23102663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23103663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
23104663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
23105663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x6E:
23106663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVD r32/m32, xmm1 = VEX.128.66.0F.W0 6E */
23107663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
23108663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && 0==getVexL(pfx)/*128*/ && 0==getRexW(pfx)/*W0*/) {
23109663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(sz == 2); /* even tho we are transferring 4, not 2. */
23110663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar modrm = getUChar(delta);
23111663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
23112663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
23113663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putYMMRegLoAndZU(
23114663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               gregOfRexRM(pfx,modrm),
23115663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               unop( Iop_32UtoV128, getIReg32(eregOfRexRM(pfx,modrm)) )
23116663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            );
23117663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovd %s, %s\n", nameIReg32(eregOfRexRM(pfx,modrm)),
23118663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  nameXMMReg(gregOfRexRM(pfx,modrm)));
23119663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        } else {
23120663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 0 );
23121663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
23122663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putYMMRegLoAndZU(
23123663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               gregOfRexRM(pfx,modrm),
23124663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               unop( Iop_32UtoV128,loadLE(Ity_I32, mkexpr(addr)))
23125663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             );
23126663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovd %s, %s\n", dis_buf,
23127663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  nameXMMReg(gregOfRexRM(pfx,modrm)));
23128663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
23129663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
23130663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23131663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVQ r64/m64, xmm1 = VEX.128.66.0F.W1 6E */
23132663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
23133663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && 0==getVexL(pfx)/*128*/ && 1==getRexW(pfx)/*W1*/) {
23134663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(sz == 2); /* even tho we are transferring 8, not 2. */
23135663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar modrm = getUChar(delta);
23136663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
23137663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
23138663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putYMMRegLoAndZU(
23139663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               gregOfRexRM(pfx,modrm),
23140663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               unop( Iop_64UtoV128, getIReg64(eregOfRexRM(pfx,modrm)) )
23141663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            );
23142663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovq %s, %s\n", nameIReg64(eregOfRexRM(pfx,modrm)),
23143663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  nameXMMReg(gregOfRexRM(pfx,modrm)));
23144663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        } else {
23145663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 0 );
23146663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
23147663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putYMMRegLoAndZU(
23148663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               gregOfRexRM(pfx,modrm),
23149663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               unop( Iop_64UtoV128,loadLE(Ity_I64, mkexpr(addr)))
23150663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             );
23151663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovq %s, %s\n", dis_buf,
23152663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  nameXMMReg(gregOfRexRM(pfx,modrm)));
23153663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
23154663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
23155663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23156663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
23157663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
23158663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x6F:
23159663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVDQA ymm2/m256, ymm1 = VEX.256.66.0F.WIG 6F */
23160663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVDQU ymm2/m256, ymm1 = VEX.256.F3.0F.WIG 6F */
23161663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if ((have66noF2noF3(pfx) || haveF3no66noF2(pfx))
23162663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && 1==getVexL(pfx)/*256*/) {
23163663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm = getUChar(delta);
23164663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rD    = gregOfRexRM(pfx, modrm);
23165663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp tD    = newTemp(Ity_V256);
23166663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Bool   isA   = have66noF2noF3(pfx);
23167663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  ch    = isA ? 'a' : 'u';
23168663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
23169663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rS = eregOfRexRM(pfx, modrm);
23170663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
23171663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(tD, getYMMReg(rS));
23172663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovdq%c %s,%s\n", ch, nameYMMReg(rS), nameYMMReg(rD));
23173663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
23174663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 0 );
23175663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
23176663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (isA)
23177663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               gen_SEGV_if_not_32_aligned(addr);
23178663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(tD, loadLE(Ity_V256, mkexpr(addr)));
23179663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovdq%c %s,%s\n", ch, dis_buf, nameYMMReg(rD));
23180663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
23181663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMReg(rD, mkexpr(tD));
23182663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
23183663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23184663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVDQA xmm2/m128, xmm1 = VEX.128.66.0F.WIG 6F */
23185663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVDQU xmm2/m128, xmm1 = VEX.128.F3.0F.WIG 6F */
23186663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if ((have66noF2noF3(pfx) || haveF3no66noF2(pfx))
23187663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && 0==getVexL(pfx)/*128*/) {
23188663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm = getUChar(delta);
23189663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rD    = gregOfRexRM(pfx, modrm);
23190663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp tD    = newTemp(Ity_V128);
23191663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Bool   isA   = have66noF2noF3(pfx);
23192663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  ch    = isA ? 'a' : 'u';
23193663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
23194663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rS = eregOfRexRM(pfx, modrm);
23195663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
23196663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(tD, getXMMReg(rS));
23197663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovdq%c %s,%s\n", ch, nameXMMReg(rS), nameXMMReg(rD));
23198663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
23199663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 0 );
23200663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
23201663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (isA)
23202663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               gen_SEGV_if_not_16_aligned(addr);
23203663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(tD, loadLE(Ity_V128, mkexpr(addr)));
23204663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovdq%c %s,%s\n", ch, dis_buf, nameXMMReg(rD));
23205663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
23206663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLoAndZU(rD, mkexpr(tD));
23207663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
23208663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23209663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
23210663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
23211663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x70:
23212663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPSHUFD imm8, xmm2/m128, xmm1 = VEX.128.66.0F.WIG 70 /r ib */
23213663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
23214663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_PSHUFD_32x4( vbi, pfx, delta, True/*writesYmm*/);
23215663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
23216663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23217663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPSHUFLW imm8, xmm2/m128, xmm1 = VEX.128.F2.0F.WIG 70 /r ib */
23218663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2no66noF3(pfx) && 0==getVexL(pfx)/*128*/) {
23219663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_PSHUFxW_128( vbi, pfx, delta,
23220663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  True/*isAvx*/, False/*!xIsH*/ );
23221663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
23222663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23223663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPSHUFHW imm8, xmm2/m128, xmm1 = VEX.128.F3.0F.WIG 70 /r ib */
23224663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx) && 0==getVexL(pfx)/*128*/) {
23225663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_PSHUFxW_128( vbi, pfx, delta,
23226663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  True/*isAvx*/, True/*xIsH*/ );
23227663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
23228663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23229663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
23230663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
23231663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x71:
23232663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPSRLW imm8, xmm2, xmm1 = VEX.NDD.128.66.0F.WIG 71 /2 ib */
23233663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPSRAW imm8, xmm2, xmm1 = VEX.NDD.128.66.0F.WIG 71 /4 ib */
23234663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPSLLW imm8, xmm2, xmm1 = VEX.NDD.128.66.0F.WIG 71 /6 ib */
23235663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
23236663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && 0==getVexL(pfx)/*128*/
23237663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && epartIsReg(getUChar(delta))) {
23238663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (gregLO3ofRM(getUChar(delta)) == 2/*SRL*/) {
23239663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta = dis_AVX128_shiftE_to_V_imm( pfx, delta,
23240663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                                "vpsrlw", Iop_ShrN16x8 );
23241663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            *uses_vvvv = True;
23242663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            goto decode_success;
23243663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
23244663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (gregLO3ofRM(getUChar(delta)) == 4/*SRA*/) {
23245663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta = dis_AVX128_shiftE_to_V_imm( pfx, delta,
23246663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                                "vpsraw", Iop_SarN16x8 );
23247663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            *uses_vvvv = True;
23248663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            goto decode_success;
23249663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
23250663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (gregLO3ofRM(getUChar(delta)) == 6/*SLL*/) {
23251663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta = dis_AVX128_shiftE_to_V_imm( pfx, delta,
23252663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                                "vpsllw", Iop_ShlN16x8 );
23253663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            *uses_vvvv = True;
23254663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            goto decode_success;
23255663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
23256663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* else fall through */
23257663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23258663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
23259663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
23260663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x72:
23261663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPSRLD imm8, xmm2, xmm1 = VEX.NDD.128.66.0F.WIG 72 /2 ib */
23262663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPSRAD imm8, xmm2, xmm1 = VEX.NDD.128.66.0F.WIG 72 /4 ib */
23263663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPSLLD imm8, xmm2, xmm1 = VEX.NDD.128.66.0F.WIG 72 /6 ib */
23264663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
23265663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && 0==getVexL(pfx)/*128*/
23266663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && epartIsReg(getUChar(delta))) {
23267663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (gregLO3ofRM(getUChar(delta)) == 2/*SRL*/) {
23268663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta = dis_AVX128_shiftE_to_V_imm( pfx, delta,
23269663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                                "vpsrld", Iop_ShrN32x4 );
23270663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            *uses_vvvv = True;
23271663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            goto decode_success;
23272663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
23273663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (gregLO3ofRM(getUChar(delta)) == 4/*SRA*/) {
23274663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta = dis_AVX128_shiftE_to_V_imm( pfx, delta,
23275663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                                "vpsrad", Iop_SarN32x4 );
23276663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            *uses_vvvv = True;
23277663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            goto decode_success;
23278663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
23279663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (gregLO3ofRM(getUChar(delta)) == 6/*SLL*/) {
23280663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta = dis_AVX128_shiftE_to_V_imm( pfx, delta,
23281663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                                "vpslld", Iop_ShlN32x4 );
23282663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            *uses_vvvv = True;
23283663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            goto decode_success;
23284663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
23285663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* else fall through */
23286663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23287663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
23288663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
23289663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x73:
23290663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPSRLDQ imm8, xmm2, xmm1 = VEX.NDD.128.66.0F.WIG 73 /3 ib */
23291663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPSLLDQ imm8, xmm2, xmm1 = VEX.NDD.128.66.0F.WIG 73 /7 ib */
23292663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPSRLQ  imm8, xmm2, xmm1 = VEX.NDD.128.66.0F.WIG 73 /2 ib */
23293663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPSLLQ  imm8, xmm2, xmm1 = VEX.NDD.128.66.0F.WIG 73 /6 ib */
23294663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/
23295663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && epartIsReg(getUChar(delta))) {
23296663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int    rS   = eregOfRexRM(pfx,getUChar(delta));
23297663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int    rD   = getVexNvvvv(pfx);
23298663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp vecS = newTemp(Ity_V128);
23299663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (gregLO3ofRM(getUChar(delta)) == 3) {
23300663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            Int imm = (Int)getUChar(delta+1);
23301663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vpsrldq $%d,%s,%s\n", imm, nameXMMReg(rS), nameXMMReg(rD));
23302663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 2;
23303663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( vecS, getXMMReg(rS) );
23304663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putYMMRegLoAndZU(rD, mkexpr(math_PSRLDQ( vecS, imm )));
23305663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            *uses_vvvv = True;
23306663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            goto decode_success;
23307663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
23308663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (gregLO3ofRM(getUChar(delta)) == 7) {
23309663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            Int imm = (Int)getUChar(delta+1);
23310663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vpslldq $%d,%s,%s\n", imm, nameXMMReg(rS), nameXMMReg(rD));
23311663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 2;
23312663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( vecS, getXMMReg(rS) );
23313663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putYMMRegLoAndZU(rD, mkexpr(math_PSLLDQ( vecS, imm )));
23314663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            *uses_vvvv = True;
23315663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            goto decode_success;
23316663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
23317663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (gregLO3ofRM(getUChar(delta)) == 2) {
23318663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta = dis_AVX128_shiftE_to_V_imm( pfx, delta,
23319663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                                "vpsrlq", Iop_ShrN64x2 );
23320663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            *uses_vvvv = True;
23321663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            goto decode_success;
23322663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
23323663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (gregLO3ofRM(getUChar(delta)) == 6) {
23324663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta = dis_AVX128_shiftE_to_V_imm( pfx, delta,
23325663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                                "vpsllq", Iop_ShlN64x2 );
23326663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            *uses_vvvv = True;
23327663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            goto decode_success;
23328663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
23329663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* else fall through */
23330663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23331663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
23332663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
23333663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x74:
23334663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPCMPEQB r/m, rV, r ::: r = rV `eq-by-8s` r/m */
23335663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPCMPEQB = VEX.NDS.128.66.0F.WIG 74 /r */
23336663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
23337663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG_simple(
23338663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpcmpeqb", Iop_CmpEQ8x16 );
23339663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
23340663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23341663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
23342663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
23343663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x75:
23344663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPCMPEQW r/m, rV, r ::: r = rV `eq-by-16s` r/m */
23345663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPCMPEQW = VEX.NDS.128.66.0F.WIG 75 /r */
23346663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
23347663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG_simple(
23348663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpcmpeqw", Iop_CmpEQ16x8 );
23349663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
23350663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23351663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
23352663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
23353663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x76:
23354663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPCMPEQD r/m, rV, r ::: r = rV `eq-by-32s` r/m */
23355663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPCMPEQD = VEX.NDS.128.66.0F.WIG 76 /r */
23356663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
23357663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG_simple(
23358663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpcmpeqd", Iop_CmpEQ32x4 );
23359663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
23360663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23361663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
23362663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
23363663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x77:
23364663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VZEROUPPER = VEX.128.0F.WIG 77 */
23365663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
23366663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int i;
23367663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp zero128 = newTemp(Ity_V128);
23368663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(zero128, mkV128(0));
23369663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         for (i = 0; i < 16; i++) {
23370663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putYMMRegLane128(i, 1, mkexpr(zero128));
23371663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
23372663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("vzeroupper\n");
23373663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
23374663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23375663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VZEROALL = VEX.256.0F.WIG 77 */
23376663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
23377663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int i;
23378663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp zero128 = newTemp(Ity_V128);
23379663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(zero128, mkV128(0));
23380663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         for (i = 0; i < 16; i++) {
23381663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putYMMRegLoAndZU(i, mkexpr(zero128));
23382663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
23383663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("vzeroall\n");
23384663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
23385663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23386663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
23387663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
23388663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x7C:
23389663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x7D:
23390663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VHADDPS xmm3/m128, xmm2, xmm1 = VEX.NDS.128.F2.0F.WIG 7C /r */
23391663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VHSUBPS xmm3/m128, xmm2, xmm1 = VEX.NDS.128.F2.0F.WIG 7D /r */
23392663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2no66noF3(pfx) && 0==getVexL(pfx)/*128*/) {
23393663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sV     = newTemp(Ity_V128);
23394663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dV     = newTemp(Ity_V128);
23395663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Bool   isAdd  = opc == 0x7C;
23396663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HChar* str    = isAdd ? "add" : "sub";
23397663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar modrm   = getUChar(delta);
23398663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG     = gregOfRexRM(pfx,modrm);
23399663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rV     = getVexNvvvv(pfx);
23400663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
23401663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
23402663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, getXMMReg(rE) );
23403663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vh%spd %s,%s,%s\n", str, nameXMMReg(rE),
23404663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                nameXMMReg(rV), nameXMMReg(rG));
23405663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
23406663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
23407663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
23408663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
23409663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vh%spd %s,%s,%s\n", str, dis_buf,
23410663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                nameXMMReg(rV), nameXMMReg(rG));
23411663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
23412663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
23413663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( dV, getXMMReg(rV) );
23414663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLoAndZU( rG, mkexpr( math_HADDPS_128 ( dV, sV, isAdd ) ) );
23415663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
23416663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
23417663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23418663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VHADDPS ymm3/m256, ymm2, ymm1 = VEX.NDS.256.F2.0F.WIG 7C /r */
23419663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VHSUBPS ymm3/m256, ymm2, ymm1 = VEX.NDS.256.F2.0F.WIG 7D /r */
23420663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2no66noF3(pfx) && 1==getVexL(pfx)/*256*/) {
23421663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sV     = newTemp(Ity_V256);
23422663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dV     = newTemp(Ity_V256);
23423663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp s1, s0, d1, d0;
23424663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Bool   isAdd  = opc == 0x7C;
23425663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HChar* str    = isAdd ? "add" : "sub";
23426663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar modrm   = getUChar(delta);
23427663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG     = gregOfRexRM(pfx,modrm);
23428663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rV     = getVexNvvvv(pfx);
23429663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         s1 = s0 = d1 = d0 = IRTemp_INVALID;
23430663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
23431663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
23432663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, getYMMReg(rE) );
23433663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vh%spd %s,%s,%s\n", str, nameYMMReg(rE),
23434663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                nameYMMReg(rV), nameYMMReg(rG));
23435663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
23436663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
23437663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
23438663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, loadLE(Ity_V256, mkexpr(addr)) );
23439663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vh%spd %s,%s,%s\n", str, dis_buf,
23440663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                nameYMMReg(rV), nameYMMReg(rG));
23441663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
23442663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
23443663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( dV, getYMMReg(rV) );
23444663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         breakupV256toV128s( dV, &d1, &d0 );
23445663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         breakupV256toV128s( sV, &s1, &s0 );
23446663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMReg( rG, binop(Iop_V128HLtoV256,
23447663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              mkexpr( math_HADDPS_128 ( d1, s1, isAdd ) ),
23448663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              mkexpr( math_HADDPS_128 ( d0, s0, isAdd ) ) ) );
23449663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
23450663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
23451663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23452663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VHADDPD xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F.WIG 7C /r */
23453663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VHSUBPD xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F.WIG 7D /r */
23454663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
23455663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sV     = newTemp(Ity_V128);
23456663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dV     = newTemp(Ity_V128);
23457663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Bool   isAdd  = opc == 0x7C;
23458663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HChar* str    = isAdd ? "add" : "sub";
23459663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar modrm   = getUChar(delta);
23460663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG     = gregOfRexRM(pfx,modrm);
23461663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rV     = getVexNvvvv(pfx);
23462663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
23463663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
23464663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, getXMMReg(rE) );
23465663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vh%spd %s,%s,%s\n", str, nameXMMReg(rE),
23466663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                nameXMMReg(rV), nameXMMReg(rG));
23467663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
23468663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
23469663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
23470663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
23471663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vh%spd %s,%s,%s\n", str, dis_buf,
23472663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                nameXMMReg(rV), nameXMMReg(rG));
23473663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
23474663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
23475663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( dV, getXMMReg(rV) );
23476663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLoAndZU( rG, mkexpr( math_HADDPD_128 ( dV, sV, isAdd ) ) );
23477663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
23478663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
23479663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23480663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VHADDPD ymm3/m256, ymm2, ymm1 = VEX.NDS.256.66.0F.WIG 7C /r */
23481663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VHSUBPD ymm3/m256, ymm2, ymm1 = VEX.NDS.256.66.0F.WIG 7D /r */
23482663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
23483663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sV     = newTemp(Ity_V256);
23484663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dV     = newTemp(Ity_V256);
23485663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp s1, s0, d1, d0;
23486663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Bool   isAdd  = opc == 0x7C;
23487663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HChar* str    = isAdd ? "add" : "sub";
23488663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar modrm   = getUChar(delta);
23489663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG     = gregOfRexRM(pfx,modrm);
23490663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rV     = getVexNvvvv(pfx);
23491663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         s1 = s0 = d1 = d0 = IRTemp_INVALID;
23492663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
23493663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
23494663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, getYMMReg(rE) );
23495663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vh%spd %s,%s,%s\n", str, nameYMMReg(rE),
23496663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                nameYMMReg(rV), nameYMMReg(rG));
23497663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
23498663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
23499663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
23500663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, loadLE(Ity_V256, mkexpr(addr)) );
23501663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vh%spd %s,%s,%s\n", str, dis_buf,
23502663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                nameYMMReg(rV), nameYMMReg(rG));
23503663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
23504663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
23505663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( dV, getYMMReg(rV) );
23506663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         breakupV256toV128s( dV, &d1, &d0 );
23507663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         breakupV256toV128s( sV, &s1, &s0 );
23508663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMReg( rG, binop(Iop_V128HLtoV256,
23509663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              mkexpr( math_HADDPD_128 ( d1, s1, isAdd ) ),
23510663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              mkexpr( math_HADDPD_128 ( d0, s0, isAdd ) ) ) );
23511663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
23512663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
23513663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23514663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
23515663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
23516663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x7E:
23517663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Note the Intel docs don't make sense for this.  I think they
23518663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         are wrong.  They seem to imply it is a store when in fact I
23519663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         think it is a load.  Also it's unclear whether this is W0, W1
23520663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         or WIG. */
23521663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVQ xmm2/m64, xmm1 = VEX.128.F3.0F.W0 7E /r */
23522663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx)
23523663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && 0==getVexL(pfx)/*128*/ && 0==getRexW(pfx)/*W0*/) {
23524663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(sz == 4); /* even tho we are transferring 8, not 4. */
23525663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar modrm = getUChar(delta);
23526663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rG    = gregOfRexRM(pfx,modrm);
23527663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
23528663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
23529663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putXMMRegLane64( rG, 0, getXMMRegLane64( rE, 0 ));
23530663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovq %s,%s\n", nameXMMReg(rE), nameXMMReg(rG));
23531663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
23532663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
23533663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
23534663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putXMMRegLane64( rG, 0, loadLE(Ity_I64, mkexpr(addr)) );
23535663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovq %s,%s\n", dis_buf, nameXMMReg(rG));
23536663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
23537663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
23538663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* zero bits 255:64 */
23539663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMRegLane64( rG, 1, mkU64(0) );
23540663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLane128( rG, 1, mkV128(0) );
23541663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
23542663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23543663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVQ xmm1, r64 = VEX.128.66.0F.W1 7E /r (reg case only) */
23544663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Moves from G to E, so is a store-form insn */
23545663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Intel docs list this in the VMOVD entry for some reason. */
23546663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
23547663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && 0==getVexL(pfx)/*128*/ && 1==getRexW(pfx)/*W1*/) {
23548663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar modrm = getUChar(delta);
23549663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rG    = gregOfRexRM(pfx,modrm);
23550663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
23551663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
23552663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovq %s,%s\n", nameXMMReg(rG), nameIReg64(rE));
23553663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putIReg64(rE, getXMMRegLane64(rG, 0));
23554663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
23555663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
23556663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
23557663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            storeLE( mkexpr(addr), getXMMRegLane64(rG, 0) );
23558663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovq %s,%s\n", dis_buf, nameXMMReg(rG));
23559663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
23560663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
23561663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
23562663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23563663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVD xmm1, m32/r32 = VEX.128.66.0F.W0 7E /r (reg case only) */
23564663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Moves from G to E, so is a store-form insn */
23565663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
23566663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && 0==getVexL(pfx)/*128*/ && 0==getRexW(pfx)/*W0*/) {
23567663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar modrm = getUChar(delta);
23568663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rG    = gregOfRexRM(pfx,modrm);
23569663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
23570663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
23571663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovd %s,%s\n", nameXMMReg(rG), nameIReg32(rE));
23572663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putIReg32(rE, getXMMRegLane32(rG, 0));
23573663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
23574663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
23575663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
23576663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            storeLE( mkexpr(addr), getXMMRegLane32(rG, 0) );
23577663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovd %s,%s\n", dis_buf, nameXMMReg(rG));
23578663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
23579663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
23580663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
23581663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23582663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
23583663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
23584663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x7F:
23585663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVDQA ymm1, ymm2/m256 = VEX.256.66.0F.WIG 7F */
23586663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVDQU ymm1, ymm2/m256 = VEX.256.F3.0F.WIG 7F */
23587663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if ((have66noF2noF3(pfx) || haveF3no66noF2(pfx))
23588663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && 1==getVexL(pfx)/*256*/) {
23589663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm = getUChar(delta);
23590663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rS    = gregOfRexRM(pfx, modrm);
23591663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp tS    = newTemp(Ity_V256);
23592663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Bool   isA   = have66noF2noF3(pfx);
23593663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  ch    = isA ? 'a' : 'u';
23594663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(tS, getYMMReg(rS));
23595663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
23596663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rD = eregOfRexRM(pfx, modrm);
23597663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
23598663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putYMMReg(rD, mkexpr(tS));
23599663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovdq%c %s,%s\n", ch, nameYMMReg(rS), nameYMMReg(rD));
23600663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
23601663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 0 );
23602663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
23603663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (isA)
23604663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               gen_SEGV_if_not_32_aligned(addr);
23605663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            storeLE(mkexpr(addr), mkexpr(tS));
23606663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovdq%c %s,%s\n", ch, nameYMMReg(rS), dis_buf);
23607663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
23608663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
23609663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23610663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVDQA xmm1, xmm2/m128 = VEX.128.66.0F.WIG 7F */
23611663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVDQU xmm1, xmm2/m128 = VEX.128.F3.0F.WIG 7F */
23612663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if ((have66noF2noF3(pfx) || haveF3no66noF2(pfx))
23613663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && 0==getVexL(pfx)/*128*/) {
23614663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm = getUChar(delta);
23615663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rS    = gregOfRexRM(pfx, modrm);
23616663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp tS    = newTemp(Ity_V128);
23617663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Bool   isA   = have66noF2noF3(pfx);
23618663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  ch    = isA ? 'a' : 'u';
23619663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(tS, getXMMReg(rS));
23620663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
23621663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rD = eregOfRexRM(pfx, modrm);
23622663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
23623663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putYMMRegLoAndZU(rD, mkexpr(tS));
23624663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovdq%c %s,%s\n", ch, nameXMMReg(rS), nameXMMReg(rD));
23625663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
23626663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 0 );
23627663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
23628663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (isA)
23629663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               gen_SEGV_if_not_16_aligned(addr);
23630663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            storeLE(mkexpr(addr), mkexpr(tS));
23631663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovdq%c %s,%s\n", ch, nameXMMReg(rS), dis_buf);
23632663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
23633663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
23634663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23635663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
23636663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
23637663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xAE:
23638663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VSTMXCSR m32 = VEX.LZ.0F.WIG AE /3 */
23639663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx)
23640663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && 0==getVexL(pfx)/*LZ*/
23641663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && 0==getRexW(pfx) /* be paranoid -- Intel docs don't require this */
23642663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && !epartIsReg(getUChar(delta)) && gregLO3ofRM(getUChar(delta)) == 3
23643663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && sz == 4) {
23644663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_STMXCSR(vbi, pfx, delta, True/*isAvx*/);
23645663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
23646663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23647663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VLDMXCSR m32 = VEX.LZ.0F.WIG AE /2 */
23648663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx)
23649663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && 0==getVexL(pfx)/*LZ*/
23650663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && 0==getRexW(pfx) /* be paranoid -- Intel docs don't require this */
23651663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && !epartIsReg(getUChar(delta)) && gregLO3ofRM(getUChar(delta)) == 2
23652663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && sz == 4) {
23653663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_LDMXCSR(vbi, pfx, delta, True/*isAvx*/);
23654663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
23655663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23656663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
23657663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
23658663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xC2:
23659663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VCMPSD xmm3/m64(E=argL), xmm2(V=argR), xmm1(G) */
23660663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* = VEX.NDS.LIG.F2.0F.WIG C2 /r ib */
23661663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2no66noF3(pfx)) {
23662663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Long delta0 = delta;
23663663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_cmp_V_E_to_G( uses_vvvv, vbi, pfx, delta,
23664663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                          "vcmpsd", False/*!all_lanes*/,
23665663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                          8/*sz*/);
23666663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (delta > delta0) goto decode_success;
23667663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* else fall through -- decoding has failed */
23668663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23669663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VCMPSS xmm3/m32(E=argL), xmm2(V=argR), xmm1(G) */
23670663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* = VEX.NDS.LIG.F3.0F.WIG C2 /r ib */
23671663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx)) {
23672663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Long delta0 = delta;
23673663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_cmp_V_E_to_G( uses_vvvv, vbi, pfx, delta,
23674663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                          "vcmpss", False/*!all_lanes*/,
23675663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                          4/*sz*/);
23676663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (delta > delta0) goto decode_success;
23677663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* else fall through -- decoding has failed */
23678663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23679663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VCMPPD xmm3/m128(E=argL), xmm2(V=argR), xmm1(G) */
23680663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* = VEX.NDS.128.66.0F.WIG C2 /r ib */
23681663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
23682663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Long delta0 = delta;
23683663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_cmp_V_E_to_G( uses_vvvv, vbi, pfx, delta,
23684663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                          "vcmppd", True/*all_lanes*/,
23685663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                          8/*sz*/);
23686663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (delta > delta0) goto decode_success;
23687663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* else fall through -- decoding has failed */
23688663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23689663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VCMPPD ymm3/m256(E=argL), ymm2(V=argR), ymm1(G) */
23690663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* = VEX.NDS.256.66.0F.WIG C2 /r ib */
23691663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
23692663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Long delta0 = delta;
23693663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX256_cmp_V_E_to_G( uses_vvvv, vbi, pfx, delta,
23694663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                          "vcmppd", 8/*sz*/);
23695663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (delta > delta0) goto decode_success;
23696663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* else fall through -- decoding has failed */
23697663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23698663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VCMPPS xmm3/m128(E=argL), xmm2(V=argR), xmm1(G) */
23699663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* = VEX.NDS.128.0F.WIG C2 /r ib */
23700663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
23701663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Long delta0 = delta;
23702663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_cmp_V_E_to_G( uses_vvvv, vbi, pfx, delta,
23703663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                          "vcmpps", True/*all_lanes*/,
23704663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                          4/*sz*/);
23705663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (delta > delta0) goto decode_success;
23706663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* else fall through -- decoding has failed */
23707663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23708663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VCMPPS ymm3/m256(E=argL), ymm2(V=argR), ymm1(G) */
23709663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* = VEX.NDS.256.0F.WIG C2 /r ib */
23710663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
23711663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Long delta0 = delta;
23712663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX256_cmp_V_E_to_G( uses_vvvv, vbi, pfx, delta,
23713663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                          "vcmpps", 4/*sz*/);
23714663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (delta > delta0) goto decode_success;
23715663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* else fall through -- decoding has failed */
23716663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23717663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
23718663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
23719663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xC4:
23720663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPINSRW r32/m16, xmm2, xmm1 = VEX.NDS.128.66.0F.WIG C4 /r ib */
23721663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
23722663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm = getUChar(delta);
23723663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG    = gregOfRexRM(pfx, modrm);
23724663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rV    = getVexNvvvv(pfx);
23725663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int    imm8;
23726663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp new16 = newTemp(Ity_I16);
23727663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
23728663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if ( epartIsReg( modrm ) ) {
23729663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = (Int)(getUChar(delta+1) & 7);
23730663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( new16, unop(Iop_32to16,
23731663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                getIReg32(eregOfRexRM(pfx,modrm))) );
23732663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1+1;
23733663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "vpinsrw $%d,%s,%s\n", imm8,
23734663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 nameIReg32( eregOfRexRM(pfx, modrm) ), nameXMMReg(rG) );
23735663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
23736663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 1 );
23737663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = (Int)(getUChar(delta+alen) & 7);
23738663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( new16, loadLE( Ity_I16, mkexpr(addr) ));
23739663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen+1;
23740663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "vpinsrw $%d,%s,%s\n",
23741663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 imm8, dis_buf, nameXMMReg(rG) );
23742663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
23743663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
23744663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp src_vec = newTemp(Ity_V128);
23745663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(src_vec, getXMMReg( rV ));
23746663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp res_vec = math_PINSRW_128( src_vec, new16, imm8 );
23747663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLoAndZU( rG, mkexpr(res_vec) );
23748663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
23749663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
23750663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23751663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
23752663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
23753663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xC5:
23754663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPEXTRW imm8, xmm1, reg32 = VEX.128.66.0F.W0 C5 /r ib */
23755663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
23756663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         && 0==getVexL(pfx)/*128*/ && 0==getRexW(pfx)/*W0*/) {
23757663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Long delta0 = delta;
23758663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_PEXTRW_128_EregOnly_toG( vbi, pfx, delta,
23759663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                              True/*isAvx*/ );
23760663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (delta > delta0) goto decode_success;
23761663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* else fall through -- decoding has failed */
23762663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23763663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
23764663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
23765663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xC6:
23766663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VSHUFPS imm8, xmm3/m128, xmm2, xmm1, xmm2 */
23767663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* = VEX.NDS.128.0F.WIG C6 /r ib */
23768663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
23769663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int    imm8 = 0;
23770663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp eV   = newTemp(Ity_V128);
23771663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp vV   = newTemp(Ity_V128);
23772663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  modrm = getUChar(delta);
23773663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rG    = gregOfRexRM(pfx,modrm);
23774663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rV    = getVexNvvvv(pfx);
23775663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( vV, getXMMReg(rV) );
23776663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
23777663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
23778663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( eV, getXMMReg(rE) );
23779663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = (Int)getUChar(delta+1);
23780663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1+1;
23781663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vshufps $%d,%s,%s,%s\n",
23782663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                imm8, nameXMMReg(rE), nameXMMReg(rV), nameXMMReg(rG));
23783663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
23784663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 1 );
23785663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( eV, loadLE(Ity_V128, mkexpr(addr)) );
23786663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = (Int)getUChar(delta+alen);
23787663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1+alen;
23788663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vshufps $%d,%s,%s,%s\n",
23789663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                imm8, dis_buf, nameXMMReg(rV), nameXMMReg(rG));
23790663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
23791663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp res = math_SHUFPS_128( eV, vV, imm8 );
23792663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLoAndZU( rG, mkexpr(res) );
23793663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
23794663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
23795663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23796663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VSHUFPS imm8, ymm3/m256, ymm2, ymm1, ymm2 */
23797663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* = VEX.NDS.256.0F.WIG C6 /r ib */
23798663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveNo66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
23799663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int    imm8 = 0;
23800663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp eV   = newTemp(Ity_V256);
23801663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp vV   = newTemp(Ity_V256);
23802663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  modrm = getUChar(delta);
23803663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rG    = gregOfRexRM(pfx,modrm);
23804663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rV    = getVexNvvvv(pfx);
23805663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( vV, getYMMReg(rV) );
23806663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
23807663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
23808663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( eV, getYMMReg(rE) );
23809663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = (Int)getUChar(delta+1);
23810663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1+1;
23811663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vshufps $%d,%s,%s,%s\n",
23812663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                imm8, nameYMMReg(rE), nameYMMReg(rV), nameYMMReg(rG));
23813663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
23814663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 1 );
23815663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( eV, loadLE(Ity_V256, mkexpr(addr)) );
23816663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = (Int)getUChar(delta+alen);
23817663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1+alen;
23818663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vshufps $%d,%s,%s,%s\n",
23819663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                imm8, dis_buf, nameYMMReg(rV), nameYMMReg(rG));
23820663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
23821663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp res = math_SHUFPS_256( eV, vV, imm8 );
23822663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMReg( rG, mkexpr(res) );
23823663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
23824663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
23825663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23826663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VSHUFPD imm8, xmm3/m128, xmm2, xmm1, xmm2 */
23827663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* = VEX.NDS.128.66.0F.WIG C6 /r ib */
23828663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
23829663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int    imm8 = 0;
23830663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp eV   = newTemp(Ity_V128);
23831663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp vV   = newTemp(Ity_V128);
23832663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  modrm = getUChar(delta);
23833663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rG    = gregOfRexRM(pfx,modrm);
23834663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rV    = getVexNvvvv(pfx);
23835663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( vV, getXMMReg(rV) );
23836663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
23837663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
23838663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( eV, getXMMReg(rE) );
23839663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = (Int)getUChar(delta+1);
23840663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1+1;
23841663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vshufpd $%d,%s,%s,%s\n",
23842663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                imm8, nameXMMReg(rE), nameXMMReg(rV), nameXMMReg(rG));
23843663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
23844663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 1 );
23845663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( eV, loadLE(Ity_V128, mkexpr(addr)) );
23846663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = (Int)getUChar(delta+alen);
23847663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1+alen;
23848663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vshufpd $%d,%s,%s,%s\n",
23849663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                imm8, dis_buf, nameXMMReg(rV), nameXMMReg(rG));
23850663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
23851663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp res = math_SHUFPD_128( eV, vV, imm8 );
23852663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLoAndZU( rG, mkexpr(res) );
23853663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
23854663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
23855663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23856663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VSHUFPD imm8, ymm3/m256, ymm2, ymm1, ymm2 */
23857663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* = VEX.NDS.256.66.0F.WIG C6 /r ib */
23858663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
23859663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int    imm8 = 0;
23860663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp eV   = newTemp(Ity_V256);
23861663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp vV   = newTemp(Ity_V256);
23862663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  modrm = getUChar(delta);
23863663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rG    = gregOfRexRM(pfx,modrm);
23864663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rV    = getVexNvvvv(pfx);
23865663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( vV, getYMMReg(rV) );
23866663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
23867663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
23868663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( eV, getYMMReg(rE) );
23869663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = (Int)getUChar(delta+1);
23870663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1+1;
23871663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vshufpd $%d,%s,%s,%s\n",
23872663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                imm8, nameYMMReg(rE), nameYMMReg(rV), nameYMMReg(rG));
23873663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
23874663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 1 );
23875663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( eV, loadLE(Ity_V256, mkexpr(addr)) );
23876663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = (Int)getUChar(delta+alen);
23877663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1+alen;
23878663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vshufpd $%d,%s,%s,%s\n",
23879663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                imm8, dis_buf, nameYMMReg(rV), nameYMMReg(rG));
23880663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
23881663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp res = math_SHUFPD_256( eV, vV, imm8 );
23882663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMReg( rG, mkexpr(res) );
23883663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
23884663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
23885663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23886663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
23887663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
23888663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xD0:
23889663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VADDSUBPD xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F.WIG D0 /r */
23890663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
23891663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG_complex(
23892663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta,
23893663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    "vaddsubpd", math_ADDSUBPD_128 );
23894663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
23895663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23896663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VADDSUBPD ymm3/m256, ymm2, ymm1 = VEX.NDS.256.66.0F.WIG D0 /r */
23897663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
23898663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_256_AnySimdPfx_0F_WIG_complex(
23899663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta,
23900663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    "vaddsubpd", math_ADDSUBPD_256 );
23901663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
23902663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23903663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VADDSUBPS xmm3/m128, xmm2, xmm1 = VEX.NDS.128.F2.0F.WIG D0 /r */
23904663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2no66noF3(pfx) && 0==getVexL(pfx)/*128*/) {
23905663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG_complex(
23906663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta,
23907663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    "vaddsubps", math_ADDSUBPS_128 );
23908663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
23909663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23910663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VADDSUBPS ymm3/m256, ymm2, ymm1 = VEX.NDS.256.F2.0F.WIG D0 /r */
23911663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2no66noF3(pfx) && 1==getVexL(pfx)/*256*/) {
23912663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_256_AnySimdPfx_0F_WIG_complex(
23913663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta,
23914663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    "vaddsubps", math_ADDSUBPS_256 );
23915663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
23916663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23917663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
23918663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
23919663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xD1:
23920663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPSRLW xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F.WIG D1 /r */
23921663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
23922663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_shiftV_byE( vbi, pfx, delta,
23923663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        "vpsrlw", Iop_ShrN16x8 );
23924663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
23925663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
23926663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
23927663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23928663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
23929663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
23930663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xD2:
23931663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPSRLD xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F.WIG D2 /r */
23932663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
23933663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_shiftV_byE( vbi, pfx, delta,
23934663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        "vpsrld", Iop_ShrN32x4 );
23935663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
23936663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
23937663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23938663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
23939663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
23940663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xD3:
23941663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPSRLQ xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F.WIG D3 /r */
23942663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
23943663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_shiftV_byE( vbi, pfx, delta,
23944663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        "vpsrlq", Iop_ShrN64x2 );
23945663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
23946663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
23947663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23948663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
23949663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
23950663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xD4:
23951663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPADDQ r/m, rV, r ::: r = rV + r/m */
23952663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPADDQ = VEX.NDS.128.66.0F.WIG D4 /r */
23953663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
23954663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG_simple(
23955663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpaddq", Iop_Add64x2 );
23956663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
23957663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23958663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
23959663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
23960663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xD5:
23961663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMULLW xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F.WIG D5 /r */
23962663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
23963663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_E_V_to_G(
23964663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpmullw", Iop_Mul16x8 );
23965663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
23966663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23967663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
23968663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
23969663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xD6:
23970663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* I can't even find any Intel docs for this one. */
23971663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Basically: 66 0F D6 = MOVQ -- move 64 bits from G (lo half
23972663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         xmm) to E (mem or lo half xmm).  Looks like L==0(128), W==0
23973663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         (WIG, maybe?) */
23974663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/
23975663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && 0==getRexW(pfx)/*this might be redundant, dunno*/) {
23976663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar modrm = getUChar(delta);
23977663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rG    = gregOfRexRM(pfx,modrm);
23978663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
23979663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* fall through, awaiting test case */
23980663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* dst: lo half copied, hi half zeroed */
23981663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
23982663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
23983663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            storeLE( mkexpr(addr), getXMMRegLane64( rG, 0 ));
23984663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovq %s,%s\n", nameXMMReg(rG), dis_buf );
23985663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
23986663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            goto decode_success;
23987663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
23988663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23989663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
23990663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
23991663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xD7:
23992663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VEX.128.66.0F.WIG D7 /r = VPMOVMSKB xmm1, r32 */
23993663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
23994663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_PMOVMSKB_128( vbi, pfx, delta, True/*isAvx*/ );
23995663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
23996663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
23997663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
23998663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
23999663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xD8:
24000663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPSUBUSB xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F.WIG D8 /r */
24001663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24002663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_E_V_to_G(
24003663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpsubusb", Iop_QSub8Ux16 );
24004663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24005663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24006663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     break;
24007663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24008663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xD9:
24009663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPSUBUSW xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F.WIG D9 /r */
24010663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24011663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_E_V_to_G(
24012663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpsubusw", Iop_QSub16Ux8 );
24013663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24014663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24015663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24016663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24017663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xDA:
24018663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMINUB xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F.WIG DA /r */
24019663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24020663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_E_V_to_G(
24021663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpminub", Iop_Min8Ux16 );
24022663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24023663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24024663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24025663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24026663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xDB:
24027663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPAND r/m, rV, r ::: r = rV & r/m */
24028663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VEX.NDS.128.66.0F.WIG DB /r = VPAND xmm3/m128, xmm2, xmm1 */
24029663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24030663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG_simple(
24031663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpand", Iop_AndV128 );
24032663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24033663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24034663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24035663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24036663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xDC:
24037663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPADDUSB xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F.WIG DC /r */
24038663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24039663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_E_V_to_G(
24040663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpaddusb", Iop_QAdd8Ux16 );
24041663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24042663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24043663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24044663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24045663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xDD:
24046663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPADDUSW xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F.WIG DD /r */
24047663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24048663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_E_V_to_G(
24049663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpaddusw", Iop_QAdd16Ux8 );
24050663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24051663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24052663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24053663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24054663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xDE:
24055663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMAXUB xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F.WIG DE /r */
24056663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24057663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_E_V_to_G(
24058663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpmaxub", Iop_Max8Ux16 );
24059663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24060663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24061663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24062663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24063663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xDF:
24064663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPANDN r/m, rV, r ::: r = rV & ~r/m (is that correct, re the ~ ?) */
24065663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VEX.NDS.128.66.0F.WIG DF /r = VPANDN xmm3/m128, xmm2, xmm1 */
24066663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24067663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG(
24068663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpandn", Iop_AndV128,
24069663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    NULL, True/*invertLeftArg*/, False/*swapArgs*/ );
24070663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24071663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24072663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24073663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24074663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xE0:
24075663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPAVGB xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F.WIG E0 /r */
24076663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24077663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_E_V_to_G(
24078663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpavgb", Iop_Avg8Ux16 );
24079663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24080663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24081663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24082663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24083663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xE1:
24084663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPSRAW xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F.WIG E1 /r */
24085663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24086663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_shiftV_byE( vbi, pfx, delta,
24087663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        "vpsraw", Iop_SarN16x8 );
24088663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
24089663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24090663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24091663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24092663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24093663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xE2:
24094663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPSRAD xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F.WIG E2 /r */
24095663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24096663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_shiftV_byE( vbi, pfx, delta,
24097663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        "vpsrad", Iop_SarN32x4 );
24098663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
24099663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24100663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24101663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24102663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24103663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xE3:
24104663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPAVGW xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F.WIG E3 /r */
24105663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24106663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_E_V_to_G(
24107663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpavgw", Iop_Avg16Ux8 );
24108663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24109663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24110663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24111663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24112663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xE4:
24113663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMULHUW xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F.WIG E4 /r */
24114663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24115663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_E_V_to_G(
24116663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpmulhuw", Iop_MulHi16Ux8 );
24117663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24118663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24119663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24120663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24121663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xE5:
24122663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMULHW xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F.WIG E5 /r */
24123663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24124663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_E_V_to_G(
24125663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpmulhw", Iop_MulHi16Sx8 );
24126663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24127663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24128663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24129663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24130663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xE6:
24131663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VCVTDQ2PD xmm2/m64, xmm1 = VEX.128.F3.0F.WIG E6 /r */
24132663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx) && 0==getVexL(pfx)/*128*/) {
24133663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_CVTDQ2PD_128(vbi, pfx, delta, True/*isAvx*/);
24134663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24135663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24136663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VCVTDQ2PD xmm2/m128, ymm1 = VEX.256.F3.0F.WIG E6 /r */
24137663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF3no66noF2(pfx) && 1==getVexL(pfx)/*256*/) {
24138663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_CVTDQ2PD_256(vbi, pfx, delta);
24139663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24140663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24141663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VCVTTPD2DQ xmm2/m128, xmm1 = VEX.128.66.0F.WIG E6 /r */
24142663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24143663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_CVTxPD2DQ_128(vbi, pfx, delta, True/*isAvx*/,
24144663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   True/*r2zero*/);
24145663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24146663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24147663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VCVTTPD2DQ ymm2/m256, xmm1 = VEX.256.66.0F.WIG E6 /r */
24148663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
24149663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_CVTxPD2DQ_256(vbi, pfx, delta, True/*r2zero*/);
24150663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24151663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24152663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VCVTPD2DQ xmm2/m128, xmm1 = VEX.128.F2.0F.WIG E6 /r */
24153663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2no66noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24154663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_CVTxPD2DQ_128(vbi, pfx, delta, True/*isAvx*/,
24155663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   False/*!r2zero*/);
24156663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24157663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24158663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VCVTPD2DQ ymm2/m256, xmm1 = VEX.256.F2.0F.WIG E6 /r */
24159663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2no66noF3(pfx) && 1==getVexL(pfx)/*256*/) {
24160663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_CVTxPD2DQ_256(vbi, pfx, delta, False/*!r2zero*/);
24161663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24162663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24163663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24164663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24165663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xE7:
24166663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVNTDQ xmm1, m128 = VEX.128.66.0F.WIG E7 /r */
24167663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24168663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar modrm = getUChar(delta);
24169663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt rG     = gregOfRexRM(pfx,modrm);
24170663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (!epartIsReg(modrm)) {
24171663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
24172663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gen_SEGV_if_not_16_aligned( addr );
24173663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            storeLE( mkexpr(addr), getXMMReg(rG) );
24174663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovntdq %s,%s\n", dis_buf, nameXMMReg(rG));
24175663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
24176663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            goto decode_success;
24177663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
24178663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* else fall through */
24179663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24180663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVNTDQ ymm1, m256 = VEX.256.66.0F.WIG E7 /r */
24181663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
24182663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar modrm = getUChar(delta);
24183663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt rG     = gregOfRexRM(pfx,modrm);
24184663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (!epartIsReg(modrm)) {
24185663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
24186663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gen_SEGV_if_not_32_aligned( addr );
24187663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            storeLE( mkexpr(addr), getYMMReg(rG) );
24188663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vmovntdq %s,%s\n", dis_buf, nameYMMReg(rG));
24189663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
24190663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            goto decode_success;
24191663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
24192663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* else fall through */
24193663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24194663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24195663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24196663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xE8:
24197663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPSUBSB xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F.WIG E8 /r */
24198663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24199663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_E_V_to_G(
24200663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpsubsb", Iop_QSub8Sx16 );
24201663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24202663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24203663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24204663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24205663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xE9:
24206663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPSUBSW xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F.WIG E9 /r */
24207663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24208663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_E_V_to_G(
24209663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpsubsw", Iop_QSub16Sx8 );
24210663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24211663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24212663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24213663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24214663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xEA:
24215663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMINSW r/m, rV, r ::: r = min-signed16s(rV, r/m) */
24216663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMINSW = VEX.NDS.128.66.0F.WIG EA /r */
24217663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24218663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG_simple(
24219663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpminsw", Iop_Min16Sx8 );
24220663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24221663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24222663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24223663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24224663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xEB:
24225663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPOR r/m, rV, r ::: r = rV | r/m */
24226663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPOR = VEX.NDS.128.66.0F.WIG EB /r */
24227663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24228663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG_simple(
24229663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpor", Iop_OrV128 );
24230663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24231663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24232663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24233663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24234663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xEC:
24235663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPADDSB xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F.WIG EC /r */
24236663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24237663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_E_V_to_G(
24238663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpaddsb", Iop_QAdd8Sx16 );
24239663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24240663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24241663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24242663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24243663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xED:
24244663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPADDSW xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F.WIG ED /r */
24245663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24246663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_E_V_to_G(
24247663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpaddsw", Iop_QAdd16Sx8 );
24248663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24249663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24250663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24251663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24252663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xEE:
24253663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMAXSW r/m, rV, r ::: r = max-signed16s(rV, r/m) */
24254663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMAXSW = VEX.NDS.128.66.0F.WIG EE /r */
24255663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24256663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG_simple(
24257663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpmaxsw", Iop_Max16Sx8 );
24258663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24259663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24260663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24261663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24262663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xEF:
24263663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPXOR r/m, rV, r ::: r = rV ^ r/m */
24264663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPXOR = VEX.NDS.128.66.0F.WIG EF /r */
24265663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24266663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG_simple(
24267663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpxor", Iop_XorV128 );
24268663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24269663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24270663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24271663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24272663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xF0:
24273663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VLDDQU m256, ymm1 = VEX.256.F2.0F.WIG F0 /r */
24274663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2no66noF3(pfx) && 1==getVexL(pfx)/*256*/) {
24275663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm = getUChar(delta);
24276663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rD    = gregOfRexRM(pfx, modrm);
24277663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp tD    = newTemp(Ity_V256);
24278663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) break;
24279663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 0 );
24280663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta += alen;
24281663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(tD, loadLE(Ity_V256, mkexpr(addr)));
24282663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("vlddqu %s,%s\n", dis_buf, nameYMMReg(rD));
24283663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMReg(rD, mkexpr(tD));
24284663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24285663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24286663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VLDDQU m128, xmm1 = VEX.128.F2.0F.WIG F0 /r */
24287663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (haveF2no66noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24288663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm = getUChar(delta);
24289663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rD    = gregOfRexRM(pfx, modrm);
24290663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp tD    = newTemp(Ity_V128);
24291663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) break;
24292663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 0 );
24293663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta += alen;
24294663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(tD, loadLE(Ity_V128, mkexpr(addr)));
24295663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("vlddqu %s,%s\n", dis_buf, nameXMMReg(rD));
24296663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLoAndZU(rD, mkexpr(tD));
24297663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24298663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24299663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24300663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24301663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xF1:
24302663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPSLLW xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F.WIG F1 /r */
24303663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24304663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_shiftV_byE( vbi, pfx, delta,
24305663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        "vpsllw", Iop_ShlN16x8 );
24306663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
24307663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24308663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24309663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24310663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24311663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24312663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xF2:
24313663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPSLLD xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F.WIG F2 /r */
24314663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24315663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_shiftV_byE( vbi, pfx, delta,
24316663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        "vpslld", Iop_ShlN32x4 );
24317663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
24318663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24319663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24320663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24321663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24322663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xF3:
24323663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPSLLQ xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F.WIG F3 /r */
24324663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24325663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_shiftV_byE( vbi, pfx, delta,
24326663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        "vpsllq", Iop_ShlN64x2 );
24327663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
24328663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24329663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24330663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24331663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24332663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xF4:
24333663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMULUDQ xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F.WIG F4 /r */
24334663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24335663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG_complex(
24336663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta,
24337663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    "vpmuludq", math_PMULUDQ_128 );
24338663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24339663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24340663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24341663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24342663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xF5:
24343663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMADDWD xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F.WIG F5 /r */
24344663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24345663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG_complex(
24346663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta,
24347663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    "vpmaddwd", math_PMADDWD_128 );
24348663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24349663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24350663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24351663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24352663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xF6:
24353663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPSADBW xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F.WIG F6 /r */
24354663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24355663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG_complex(
24356663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta,
24357663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    "vpsadbw", math_PSADBW_128 );
24358663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24359663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24360663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24361663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24362663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xF7:
24363663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMASKMOVDQU xmm2, xmm1 = VEX.128.66.0F.WIG F7 /r */
24364663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/
24365663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && epartIsReg(getUChar(delta))) {
24366663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_MASKMOVDQU( vbi, pfx, delta, True/*isAvx*/ );
24367663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24368663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24369663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24370663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24371663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xF8:
24372663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPSUBB r/m, rV, r ::: r = rV - r/m */
24373663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPSUBB = VEX.NDS.128.66.0F.WIG F8 /r */
24374663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24375663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG_simple(
24376663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpsubb", Iop_Sub8x16 );
24377663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24378663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24379663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24380663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24381663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xF9:
24382663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPSUBW r/m, rV, r ::: r = rV - r/m */
24383663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPSUBW = VEX.NDS.128.66.0F.WIG F9 /r */
24384663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24385663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG_simple(
24386663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpsubw", Iop_Sub16x8 );
24387663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24388663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24389663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24390663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24391663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xFA:
24392663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPSUBD r/m, rV, r ::: r = rV - r/m */
24393663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPSUBD = VEX.NDS.128.66.0F.WIG FA /r */
24394663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24395663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG_simple(
24396663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpsubd", Iop_Sub32x4 );
24397663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24398663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24399663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24400663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24401663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xFB:
24402663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPSUBQ r/m, rV, r ::: r = rV - r/m */
24403663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPSUBQ = VEX.NDS.128.66.0F.WIG FB /r */
24404663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24405663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG_simple(
24406663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpsubq", Iop_Sub64x2 );
24407663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24408663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24409663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24410663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24411663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xFC:
24412663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPADDB r/m, rV, r ::: r = rV + r/m */
24413663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPADDB = VEX.NDS.128.66.0F.WIG FC /r */
24414663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24415663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG_simple(
24416663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpaddb", Iop_Add8x16 );
24417663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24418663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24419663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24420663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24421663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xFD:
24422663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPADDW r/m, rV, r ::: r = rV + r/m */
24423663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPADDW = VEX.NDS.128.66.0F.WIG FD /r */
24424663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24425663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG_simple(
24426663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpaddw", Iop_Add16x8 );
24427663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24428663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24429663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24430663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24431663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xFE:
24432663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPADDD r/m, rV, r ::: r = rV + r/m */
24433663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPADDD = VEX.NDS.128.66.0F.WIG FE /r */
24434663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24435663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG_simple(
24436663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpaddd", Iop_Add32x4 );
24437663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24438663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24439663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24440663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24441663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   default:
24442663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24443663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24444663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
24445663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24446663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  //decode_failure:
24447663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return deltaIN;
24448663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24449663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  decode_success:
24450663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
24451663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
24452663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24453663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24454663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*------------------------------------------------------------*/
24455663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---                                                      ---*/
24456663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*--- Top-level post-escape decoders: dis_ESC_0F38__VEX    ---*/
24457663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---                                                      ---*/
24458663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*------------------------------------------------------------*/
24459663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24460663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRTemp math_PERMILPS_VAR_128 ( IRTemp dataV, IRTemp ctrlV )
24461663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
24462663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* In the control vector, zero out all but the bottom two bits of
24463663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      each 32-bit lane. */
24464663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRExpr* cv1 = binop(Iop_ShrN32x4,
24465663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       binop(Iop_ShlN32x4, mkexpr(ctrlV), mkU8(30)),
24466663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       mkU8(30));
24467663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* And use the resulting cleaned-up control vector as steering
24468663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      in a Perm operation. */
24469663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp res = newTemp(Ity_V128);
24470663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(res, binop(Iop_Perm32x4, mkexpr(dataV), cv1));
24471663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return res;
24472663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
24473663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24474663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRTemp math_PERMILPS_VAR_256 ( IRTemp dataV, IRTemp ctrlV )
24475663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
24476663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp dHi, dLo, cHi, cLo;
24477663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   dHi = dLo = cHi = cLo = IRTemp_INVALID;
24478663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV256toV128s( dataV, &dHi, &dLo );
24479663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV256toV128s( ctrlV, &cHi, &cLo );
24480663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp rHi = math_PERMILPS_VAR_128( dHi, cHi );
24481663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp rLo = math_PERMILPS_VAR_128( dLo, cLo );
24482663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp res = newTemp(Ity_V256);
24483663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(res, binop(Iop_V128HLtoV256, mkexpr(rHi), mkexpr(rLo)));
24484663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return res;
24485663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
24486663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24487663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRTemp math_PERMILPD_VAR_128 ( IRTemp dataV, IRTemp ctrlV )
24488663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
24489663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* No cleverness here .. */
24490663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp dHi, dLo, cHi, cLo;
24491663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   dHi = dLo = cHi = cLo = IRTemp_INVALID;
24492663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV128to64s( dataV, &dHi, &dLo );
24493663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV128to64s( ctrlV, &cHi, &cLo );
24494663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRExpr* rHi
24495663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      = IRExpr_Mux0X( unop(Iop_64to8,
24496663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           binop(Iop_And64, mkexpr(cHi), mkU64(2))),
24497663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      mkexpr(dLo), mkexpr(dHi) );
24498663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRExpr* rLo
24499663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      = IRExpr_Mux0X( unop(Iop_64to8,
24500663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           binop(Iop_And64, mkexpr(cLo), mkU64(2))),
24501663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      mkexpr(dLo), mkexpr(dHi) );
24502663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp res = newTemp(Ity_V128);
24503663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(res, binop(Iop_64HLtoV128, rHi, rLo));
24504663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return res;
24505663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
24506663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24507663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRTemp math_PERMILPD_VAR_256 ( IRTemp dataV, IRTemp ctrlV )
24508663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
24509663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp dHi, dLo, cHi, cLo;
24510663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   dHi = dLo = cHi = cLo = IRTemp_INVALID;
24511663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV256toV128s( dataV, &dHi, &dLo );
24512663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV256toV128s( ctrlV, &cHi, &cLo );
24513663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp rHi = math_PERMILPD_VAR_128( dHi, cHi );
24514663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp rLo = math_PERMILPD_VAR_128( dLo, cLo );
24515663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp res = newTemp(Ity_V256);
24516663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(res, binop(Iop_V128HLtoV256, mkexpr(rHi), mkexpr(rLo)));
24517663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return res;
24518663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
24519663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24520663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng__attribute__((noinline))
24521663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic
24522663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengLong dis_ESC_0F38__VEX (
24523663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        /*MB_OUT*/DisResult* dres,
24524663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        /*OUT*/   Bool*      uses_vvvv,
24525663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        Bool         (*resteerOkFn) ( /*opaque*/void*, Addr64 ),
24526663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        Bool         resteerCisOk,
24527663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        void*        callback_opaque,
24528663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        VexArchInfo* archinfo,
24529663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        VexAbiInfo*  vbi,
24530663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        Prefix pfx, Int sz, Long deltaIN
24531663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     )
24532663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
24533663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr  = IRTemp_INVALID;
24534663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen  = 0;
24535663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
24536663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Long   delta = deltaIN;
24537663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  opc   = getUChar(delta);
24538663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   delta++;
24539663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *uses_vvvv = False;
24540663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24541663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (opc) {
24542663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24543663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x00:
24544663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPSHUFB r/m, rV, r ::: r = shuf(rV, r/m) */
24545663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPSHUFB = VEX.NDS.128.66.0F38.WIG 00 /r */
24546663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24547663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG_complex(
24548663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpshufb", math_PSHUFB_XMM );
24549663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24550663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24551663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24552663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24553663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x01:
24554663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x02:
24555663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x03:
24556663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPHADDW xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F38.WIG 01 /r */
24557663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPHADDD xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F38.WIG 02 /r */
24558663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPHADDSW xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F38.WIG 03 /r */
24559663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24560663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_PHADD_128( vbi, pfx, delta, True/*isAvx*/, opc );
24561663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
24562663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24563663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24564663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24565663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24566663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x04:
24567663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMADDUBSW xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F38.WIG 04 /r */
24568663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24569663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG_complex(
24570663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpmaddubsw",
24571663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    math_PMADDUBSW_128 );
24572663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24573663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24574663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24575663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24576663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x05:
24577663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x06:
24578663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x07:
24579663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPHSUBW xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F38.WIG 05 /r */
24580663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPHSUBD xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F38.WIG 06 /r */
24581663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPHSUBSW xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F38.WIG 07 /r */
24582663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24583663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_PHADD_128( vbi, pfx, delta, True/*isAvx*/, opc );
24584663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
24585663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24586663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24587663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24588663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24589663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x08:
24590663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x09:
24591663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x0A:
24592663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPSIGNB xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F38.WIG 08 /r */
24593663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPSIGNW xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F38.WIG 09 /r */
24594663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPSIGND xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F38.WIG 0A /r */
24595663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24596663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sV      = newTemp(Ity_V128);
24597663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dV      = newTemp(Ity_V128);
24598663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sHi, sLo, dHi, dLo;
24599663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         sHi = sLo = dHi = dLo = IRTemp_INVALID;
24600663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  ch      = '?';
24601663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int    laneszB = 0;
24602663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm   = getUChar(delta);
24603663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG      = gregOfRexRM(pfx,modrm);
24604663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rV      = getVexNvvvv(pfx);
24605663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24606663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         switch (opc) {
24607663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 0x08: laneszB = 1; ch = 'b'; break;
24608663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 0x09: laneszB = 2; ch = 'w'; break;
24609663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 0x0A: laneszB = 4; ch = 'd'; break;
24610663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            default: vassert(0);
24611663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
24612663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24613663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( dV, getXMMReg(rV) );
24614663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24615663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
24616663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
24617663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, getXMMReg(rE) );
24618663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
24619663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vpsign%c %s,%s,%s\n", ch, nameXMMReg(rE),
24620663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                nameXMMReg(rV), nameXMMReg(rG));
24621663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
24622663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
24623663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
24624663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
24625663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vpsign%c %s,%s,%s\n", ch, dis_buf,
24626663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                nameXMMReg(rV), nameXMMReg(rG));
24627663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
24628663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24629663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         breakupV128to64s( dV, &dHi, &dLo );
24630663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         breakupV128to64s( sV, &sHi, &sLo );
24631663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24632663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLoAndZU(
24633663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            rG,
24634663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            binop(Iop_64HLtoV128,
24635663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  dis_PSIGN_helper( mkexpr(sHi), mkexpr(dHi), laneszB ),
24636663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  dis_PSIGN_helper( mkexpr(sLo), mkexpr(dLo), laneszB )
24637663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            )
24638663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         );
24639663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
24640663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24641663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24642663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24643663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24644663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x0B:
24645663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMULHRSW xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F38.WIG 0B /r */
24646663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24647663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sV      = newTemp(Ity_V128);
24648663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dV      = newTemp(Ity_V128);
24649663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sHi, sLo, dHi, dLo;
24650663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         sHi = sLo = dHi = dLo = IRTemp_INVALID;
24651663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm   = getUChar(delta);
24652663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG      = gregOfRexRM(pfx,modrm);
24653663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rV      = getVexNvvvv(pfx);
24654663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24655663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( dV, getXMMReg(rV) );
24656663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24657663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
24658663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
24659663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, getXMMReg(rE) );
24660663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
24661663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vpmulhrsw %s,%s,%s\n", nameXMMReg(rE),
24662663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                nameXMMReg(rV), nameXMMReg(rG));
24663663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
24664663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
24665663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
24666663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
24667663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vpmulhrsw %s,%s,%s\n", dis_buf,
24668663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                nameXMMReg(rV), nameXMMReg(rG));
24669663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
24670663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24671663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         breakupV128to64s( dV, &dHi, &dLo );
24672663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         breakupV128to64s( sV, &sHi, &sLo );
24673663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24674663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLoAndZU(
24675663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            rG,
24676663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            binop(Iop_64HLtoV128,
24677663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  dis_PMULHRSW_helper( mkexpr(sHi), mkexpr(dHi) ),
24678663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  dis_PMULHRSW_helper( mkexpr(sLo), mkexpr(dLo) )
24679663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            )
24680663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         );
24681663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
24682663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24683663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24684663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24685663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24686663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x0C:
24687663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPERMILPS xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F38.W0 0C /r */
24688663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
24689663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && 0==getVexL(pfx)/*128*/ && 0==getRexW(pfx)/*W0*/) {
24690663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm = getUChar(delta);
24691663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG    = gregOfRexRM(pfx, modrm);
24692663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rV    = getVexNvvvv(pfx);
24693663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp ctrlV = newTemp(Ity_V128);
24694663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
24695663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx, modrm);
24696663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
24697663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vpermilps %s,%s,%s\n",
24698663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                nameXMMReg(rE), nameXMMReg(rV), nameXMMReg(rG));
24699663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(ctrlV, getXMMReg(rE));
24700663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
24701663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 0 );
24702663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
24703663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vpermilps %s,%s,%s\n",
24704663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                dis_buf, nameXMMReg(rV), nameXMMReg(rG));
24705663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(ctrlV, loadLE(Ity_V128, mkexpr(addr)));
24706663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
24707663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dataV = newTemp(Ity_V128);
24708663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(dataV, getXMMReg(rV));
24709663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp resV = math_PERMILPS_VAR_128(dataV, ctrlV);
24710663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLoAndZU(rG, mkexpr(resV));
24711663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
24712663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24713663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24714663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPERMILPS ymm3/m256, ymm2, ymm1 = VEX.NDS.256.66.0F38.W0 0C /r */
24715663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
24716663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && 1==getVexL(pfx)/*256*/ && 0==getRexW(pfx)/*W0*/) {
24717663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm = getUChar(delta);
24718663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG    = gregOfRexRM(pfx, modrm);
24719663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rV    = getVexNvvvv(pfx);
24720663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp ctrlV = newTemp(Ity_V256);
24721663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
24722663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx, modrm);
24723663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
24724663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vpermilps %s,%s,%s\n",
24725663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                nameYMMReg(rE), nameYMMReg(rV), nameYMMReg(rG));
24726663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(ctrlV, getYMMReg(rE));
24727663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
24728663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 0 );
24729663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
24730663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vpermilps %s,%s,%s\n",
24731663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                dis_buf, nameYMMReg(rV), nameYMMReg(rG));
24732663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(ctrlV, loadLE(Ity_V256, mkexpr(addr)));
24733663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
24734663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dataV = newTemp(Ity_V256);
24735663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(dataV, getYMMReg(rV));
24736663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp resV = math_PERMILPS_VAR_256(dataV, ctrlV);
24737663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMReg(rG, mkexpr(resV));
24738663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
24739663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24740663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24741663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24742663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24743663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x0D:
24744663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPERMILPD xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F38.W0 0D /r */
24745663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
24746663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && 0==getVexL(pfx)/*128*/ && 0==getRexW(pfx)/*W0*/) {
24747663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm = getUChar(delta);
24748663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG    = gregOfRexRM(pfx, modrm);
24749663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rV    = getVexNvvvv(pfx);
24750663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp ctrlV = newTemp(Ity_V128);
24751663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
24752663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx, modrm);
24753663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
24754663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vpermilpd %s,%s,%s\n",
24755663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                nameXMMReg(rE), nameXMMReg(rV), nameXMMReg(rG));
24756663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(ctrlV, getXMMReg(rE));
24757663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
24758663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 0 );
24759663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
24760663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vpermilpd %s,%s,%s\n",
24761663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                dis_buf, nameXMMReg(rV), nameXMMReg(rG));
24762663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(ctrlV, loadLE(Ity_V128, mkexpr(addr)));
24763663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
24764663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dataV = newTemp(Ity_V128);
24765663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(dataV, getXMMReg(rV));
24766663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp resV = math_PERMILPD_VAR_128(dataV, ctrlV);
24767663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLoAndZU(rG, mkexpr(resV));
24768663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
24769663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24770663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24771663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPERMILPD ymm3/m256, ymm2, ymm1 = VEX.NDS.256.66.0F38.W0 0D /r */
24772663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
24773663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && 1==getVexL(pfx)/*256*/ && 0==getRexW(pfx)/*W0*/) {
24774663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm = getUChar(delta);
24775663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG    = gregOfRexRM(pfx, modrm);
24776663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rV    = getVexNvvvv(pfx);
24777663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp ctrlV = newTemp(Ity_V256);
24778663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
24779663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx, modrm);
24780663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
24781663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vpermilpd %s,%s,%s\n",
24782663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                nameYMMReg(rE), nameYMMReg(rV), nameYMMReg(rG));
24783663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(ctrlV, getYMMReg(rE));
24784663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
24785663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 0 );
24786663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
24787663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vpermilpd %s,%s,%s\n",
24788663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                dis_buf, nameYMMReg(rV), nameYMMReg(rG));
24789663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(ctrlV, loadLE(Ity_V256, mkexpr(addr)));
24790663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
24791663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dataV = newTemp(Ity_V256);
24792663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(dataV, getYMMReg(rV));
24793663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp resV = math_PERMILPD_VAR_256(dataV, ctrlV);
24794663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMReg(rG, mkexpr(resV));
24795663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
24796663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24797663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24798663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24799663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24800663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x0E:
24801663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VTESTPS xmm2/m128, xmm1 = VEX.128.66.0F38.WIG 0E /r */
24802663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24803663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_xTESTy_128( vbi, pfx, delta, True/*isAvx*/, 32 );
24804663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24805663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24806663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VTESTPS ymm2/m256, ymm1 = VEX.256.66.0F38.WIG 0E /r */
24807663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
24808663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_xTESTy_256( vbi, pfx, delta, 32 );
24809663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24810663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24811663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24812663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24813663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x0F:
24814663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VTESTPD xmm2/m128, xmm1 = VEX.128.66.0F38.WIG 0F /r */
24815663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24816663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_xTESTy_128( vbi, pfx, delta, True/*isAvx*/, 64 );
24817663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24818663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24819663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VTESTPD ymm2/m256, ymm1 = VEX.256.66.0F38.WIG 0F /r */
24820663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
24821663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_xTESTy_256( vbi, pfx, delta, 64 );
24822663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24823663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24824663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24825663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24826663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x17:
24827663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPTEST xmm2/m128, xmm1 = VEX.128.66.0F38.WIG 17 /r */
24828663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24829663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_xTESTy_128( vbi, pfx, delta, True/*isAvx*/, 0 );
24830663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24831663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24832663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPTEST ymm2/m256, ymm1 = VEX.256.66.0F38.WIG 17 /r */
24833663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
24834663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_xTESTy_256( vbi, pfx, delta, 0 );
24835663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24836663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24837663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24838663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24839663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x18:
24840663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VBROADCASTSS m32, xmm1 = VEX.128.66.0F38.WIG 18 /r */
24841663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
24842663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && 0==getVexL(pfx)/*128*/
24843663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && !epartIsReg(getUChar(delta))) {
24844663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar modrm = getUChar(delta);
24845663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rG    = gregOfRexRM(pfx, modrm);
24846663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 0 );
24847663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta += alen;
24848663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("vbroadcastss %s,%s\n", dis_buf, nameXMMReg(rG));
24849663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp t32 = newTemp(Ity_I32);
24850663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(t32, loadLE(Ity_I32, mkexpr(addr)));
24851663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp t64 = newTemp(Ity_I64);
24852663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(t64, binop(Iop_32HLto64, mkexpr(t32), mkexpr(t32)));
24853663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRExpr* res = binop(Iop_64HLtoV128, mkexpr(t64), mkexpr(t64));
24854663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLoAndZU(rG, res);
24855663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24856663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24857663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VBROADCASTSS m32, ymm1 = VEX.256.66.0F38.WIG 18 /r */
24858663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
24859663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && 1==getVexL(pfx)/*256*/
24860663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && !epartIsReg(getUChar(delta))) {
24861663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar modrm = getUChar(delta);
24862663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rG    = gregOfRexRM(pfx, modrm);
24863663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 0 );
24864663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta += alen;
24865663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("vbroadcastss %s,%s\n", dis_buf, nameYMMReg(rG));
24866663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp t32 = newTemp(Ity_I32);
24867663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(t32, loadLE(Ity_I32, mkexpr(addr)));
24868663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp t64 = newTemp(Ity_I64);
24869663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(t64, binop(Iop_32HLto64, mkexpr(t32), mkexpr(t32)));
24870663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRExpr* res = IRExpr_Qop(Iop_64x4toV256, mkexpr(t64), mkexpr(t64),
24871663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                                  mkexpr(t64), mkexpr(t64));
24872663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMReg(rG, res);
24873663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24874663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24875663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24876663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24877663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x19:
24878663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VBROADCASTSD m64, ymm1 = VEX.256.66.0F38.WIG 19 /r */
24879663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
24880663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && 1==getVexL(pfx)/*256*/
24881663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && !epartIsReg(getUChar(delta))) {
24882663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar modrm = getUChar(delta);
24883663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rG    = gregOfRexRM(pfx, modrm);
24884663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 0 );
24885663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta += alen;
24886663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("vbroadcastsd %s,%s\n", dis_buf, nameYMMReg(rG));
24887663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp t64 = newTemp(Ity_I64);
24888663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(t64, loadLE(Ity_I64, mkexpr(addr)));
24889663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRExpr* res = IRExpr_Qop(Iop_64x4toV256, mkexpr(t64), mkexpr(t64),
24890663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                                  mkexpr(t64), mkexpr(t64));
24891663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMReg(rG, res);
24892663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24893663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24894663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24895663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24896663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x1A:
24897663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VBROADCASTF128 m128, ymm1 = VEX.256.66.0F38.WIG 1A /r */
24898663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
24899663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && 1==getVexL(pfx)/*256*/
24900663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && !epartIsReg(getUChar(delta))) {
24901663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar modrm = getUChar(delta);
24902663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt  rG    = gregOfRexRM(pfx, modrm);
24903663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 0 );
24904663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta += alen;
24905663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("vbroadcastf128 %s,%s\n", dis_buf, nameYMMReg(rG));
24906663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp t128 = newTemp(Ity_V128);
24907663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(t128, loadLE(Ity_V128, mkexpr(addr)));
24908663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMReg( rG, binop(Iop_V128HLtoV256, mkexpr(t128), mkexpr(t128)) );
24909663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24910663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24911663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24912663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24913663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x1C:
24914663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPABSB xmm2/m128, xmm1 = VEX.128.66.0F38.WIG 1C /r */
24915663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24916663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_E_to_G_unary(
24917663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta,
24918663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    "vpabsb", math_PABS_XMM_pap1 );
24919663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24920663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24921663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24922663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24923663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x1D:
24924663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPABSW xmm2/m128, xmm1 = VEX.128.66.0F38.WIG 1D /r */
24925663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24926663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_E_to_G_unary(
24927663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta,
24928663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    "vpabsw", math_PABS_XMM_pap2 );
24929663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24930663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24931663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24932663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24933663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x1E:
24934663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPABSD xmm2/m128, xmm1 = VEX.128.66.0F38.WIG 1E /r */
24935663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24936663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AVX128_E_to_G_unary(
24937663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta,
24938663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    "vpabsd", math_PABS_XMM_pap4 );
24939663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24940663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24941663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24942663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24943663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x20:
24944663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMOVSXBW xmm2/m64, xmm1 */
24945663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMOVSXBW = VEX.128.66.0F38.WIG 20 /r */
24946663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24947663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_PMOVxXBW_128( vbi, pfx, delta,
24948663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   True/*isAvx*/, False/*!xIsZ*/ );
24949663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24950663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24951663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24952663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24953663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x21:
24954663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMOVSXBD xmm2/m32, xmm1 */
24955663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMOVSXBD = VEX.128.66.0F38.WIG 21 /r */
24956663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24957663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_PMOVxXBD_128( vbi, pfx, delta,
24958663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   True/*isAvx*/, False/*!xIsZ*/ );
24959663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24960663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24961663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24962663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24963663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x22:
24964663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMOVSXBQ xmm2/m16, xmm1 */
24965663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMOVSXBQ = VEX.128.66.0F38.WIG 22 /r */
24966663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24967663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_PMOVSXBQ_128( vbi, pfx, delta, True/*isAvx*/ );
24968663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24969663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24970663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24971663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24972663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x23:
24973663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMOVSXWD xmm2/m64, xmm1 = VEX.128.66.0F38.WIG 23 /r */
24974663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24975663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_PMOVxXWD_128( vbi, pfx, delta,
24976663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   True/*isAvx*/, False/*!xIsZ*/ );
24977663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24978663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24979663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24980663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24981663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x24:
24982663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMOVSXWQ xmm2/m32, xmm1 = VEX.128.66.0F38.WIG 24 /r */
24983663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24984663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_PMOVSXWQ_128( vbi, pfx, delta, True/*isAvx*/ );
24985663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24986663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24987663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24988663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24989663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x25:
24990663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMOVSXDQ xmm2/m64, xmm1 = VEX.128.66.0F38.WIG 25 /r */
24991663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
24992663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_PMOVxXDQ_128( vbi, pfx, delta,
24993663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   True/*isAvx*/, False/*!xIsZ*/ );
24994663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
24995663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
24996663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
24997663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24998663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x28:
24999663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMULDQ xmm3/m128, xmm2, xmm1 = VEX.NDS.128.66.0F38.WIG 28 /r */
25000663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
25001663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG_complex(
25002663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta,
25003663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    "vpmuldq", math_PMULDQ_128 );
25004663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
25005663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
25006663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
25007663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25008663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x29:
25009663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPCMPEQQ r/m, rV, r ::: r = rV `eq-by-64s` r/m */
25010663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPCMPEQQ = VEX.NDS.128.66.0F38.WIG 29 /r */
25011663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
25012663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG_simple(
25013663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpcmpeqq", Iop_CmpEQ64x2 );
25014663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
25015663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
25016663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
25017663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25018663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x2A:
25019663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMOVNTDQA m128, xmm1 = VEX.128.66.0F38.WIG 2A /r */
25020663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/
25021663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && !epartIsReg(getUChar(delta))) {
25022663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm = getUChar(delta);
25023663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rD    = gregOfRexRM(pfx, modrm);
25024663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp tD    = newTemp(Ity_V128);
25025663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 0 );
25026663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta += alen;
25027663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         gen_SEGV_if_not_16_aligned(addr);
25028663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(tD, loadLE(Ity_V128, mkexpr(addr)));
25029663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("vmovntdqa %s,%s\n", dis_buf, nameXMMReg(rD));
25030663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLoAndZU(rD, mkexpr(tD));
25031663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
25032663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
25033663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
25034663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25035663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x2B:
25036663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPACKUSDW r/m, rV, r ::: r = QNarrowBin32Sto16Ux8(rV, r/m) */
25037663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPACKUSDW = VEX.NDS.128.66.0F38.WIG 2B /r */
25038663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
25039663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG(
25040663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpackusdw",
25041663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    Iop_QNarrowBin32Sto16Ux8, NULL,
25042663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    False/*!invertLeftArg*/, True/*swapArgs*/ );
25043663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
25044663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
25045663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
25046663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25047663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x30:
25048663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMOVZXBW xmm2/m64, xmm1 */
25049663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMOVZXBW = VEX.128.66.0F38.WIG 30 /r */
25050663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
25051663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_PMOVxXBW_128( vbi, pfx, delta,
25052663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   True/*isAvx*/, True/*xIsZ*/ );
25053663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
25054663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
25055663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
25056663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25057663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x31:
25058663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMOVZXBD xmm2/m32, xmm1 */
25059663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMOVZXBD = VEX.128.66.0F38.WIG 31 /r */
25060663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
25061663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_PMOVxXBD_128( vbi, pfx, delta,
25062663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   True/*isAvx*/, True/*xIsZ*/ );
25063663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
25064663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
25065663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
25066663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25067663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x32:
25068663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMOVZXBQ xmm2/m16, xmm1 */
25069663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMOVZXBQ = VEX.128.66.0F38.WIG 32 /r */
25070663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
25071663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_PMOVZXBQ_128( vbi, pfx, delta, True/*isAvx*/ );
25072663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
25073663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
25074663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
25075663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25076663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x33:
25077663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMOVZXWD xmm2/m64, xmm1 */
25078663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMOVZXWD = VEX.128.66.0F38.WIG 33 /r */
25079663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
25080663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_PMOVxXWD_128( vbi, pfx, delta,
25081663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   True/*isAvx*/, True/*xIsZ*/ );
25082663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
25083663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
25084663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
25085663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25086663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x34:
25087663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMOVZXWQ xmm2/m32, xmm1 = VEX.128.66.0F38.WIG 34 /r */
25088663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
25089663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_PMOVZXWQ_128( vbi, pfx, delta, True/*isAvx*/ );
25090663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
25091663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
25092663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
25093663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25094663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x35:
25095663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMOVZXDQ xmm2/m64, xmm1 = VEX.128.66.0F38.WIG 35 /r */
25096663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
25097663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_PMOVxXDQ_128( vbi, pfx, delta,
25098663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   True/*isAvx*/, True/*xIsZ*/ );
25099663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
25100663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
25101663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
25102663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25103663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x37:
25104663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPCMPGTQ r/m, rV, r ::: r = rV `>s-by-64s` r/m */
25105663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPCMPGTQ = VEX.NDS.128.66.0F38.WIG 37 /r */
25106663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
25107663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG_simple(
25108663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpcmpgtq", Iop_CmpGT64Sx2 );
25109663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
25110663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
25111663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
25112663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25113663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x38:
25114663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMINSB r/m, rV, r ::: r = min-signed-8s(rV, r/m) */
25115663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMINSB = VEX.NDS.128.66.0F38.WIG 38 /r */
25116663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
25117663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG_simple(
25118663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpminsb", Iop_Min8Sx16 );
25119663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
25120663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
25121663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
25122663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25123663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x39:
25124663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMINSD r/m, rV, r ::: r = min-signed-32s(rV, r/m) */
25125663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMINSD = VEX.NDS.128.66.0F38.WIG 39 /r */
25126663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
25127663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG_simple(
25128663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpminsd", Iop_Min32Sx4 );
25129663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
25130663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
25131663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
25132663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25133663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x3A:
25134663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMINUW r/m, rV, r ::: r = min-unsigned-16s(rV, r/m) */
25135663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMINUW = VEX.NDS.128.66.0F38.WIG 3A /r */
25136663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
25137663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG_simple(
25138663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpminuw", Iop_Min16Ux8 );
25139663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
25140663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
25141663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
25142663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25143663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x3B:
25144663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMINUD r/m, rV, r ::: r = min-unsigned-32s(rV, r/m) */
25145663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMINUD = VEX.NDS.128.66.0F38.WIG 3B /r */
25146663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
25147663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG_simple(
25148663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpminud", Iop_Min32Ux4 );
25149663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
25150663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
25151663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
25152663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25153663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x3C:
25154663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMAXSB r/m, rV, r ::: r = max-signed-8s(rV, r/m) */
25155663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMAXSB = VEX.NDS.128.66.0F38.WIG 3C /r */
25156663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
25157663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG_simple(
25158663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpmaxsb", Iop_Max8Sx16 );
25159663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
25160663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
25161663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
25162663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25163663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x3D:
25164663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMAXSD r/m, rV, r ::: r = max-signed-32s(rV, r/m) */
25165663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMAXSD = VEX.NDS.128.66.0F38.WIG 3D /r */
25166663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
25167663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG_simple(
25168663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpmaxsd", Iop_Max32Sx4 );
25169663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
25170663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
25171663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
25172663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25173663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x3E:
25174663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMAXUW r/m, rV, r ::: r = max-unsigned-16s(rV, r/m) */
25175663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMAXUW = VEX.NDS.128.66.0F38.WIG 3E /r */
25176663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
25177663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG_simple(
25178663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpmaxuw", Iop_Max16Ux8 );
25179663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
25180663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
25181663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
25182663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25183663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x3F:
25184663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMAXUD r/m, rV, r ::: r = max-unsigned-32s(rV, r/m) */
25185663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMAXUD = VEX.NDS.128.66.0F38.WIG 3F /r */
25186663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
25187663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG_simple(
25188663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpmaxud", Iop_Max32Ux4 );
25189663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
25190663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
25191663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
25192663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25193663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x40:
25194663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMULLD r/m, rV, r ::: r = mul-32s(rV, r/m) */
25195663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPMULLD = VEX.NDS.128.66.0F38.WIG 40 /r */
25196663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
25197663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VEX_NDS_128_AnySimdPfx_0F_WIG_simple(
25198663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    uses_vvvv, vbi, pfx, delta, "vpmulld", Iop_Mul32x4 );
25199663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
25200663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
25201663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
25202663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25203663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x41:
25204663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPHMINPOSUW xmm2/m128, xmm1 = VEX.128.66.0F38.WIG 41 /r */
25205663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
25206663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_PHMINPOSUW_128( vbi, pfx, delta, True/*isAvx*/ );
25207663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
25208663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
25209663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
25210663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25211663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xDB:
25212663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xDC:
25213663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xDD:
25214663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xDE:
25215663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xDF:
25216663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VAESIMC xmm2/m128, xmm1 = VEX.128.66.0F38.WIG DB /r */
25217663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VAESENC xmm3/m128, xmm2, xmm1 = VEX.128.66.0F38.WIG DC /r */
25218663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VAESENCLAST xmm3/m128, xmm2, xmm1 = VEX.128.66.0F38.WIG DD /r */
25219663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VAESDEC xmm3/m128, xmm2, xmm1 = VEX.128.66.0F38.WIG DE /r */
25220663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VAESDECLAST xmm3/m128, xmm2, xmm1 = VEX.128.66.0F38.WIG DF /r */
25221663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
25222663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AESx( vbi, pfx, delta, True/*!isAvx*/, opc );
25223663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (opc != 0xDB) *uses_vvvv = True;
25224663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
25225663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
25226663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
25227663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25228663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   default:
25229663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
25230663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25231663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
25232663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25233663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  //decode_failure:
25234663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return deltaIN;
25235663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25236663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  decode_success:
25237663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
25238663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
25239663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25240663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25241663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*------------------------------------------------------------*/
25242663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---                                                      ---*/
25243663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*--- Top-level post-escape decoders: dis_ESC_0F3A__VEX    ---*/
25244663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---                                                      ---*/
25245663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*------------------------------------------------------------*/
25246663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25247663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRTemp math_VPERMILPS_128 ( IRTemp sV, UInt imm8 )
25248663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
25249663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(imm8 < 256);
25250663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp s3, s2, s1, s0;
25251663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   s3 = s2 = s1 = s0 = IRTemp_INVALID;
25252663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   breakupV128to32s( sV, &s3, &s2, &s1, &s0 );
25253663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  define SEL(_nn) (((_nn)==0) ? s0 : ((_nn)==1) ? s1 \
25254663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    : ((_nn)==2) ? s2 : s3)
25255663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp res = newTemp(Ity_V128);
25256663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(res, mkV128from32s( SEL((imm8 >> 6) & 3),
25257663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              SEL((imm8 >> 4) & 3),
25258663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              SEL((imm8 >> 2) & 3),
25259663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              SEL((imm8 >> 0) & 3) ));
25260663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  undef SEL
25261663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return res;
25262663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
25263663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25264663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng__attribute__((noinline))
25265663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic
25266663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengLong dis_ESC_0F3A__VEX (
25267663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        /*MB_OUT*/DisResult* dres,
25268663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        /*OUT*/   Bool*      uses_vvvv,
25269663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        Bool         (*resteerOkFn) ( /*opaque*/void*, Addr64 ),
25270663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        Bool         resteerCisOk,
25271663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        void*        callback_opaque,
25272663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        VexArchInfo* archinfo,
25273663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        VexAbiInfo*  vbi,
25274663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        Prefix pfx, Int sz, Long deltaIN
25275663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     )
25276663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
25277663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp addr  = IRTemp_INVALID;
25278663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int    alen  = 0;
25279663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HChar  dis_buf[50];
25280663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Long   delta = deltaIN;
25281663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar  opc   = getUChar(delta);
25282663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   delta++;
25283663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *uses_vvvv = False;
25284663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25285663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (opc) {
25286663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25287663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x04:
25288663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPERMILPS imm8, ymm2/m256, ymm1 = VEX.256.66.0F3A.WIG 04 /r ib */
25289663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
25290663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm = getUChar(delta);
25291663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   imm8  = 0;
25292663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG    = gregOfRexRM(pfx, modrm);
25293663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sV    = newTemp(Ity_V256);
25294663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
25295663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx, modrm);
25296663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
25297663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = getUChar(delta);
25298663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vpermilps $%u,%s,%s\n",
25299663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                imm8, nameYMMReg(rE), nameYMMReg(rG));
25300663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(sV, getYMMReg(rE));
25301663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
25302663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 1 );
25303663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
25304663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = getUChar(delta);
25305663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vpermilps $%u,%s,%s\n",
25306663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                imm8, dis_buf, nameYMMReg(rG));
25307663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(sV, loadLE(Ity_V256, mkexpr(addr)));
25308663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
25309663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta++;
25310663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp  sVhi = IRTemp_INVALID, sVlo = IRTemp_INVALID;
25311663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         breakupV256toV128s( sV, &sVhi, &sVlo );
25312663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp  dVhi = math_VPERMILPS_128( sVhi, imm8 );
25313663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp  dVlo = math_VPERMILPS_128( sVlo, imm8 );
25314663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRExpr* res  = binop(Iop_V128HLtoV256, mkexpr(dVhi), mkexpr(dVlo));
25315663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMReg(rG, res);
25316663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
25317663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
25318663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPERMILPS imm8, xmm2/m128, xmm1 = VEX.128.66.0F3A.WIG 04 /r ib */
25319663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
25320663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm = getUChar(delta);
25321663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   imm8  = 0;
25322663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG    = gregOfRexRM(pfx, modrm);
25323663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sV    = newTemp(Ity_V128);
25324663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
25325663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx, modrm);
25326663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
25327663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = getUChar(delta);
25328663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vpermilps $%u,%s,%s\n",
25329663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                imm8, nameXMMReg(rE), nameXMMReg(rG));
25330663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(sV, getXMMReg(rE));
25331663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
25332663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 1 );
25333663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
25334663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = getUChar(delta);
25335663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vpermilps $%u,%s,%s\n",
25336663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                imm8, dis_buf, nameXMMReg(rG));
25337663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(sV, loadLE(Ity_V128, mkexpr(addr)));
25338663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
25339663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta++;
25340663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLoAndZU(rG, mkexpr ( math_VPERMILPS_128 ( sV, imm8 ) ) );
25341663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
25342663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
25343663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
25344663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25345663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x05:
25346663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPERMILPD imm8, xmm2/m128, xmm1 = VEX.128.66.0F3A.WIG 05 /r ib */
25347663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
25348663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm = getUChar(delta);
25349663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   imm8  = 0;
25350663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG    = gregOfRexRM(pfx, modrm);
25351663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sV    = newTemp(Ity_V128);
25352663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
25353663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx, modrm);
25354663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
25355663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = getUChar(delta);
25356663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vpermilpd $%u,%s,%s\n",
25357663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                imm8, nameXMMReg(rE), nameXMMReg(rG));
25358663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(sV, getXMMReg(rE));
25359663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
25360663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 1 );
25361663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
25362663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = getUChar(delta);
25363663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vpermilpd $%u,%s,%s\n",
25364663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                imm8, dis_buf, nameXMMReg(rG));
25365663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(sV, loadLE(Ity_V128, mkexpr(addr)));
25366663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
25367663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta++;
25368663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp s1 = newTemp(Ity_I64);
25369663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp s0 = newTemp(Ity_I64);
25370663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(s1, unop(Iop_V128HIto64, mkexpr(sV)));
25371663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(s0, unop(Iop_V128to64,   mkexpr(sV)));
25372663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dV = newTemp(Ity_V128);
25373663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(dV, binop(Iop_64HLtoV128,
25374663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               mkexpr((imm8 & (1<<1)) ? s1 : s0),
25375663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               mkexpr((imm8 & (1<<0)) ? s1 : s0)));
25376663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLoAndZU(rG, mkexpr(dV));
25377663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
25378663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
25379663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPERMILPD imm8, ymm2/m256, ymm1 = VEX.256.66.0F3A.WIG 05 /r ib */
25380663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
25381663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm = getUChar(delta);
25382663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   imm8  = 0;
25383663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG    = gregOfRexRM(pfx, modrm);
25384663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sV    = newTemp(Ity_V256);
25385663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
25386663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx, modrm);
25387663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
25388663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = getUChar(delta);
25389663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vpermilpd $%u,%s,%s\n",
25390663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                imm8, nameYMMReg(rE), nameYMMReg(rG));
25391663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(sV, getYMMReg(rE));
25392663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
25393663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 1 );
25394663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
25395663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = getUChar(delta);
25396663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vpermilpd $%u,%s,%s\n",
25397663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                imm8, dis_buf, nameYMMReg(rG));
25398663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(sV, loadLE(Ity_V256, mkexpr(addr)));
25399663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
25400663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta++;
25401663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp s3, s2, s1, s0;
25402663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         s3 = s2 = s1 = s0 = IRTemp_INVALID;
25403663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         breakupV256to64s(sV, &s3, &s2, &s1, &s0);
25404663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dV = newTemp(Ity_V256);
25405663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(dV, IRExpr_Qop(Iop_64x4toV256,
25406663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               mkexpr((imm8 & (1<<3)) ? s3 : s2),
25407663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               mkexpr((imm8 & (1<<2)) ? s3 : s2),
25408663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               mkexpr((imm8 & (1<<1)) ? s1 : s0),
25409663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               mkexpr((imm8 & (1<<0)) ? s1 : s0)));
25410663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMReg(rG, mkexpr(dV));
25411663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
25412663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
25413663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
25414663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25415663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x06:
25416663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPERM2F128 imm8, ymm3/m256, ymm2, ymm1 = VEX.NDS.66.0F3A.W0 06 /r ib */
25417663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
25418663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && 1==getVexL(pfx)/*256*/ && 0==getRexW(pfx)/*W0*/) {
25419663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm = getUChar(delta);
25420663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   imm8  = 0;
25421663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG    = gregOfRexRM(pfx, modrm);
25422663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rV    = getVexNvvvv(pfx);
25423663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp s00   = newTemp(Ity_V128);
25424663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp s01   = newTemp(Ity_V128);
25425663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp s10   = newTemp(Ity_V128);
25426663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp s11   = newTemp(Ity_V128);
25427663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(s00, getYMMRegLane128(rV, 0));
25428663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(s01, getYMMRegLane128(rV, 1));
25429663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
25430663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx, modrm);
25431663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
25432663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = getUChar(delta);
25433663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vperm2f128 $%u,%s,%s,%s\n",
25434663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                imm8, nameYMMReg(rE), nameYMMReg(rV), nameYMMReg(rG));
25435663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(s10, getYMMRegLane128(rE, 0));
25436663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(s11, getYMMRegLane128(rE, 1));
25437663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
25438663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 1 );
25439663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
25440663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = getUChar(delta);
25441663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vperm2f128 $%u,%s,%s,%s\n",
25442663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                imm8, dis_buf, nameYMMReg(rV), nameYMMReg(rG));
25443663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(s10, loadLE(Ity_V128, binop(Iop_Add64,
25444663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                               mkexpr(addr), mkU64(0))));
25445663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(s11, loadLE(Ity_V128, binop(Iop_Add64,
25446663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                               mkexpr(addr), mkU64(16))));
25447663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
25448663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta++;
25449663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#        define SEL(_nn) (((_nn)==0) ? s00 : ((_nn)==1) ? s01 \
25450663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                           : ((_nn)==2) ? s10 : s11)
25451663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLane128(rG, 0, mkexpr(SEL((imm8 >> 0) & 3)));
25452663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLane128(rG, 1, mkexpr(SEL((imm8 >> 4) & 3)));
25453663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#        undef SEL
25454663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (imm8 & (1<<3)) putYMMRegLane128(rG, 0, mkV128(0));
25455663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (imm8 & (1<<7)) putYMMRegLane128(rG, 1, mkV128(0));
25456663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
25457663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
25458663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
25459663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
25460663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25461663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x08:
25462663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VROUNDPS imm8, xmm2/m128, xmm1 */
25463663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VROUNDPS = VEX.NDS.128.66.0F3A.WIG 08 ib */
25464663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
25465663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm = getUChar(delta);
25466663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG    = gregOfRexRM(pfx, modrm);
25467663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp src   = newTemp(Ity_V128);
25468663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp s0    = IRTemp_INVALID;
25469663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp s1    = IRTemp_INVALID;
25470663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp s2    = IRTemp_INVALID;
25471663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp s3    = IRTemp_INVALID;
25472663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp rm    = newTemp(Ity_I32);
25473663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int    imm   = 0;
25474663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25475663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
25476663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25477663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
25478663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx, modrm);
25479663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( src, getXMMReg( rE ) );
25480663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm = getUChar(delta+1);
25481663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (imm & ~15) break;
25482663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1+1;
25483663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "vroundps $%d,%s,%s\n", imm, nameXMMReg(rE), nameXMMReg(rG) );
25484663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
25485663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 1 );
25486663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( src, loadLE(Ity_V128, mkexpr(addr) ) );
25487663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm = getUChar(delta+alen);
25488663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (imm & ~15) break;
25489663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen+1;
25490663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "vroundps $%d,%s,%s\n", imm, dis_buf, nameXMMReg(rG) );
25491663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
25492663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25493663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* (imm & 3) contains an Intel-encoded rounding mode.  Because
25494663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            that encoding is the same as the encoding for IRRoundingMode,
25495663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            we can use that value directly in the IR as a rounding
25496663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            mode. */
25497663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(rm, (imm & 4) ? get_sse_roundingmode() : mkU32(imm & 3));
25498663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25499663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         breakupV128to32s( src, &s3, &s2, &s1, &s0 );
25500663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLane128( rG, 1, mkV128(0) );
25501663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#        define CVT(s) binop(Iop_RoundF32toInt, mkexpr(rm), \
25502663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             unop(Iop_ReinterpI32asF32, mkexpr(s)))
25503663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLane32F( rG, 3, CVT(s3) );
25504663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLane32F( rG, 2, CVT(s2) );
25505663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLane32F( rG, 1, CVT(s1) );
25506663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLane32F( rG, 0, CVT(s0) );
25507663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#        undef CVT
25508663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
25509663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
25510663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VROUNDPS imm8, ymm2/m256, ymm1 */
25511663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VROUNDPS = VEX.NDS.256.66.0F3A.WIG 08 ib */
25512663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
25513663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm = getUChar(delta);
25514663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG    = gregOfRexRM(pfx, modrm);
25515663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp src   = newTemp(Ity_V256);
25516663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp s0    = IRTemp_INVALID;
25517663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp s1    = IRTemp_INVALID;
25518663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp s2    = IRTemp_INVALID;
25519663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp s3    = IRTemp_INVALID;
25520663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp s4    = IRTemp_INVALID;
25521663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp s5    = IRTemp_INVALID;
25522663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp s6    = IRTemp_INVALID;
25523663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp s7    = IRTemp_INVALID;
25524663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp rm    = newTemp(Ity_I32);
25525663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int    imm   = 0;
25526663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25527663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
25528663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25529663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
25530663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx, modrm);
25531663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( src, getYMMReg( rE ) );
25532663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm = getUChar(delta+1);
25533663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (imm & ~15) break;
25534663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1+1;
25535663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "vroundps $%d,%s,%s\n", imm, nameYMMReg(rE), nameYMMReg(rG) );
25536663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
25537663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 1 );
25538663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( src, loadLE(Ity_V256, mkexpr(addr) ) );
25539663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm = getUChar(delta+alen);
25540663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (imm & ~15) break;
25541663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen+1;
25542663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "vroundps $%d,%s,%s\n", imm, dis_buf, nameYMMReg(rG) );
25543663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
25544663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25545663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* (imm & 3) contains an Intel-encoded rounding mode.  Because
25546663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            that encoding is the same as the encoding for IRRoundingMode,
25547663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            we can use that value directly in the IR as a rounding
25548663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            mode. */
25549663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(rm, (imm & 4) ? get_sse_roundingmode() : mkU32(imm & 3));
25550663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25551663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         breakupV256to32s( src, &s7, &s6, &s5, &s4, &s3, &s2, &s1, &s0 );
25552663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#        define CVT(s) binop(Iop_RoundF32toInt, mkexpr(rm), \
25553663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             unop(Iop_ReinterpI32asF32, mkexpr(s)))
25554663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLane32F( rG, 7, CVT(s7) );
25555663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLane32F( rG, 6, CVT(s6) );
25556663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLane32F( rG, 5, CVT(s5) );
25557663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLane32F( rG, 4, CVT(s4) );
25558663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLane32F( rG, 3, CVT(s3) );
25559663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLane32F( rG, 2, CVT(s2) );
25560663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLane32F( rG, 1, CVT(s1) );
25561663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLane32F( rG, 0, CVT(s0) );
25562663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#        undef CVT
25563663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
25564663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
25565663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25566663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x09:
25567663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VROUNDPD imm8, xmm2/m128, xmm1 */
25568663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VROUNDPD = VEX.NDS.128.66.0F3A.WIG 09 ib */
25569663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
25570663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm = getUChar(delta);
25571663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG    = gregOfRexRM(pfx, modrm);
25572663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp src   = newTemp(Ity_V128);
25573663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp s0    = IRTemp_INVALID;
25574663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp s1    = IRTemp_INVALID;
25575663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp rm    = newTemp(Ity_I32);
25576663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int    imm   = 0;
25577663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25578663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
25579663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25580663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
25581663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx, modrm);
25582663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( src, getXMMReg( rE ) );
25583663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm = getUChar(delta+1);
25584663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (imm & ~15) break;
25585663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1+1;
25586663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "vroundpd $%d,%s,%s\n", imm, nameXMMReg(rE), nameXMMReg(rG) );
25587663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
25588663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 1 );
25589663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( src, loadLE(Ity_V128, mkexpr(addr) ) );
25590663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm = getUChar(delta+alen);
25591663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (imm & ~15) break;
25592663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen+1;
25593663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "vroundpd $%d,%s,%s\n", imm, dis_buf, nameXMMReg(rG) );
25594663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
25595663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25596663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* (imm & 3) contains an Intel-encoded rounding mode.  Because
25597663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            that encoding is the same as the encoding for IRRoundingMode,
25598663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            we can use that value directly in the IR as a rounding
25599663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            mode. */
25600663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(rm, (imm & 4) ? get_sse_roundingmode() : mkU32(imm & 3));
25601663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25602663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         breakupV128to64s( src, &s1, &s0 );
25603663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLane128( rG, 1, mkV128(0) );
25604663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#        define CVT(s) binop(Iop_RoundF64toInt, mkexpr(rm), \
25605663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             unop(Iop_ReinterpI64asF64, mkexpr(s)))
25606663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLane64F( rG, 1, CVT(s1) );
25607663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLane64F( rG, 0, CVT(s0) );
25608663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#        undef CVT
25609663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
25610663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
25611663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VROUNDPD imm8, ymm2/m256, ymm1 */
25612663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VROUNDPD = VEX.NDS.256.66.0F3A.WIG 09 ib */
25613663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
25614663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm = getUChar(delta);
25615663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG    = gregOfRexRM(pfx, modrm);
25616663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp src   = newTemp(Ity_V256);
25617663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp s0    = IRTemp_INVALID;
25618663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp s1    = IRTemp_INVALID;
25619663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp s2    = IRTemp_INVALID;
25620663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp s3    = IRTemp_INVALID;
25621663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp rm    = newTemp(Ity_I32);
25622663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int    imm   = 0;
25623663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25624663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         modrm = getUChar(delta);
25625663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25626663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
25627663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx, modrm);
25628663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( src, getYMMReg( rE ) );
25629663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm = getUChar(delta+1);
25630663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (imm & ~15) break;
25631663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1+1;
25632663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "vroundpd $%d,%s,%s\n", imm, nameYMMReg(rE), nameYMMReg(rG) );
25633663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
25634663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 1 );
25635663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( src, loadLE(Ity_V256, mkexpr(addr) ) );
25636663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm = getUChar(delta+alen);
25637663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (imm & ~15) break;
25638663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen+1;
25639663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "vroundps $%d,%s,%s\n", imm, dis_buf, nameYMMReg(rG) );
25640663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
25641663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25642663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* (imm & 3) contains an Intel-encoded rounding mode.  Because
25643663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            that encoding is the same as the encoding for IRRoundingMode,
25644663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            we can use that value directly in the IR as a rounding
25645663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            mode. */
25646663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(rm, (imm & 4) ? get_sse_roundingmode() : mkU32(imm & 3));
25647663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25648663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         breakupV256to64s( src, &s3, &s2, &s1, &s0 );
25649663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#        define CVT(s) binop(Iop_RoundF64toInt, mkexpr(rm), \
25650663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             unop(Iop_ReinterpI64asF64, mkexpr(s)))
25651663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLane64F( rG, 3, CVT(s3) );
25652663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLane64F( rG, 2, CVT(s2) );
25653663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLane64F( rG, 1, CVT(s1) );
25654663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLane64F( rG, 0, CVT(s0) );
25655663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#        undef CVT
25656663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
25657663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
25658663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25659663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x0A:
25660663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x0B:
25661663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VROUNDSS imm8, xmm3/m32, xmm2, xmm1 */
25662663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VROUNDSS = VEX.NDS.128.66.0F3A.WIG 0A ib */
25663663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VROUNDSD imm8, xmm3/m64, xmm2, xmm1 */
25664663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VROUNDSD = VEX.NDS.128.66.0F3A.WIG 0B ib */
25665663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
25666663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm = getUChar(delta);
25667663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG    = gregOfRexRM(pfx, modrm);
25668663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rV    = getVexNvvvv(pfx);
25669663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Bool   isD   = opc == 0x0B;
25670663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp src   = newTemp(isD ? Ity_F64 : Ity_F32);
25671663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp res   = newTemp(isD ? Ity_F64 : Ity_F32);
25672663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int    imm   = 0;
25673663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25674663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
25675663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx, modrm);
25676663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( src,
25677663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    isD ? getXMMRegLane64F(rE, 0) : getXMMRegLane32F(rE, 0) );
25678663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm = getUChar(delta+1);
25679663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (imm & ~15) break;
25680663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1+1;
25681663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "vrounds%c $%d,%s,%s,%s\n",
25682663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 isD ? 'd' : 's',
25683663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 imm, nameXMMReg( rE ), nameXMMReg( rV ), nameXMMReg( rG ) );
25684663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
25685663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 1 );
25686663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( src, loadLE( isD ? Ity_F64 : Ity_F32, mkexpr(addr) ));
25687663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm = getUChar(delta+alen);
25688663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (imm & ~15) break;
25689663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen+1;
25690663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "vrounds%c $%d,%s,%s,%s\n",
25691663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 isD ? 'd' : 's',
25692663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 imm, dis_buf, nameXMMReg( rV ), nameXMMReg( rG ) );
25693663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
25694663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25695663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* (imm & 3) contains an Intel-encoded rounding mode.  Because
25696663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            that encoding is the same as the encoding for IRRoundingMode,
25697663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            we can use that value directly in the IR as a rounding
25698663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            mode. */
25699663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(res, binop(isD ? Iop_RoundF64toInt : Iop_RoundF32toInt,
25700663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           (imm & 4) ? get_sse_roundingmode()
25701663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                     : mkU32(imm & 3),
25702663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           mkexpr(src)) );
25703663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25704663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (isD)
25705663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putXMMRegLane64F( rG, 0, mkexpr(res) );
25706663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         else {
25707663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putXMMRegLane32F( rG, 0, mkexpr(res) );
25708663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putXMMRegLane32F( rG, 1, getXMMRegLane32F( rV, 1 ) );
25709663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
25710663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putXMMRegLane64F( rG, 1, getXMMRegLane64F( rV, 1 ) );
25711663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLane128( rG, 1, mkV128(0) );
25712663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
25713663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
25714663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
25715663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
25716663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25717663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x0C:
25718663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VBLENDPS imm8, ymm3/m256, ymm2, ymm1 */
25719663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VBLENDPS = VEX.NDS.256.66.0F3A.WIG 0C /r ib */
25720663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
25721663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm = getUChar(delta);
25722663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   imm8;
25723663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG    = gregOfRexRM(pfx, modrm);
25724663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rV    = getVexNvvvv(pfx);
25725663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sV    = newTemp(Ity_V256);
25726663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sE    = newTemp(Ity_V256);
25727663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign ( sV, getYMMReg(rV) );
25728663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
25729663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx, modrm);
25730663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
25731663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = getUChar(delta);
25732663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vblendps $%u,%s,%s,%s\n",
25733663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                imm8, nameYMMReg(rE), nameYMMReg(rV), nameYMMReg(rG));
25734663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(sE, getYMMReg(rE));
25735663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
25736663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 1 );
25737663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
25738663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = getUChar(delta);
25739663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vblendps $%u,%s,%s,%s\n",
25740663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                imm8, dis_buf, nameYMMReg(rV), nameYMMReg(rG));
25741663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(sE, loadLE(Ity_V256, mkexpr(addr)));
25742663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
25743663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta++;
25744663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMReg( rG,
25745663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    mkexpr( math_BLENDPS_256( sE, sV, imm8) ) );
25746663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
25747663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
25748663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
25749663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VBLENDPS imm8, xmm3/m128, xmm2, xmm1 */
25750663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VBLENDPS = VEX.NDS.128.66.0F3A.WIG 0C /r ib */
25751663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
25752663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm = getUChar(delta);
25753663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   imm8;
25754663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG    = gregOfRexRM(pfx, modrm);
25755663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rV    = getVexNvvvv(pfx);
25756663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sV    = newTemp(Ity_V128);
25757663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sE    = newTemp(Ity_V128);
25758663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign ( sV, getXMMReg(rV) );
25759663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
25760663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx, modrm);
25761663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
25762663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = getUChar(delta);
25763663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vblendps $%u,%s,%s,%s\n",
25764663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                imm8, nameXMMReg(rE), nameXMMReg(rV), nameXMMReg(rG));
25765663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(sE, getXMMReg(rE));
25766663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
25767663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 1 );
25768663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
25769663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = getUChar(delta);
25770663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vblendps $%u,%s,%s,%s\n",
25771663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                imm8, dis_buf, nameXMMReg(rV), nameXMMReg(rG));
25772663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(sE, loadLE(Ity_V128, mkexpr(addr)));
25773663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
25774663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta++;
25775663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLoAndZU( rG,
25776663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           mkexpr( math_BLENDPS_128( sE, sV, imm8) ) );
25777663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
25778663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
25779663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
25780663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
25781663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25782663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x0D:
25783663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VBLENDPD imm8, ymm3/m256, ymm2, ymm1 */
25784663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VBLENDPD = VEX.NDS.256.66.0F3A.WIG 0D /r ib */
25785663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
25786663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm = getUChar(delta);
25787663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   imm8;
25788663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG    = gregOfRexRM(pfx, modrm);
25789663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rV    = getVexNvvvv(pfx);
25790663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sV    = newTemp(Ity_V256);
25791663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sE    = newTemp(Ity_V256);
25792663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign ( sV, getYMMReg(rV) );
25793663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
25794663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx, modrm);
25795663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
25796663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = getUChar(delta);
25797663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vblendpd $%u,%s,%s,%s\n",
25798663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                imm8, nameYMMReg(rE), nameYMMReg(rV), nameYMMReg(rG));
25799663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(sE, getYMMReg(rE));
25800663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
25801663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 1 );
25802663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
25803663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = getUChar(delta);
25804663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vblendpd $%u,%s,%s,%s\n",
25805663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                imm8, dis_buf, nameYMMReg(rV), nameYMMReg(rG));
25806663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(sE, loadLE(Ity_V256, mkexpr(addr)));
25807663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
25808663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta++;
25809663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMReg( rG,
25810663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    mkexpr( math_BLENDPD_256( sE, sV, imm8) ) );
25811663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
25812663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
25813663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
25814663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VBLENDPD imm8, xmm3/m128, xmm2, xmm1 */
25815663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VBLENDPD = VEX.NDS.128.66.0F3A.WIG 0D /r ib */
25816663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
25817663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm = getUChar(delta);
25818663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   imm8;
25819663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG    = gregOfRexRM(pfx, modrm);
25820663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rV    = getVexNvvvv(pfx);
25821663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sV    = newTemp(Ity_V128);
25822663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sE    = newTemp(Ity_V128);
25823663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign ( sV, getXMMReg(rV) );
25824663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
25825663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx, modrm);
25826663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
25827663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = getUChar(delta);
25828663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vblendpd $%u,%s,%s,%s\n",
25829663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                imm8, nameXMMReg(rE), nameXMMReg(rV), nameXMMReg(rG));
25830663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(sE, getXMMReg(rE));
25831663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
25832663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 1 );
25833663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
25834663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = getUChar(delta);
25835663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vblendpd $%u,%s,%s,%s\n",
25836663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                imm8, dis_buf, nameXMMReg(rV), nameXMMReg(rG));
25837663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(sE, loadLE(Ity_V128, mkexpr(addr)));
25838663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
25839663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta++;
25840663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLoAndZU( rG,
25841663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           mkexpr( math_BLENDPD_128( sE, sV, imm8) ) );
25842663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
25843663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
25844663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
25845663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
25846663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25847663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x0E:
25848663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPBLENDW imm8, xmm3/m128, xmm2, xmm1 */
25849663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPBLENDW = VEX.NDS.128.66.0F3A.WIG 0E /r ib */
25850663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
25851663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm = getUChar(delta);
25852663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   imm8;
25853663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG    = gregOfRexRM(pfx, modrm);
25854663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rV    = getVexNvvvv(pfx);
25855663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sV    = newTemp(Ity_V128);
25856663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sE    = newTemp(Ity_V128);
25857663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign ( sV, getXMMReg(rV) );
25858663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
25859663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx, modrm);
25860663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
25861663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = getUChar(delta);
25862663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vpblendw $%u,%s,%s,%s\n",
25863663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                imm8, nameXMMReg(rE), nameXMMReg(rV), nameXMMReg(rG));
25864663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(sE, getXMMReg(rE));
25865663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
25866663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 1 );
25867663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
25868663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = getUChar(delta);
25869663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vpblendw $%u,%s,%s,%s\n",
25870663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                imm8, dis_buf, nameYMMReg(rV), nameYMMReg(rG));
25871663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(sE, loadLE(Ity_V128, mkexpr(addr)));
25872663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
25873663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta++;
25874663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLoAndZU( rG,
25875663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           mkexpr( math_PBLENDW_128( sE, sV, imm8) ) );
25876663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
25877663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
25878663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
25879663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
25880663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25881663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x0F:
25882663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPALIGNR imm8, xmm3/m128, xmm2, xmm1 */
25883663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPALIGNR = VEX.NDS.128.66.0F3A.WIG 0F /r ib */
25884663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
25885663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm = getUChar(delta);
25886663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG    = gregOfRexRM(pfx, modrm);
25887663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rV    = getVexNvvvv(pfx);
25888663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sV    = newTemp(Ity_V128);
25889663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dV    = newTemp(Ity_V128);
25890663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   imm8;
25891663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25892663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( dV, getXMMReg(rV) );
25893663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25894663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if ( epartIsReg( modrm ) ) {
25895663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt   rE = eregOfRexRM(pfx, modrm);
25896663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, getXMMReg(rE) );
25897663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = getUChar(delta+1);
25898663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1+1;
25899663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vpalignr $%d,%s,%s,%s\n", imm8, nameXMMReg(rE),
25900663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                           nameXMMReg(rV), nameXMMReg(rG));
25901663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
25902663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 1 );
25903663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
25904663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = getUChar(delta+alen);
25905663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen+1;
25906663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vpalignr $%d,%s,%s,%s\n", imm8, dis_buf,
25907663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                           nameXMMReg(rV), nameXMMReg(rG));
25908663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
25909663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25910663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp res = math_PALIGNR_XMM( sV, dV, imm8 );
25911663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLoAndZU( rG, mkexpr(res) );
25912663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
25913663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
25914663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
25915663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
25916663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25917663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x14:
25918663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPEXTRB imm8, xmm2, reg/m8 = VEX.128.66.0F3A.W0 14 /r ib */
25919663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
25920663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && 0==getVexL(pfx)/*128*/ && 0==getRexW(pfx)/*W0*/) {
25921663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_PEXTRB_128_GtoE( vbi, pfx, delta, False/*!isAvx*/ );
25922663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
25923663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
25924663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
25925663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25926663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x15:
25927663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPEXTRW imm8, reg/m16, xmm2 */
25928663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPEXTRW = VEX.128.66.0F3A.W0 15 /r ib */
25929663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
25930663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && 0==getVexL(pfx)/*128*/ && 0==getRexW(pfx)/*W0*/) {
25931663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_PEXTRW( vbi, pfx, delta, True/*isAvx*/ );
25932663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
25933663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
25934663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
25935663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25936663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x16:
25937663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPEXTRD imm8, r32/m32, xmm2 */
25938663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPEXTRD = VEX.128.66.0F3A.W0 16 /r ib */
25939663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
25940663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && 0==getVexL(pfx)/*128*/ && 0==getRexW(pfx)/*W0*/) {
25941663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_PEXTRD( vbi, pfx, delta, True/*isAvx*/ );
25942663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
25943663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
25944663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPEXTRQ = VEX.128.66.0F3A.W1 16 /r ib */
25945663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
25946663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && 0==getVexL(pfx)/*128*/ && 1==getRexW(pfx)/*W1*/) {
25947663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_PEXTRQ( vbi, pfx, delta, True/*isAvx*/ );
25948663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
25949663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
25950663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
25951663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25952663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x17:
25953663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VEXTRACTPS imm8, xmm1, r32/m32 = VEX.128.66.0F3A.WIG 17 /r ib */
25954663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
25955663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_EXTRACTPS( vbi, pfx, delta, True/*isAvx*/ );
25956663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
25957663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
25958663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
25959663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25960663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x18:
25961663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VINSERTF128 r/m, rV, rD
25962663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         ::: rD = insertinto(a lane in rV, 128 bits from r/m) */
25963663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VINSERTF128 = VEX.NDS.256.66.0F3A.W0 18 /r ib */
25964663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
25965663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && 1==getVexL(pfx)/*256*/ && 0==getRexW(pfx)/*W0*/) {
25966663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm = getUChar(delta);
25967663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   ib    = 0;
25968663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG    = gregOfRexRM(pfx, modrm);
25969663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rV    = getVexNvvvv(pfx);
25970663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp t128  = newTemp(Ity_V128);
25971663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
25972663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx, modrm);
25973663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
25974663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(t128, getXMMReg(rE));
25975663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            ib = getUChar(delta);
25976663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vinsertf128 $%u,%s,%s,%s\n",
25977663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                ib, nameXMMReg(rE), nameYMMReg(rV), nameYMMReg(rG));
25978663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
25979663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 1 );
25980663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(t128, loadLE(Ity_V128, mkexpr(addr)));
25981663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
25982663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            ib = getUChar(delta);
25983663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vinsertf128 $%u,%s,%s,%s\n",
25984663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                ib, dis_buf, nameYMMReg(rV), nameYMMReg(rG));
25985663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
25986663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta++;
25987663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLane128(rG, 0,   getYMMRegLane128(rV, 0));
25988663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLane128(rG, 1,   getYMMRegLane128(rV, 1));
25989663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLane128(rG, ib & 1, mkexpr(t128));
25990663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
25991663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
25992663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
25993663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
25994663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
25995663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x19:
25996663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     /* VEXTRACTF128 $lane_no, rS, r/m
25997663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        ::: r/m:V128 = a lane of rS:V256 (RM format) */
25998663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     /* VEXTRACTF128 = VEX.256.66.0F3A.W0 19 /r ib */
25999663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
26000663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && 1==getVexL(pfx)/*256*/ && 0==getRexW(pfx)/*W0*/) {
26001663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm = getUChar(delta);
26002663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   ib    = 0;
26003663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rS    = gregOfRexRM(pfx, modrm);
26004663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp t128  = newTemp(Ity_V128);
26005663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg(modrm)) {
26006663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rD = eregOfRexRM(pfx, modrm);
26007663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1;
26008663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            ib = getUChar(delta);
26009663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(t128, getYMMRegLane128(rS, ib & 1));
26010663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putYMMRegLoAndZU(rD, mkexpr(t128));
26011663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vextractf128 $%u,%s,%s\n",
26012663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                ib, nameXMMReg(rS), nameYMMReg(rD));
26013663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
26014663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 1 );
26015663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen;
26016663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            ib = getUChar(delta);
26017663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(t128, getYMMRegLane128(rS, ib & 1));
26018663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            storeLE(mkexpr(addr), mkexpr(t128));
26019663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("vextractf128 $%u,%s,%s\n",
26020663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                ib, nameYMMReg(rS), dis_buf);
26021663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
26022663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta++;
26023663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* doesn't use vvvv */
26024663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
26025663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
26026663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
26027663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26028663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x20:
26029663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPINSRB r32/m8, xmm2, xmm1 = VEX.NDS.128.66.0F3A.W0 20 /r ib */
26030663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
26031663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && 0==getVexL(pfx)/*128*/ && 0==getRexW(pfx)/*W0*/) {
26032663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm  = getUChar(delta);
26033663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG     = gregOfRexRM(pfx, modrm);
26034663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rV     = getVexNvvvv(pfx);
26035663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int    imm8;
26036663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp src_u8 = newTemp(Ity_I8);
26037663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26038663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if ( epartIsReg( modrm ) ) {
26039663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
26040663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = (Int)(getUChar(delta+1) & 15);
26041663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( src_u8, unop(Iop_32to8, getIReg32( rE )) );
26042663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1+1;
26043663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "vpinsrb $%d,%s,%s,%s\n",
26044663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 imm8, nameIReg32(rE), nameXMMReg(rV), nameXMMReg(rG) );
26045663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
26046663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 1 );
26047663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = (Int)(getUChar(delta+alen) & 15);
26048663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( src_u8, loadLE( Ity_I8, mkexpr(addr) ) );
26049663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen+1;
26050663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "vpinsrb $%d,%s,%s,%s\n",
26051663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 imm8, dis_buf, nameXMMReg(rV), nameXMMReg(rG) );
26052663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
26053663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26054663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp src_vec = newTemp(Ity_V128);
26055663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(src_vec, getXMMReg( rV ));
26056663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp res_vec = math_PINSRB_128( src_vec, src_u8, imm8 );
26057663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLoAndZU( rG, mkexpr(res_vec) );
26058663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
26059663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
26060663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
26061663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
26062663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26063663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x21:
26064663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VINSERTPS imm8, xmm3/m32, xmm2, xmm1
26065663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         = VEX.NDS.128.66.0F3A.WIG 21 /r ib */
26066663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
26067663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm = getUChar(delta);
26068663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG    = gregOfRexRM(pfx, modrm);
26069663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rV    = getVexNvvvv(pfx);
26070663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   imm8;
26071663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp d2ins = newTemp(Ity_I32); /* comes from the E part */
26072663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         const IRTemp inval = IRTemp_INVALID;
26073663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26074663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if ( epartIsReg( modrm ) ) {
26075663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt   rE = eregOfRexRM(pfx, modrm);
26076663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            IRTemp vE = newTemp(Ity_V128);
26077663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( vE, getXMMReg(rE) );
26078663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            IRTemp dsE[4] = { inval, inval, inval, inval };
26079663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            breakupV128to32s( vE, &dsE[3], &dsE[2], &dsE[1], &dsE[0] );
26080663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = getUChar(delta+1);
26081663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            d2ins = dsE[(imm8 >> 6) & 3]; /* "imm8_count_s" */
26082663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1+1;
26083663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "insertps $%u, %s,%s\n",
26084663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 imm8, nameXMMReg(rE), nameXMMReg(rG) );
26085663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
26086663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 1 );
26087663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( d2ins, loadLE( Ity_I32, mkexpr(addr) ) );
26088663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = getUChar(delta+alen);
26089663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen+1;
26090663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "insertps $%u, %s,%s\n",
26091663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 imm8, dis_buf, nameXMMReg(rG) );
26092663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
26093663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26094663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp vV = newTemp(Ity_V128);
26095663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( vV, getXMMReg(rV) );
26096663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26097663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLoAndZU( rG, mkexpr(math_INSERTPS( vV, d2ins, imm8 )) );
26098663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
26099663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
26100663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
26101663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
26102663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26103663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x22:
26104663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPINSRD r32/m32, xmm2, xmm1 = VEX.NDS.128.66.0F3A.W0 22 /r ib */
26105663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
26106663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && 0==getVexL(pfx)/*128*/ && 0==getRexW(pfx)/*W0*/) {
26107663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm = getUChar(delta);
26108663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG    = gregOfRexRM(pfx, modrm);
26109663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rV    = getVexNvvvv(pfx);
26110663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int    imm8_10;
26111663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp src_u32 = newTemp(Ity_I32);
26112663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26113663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if ( epartIsReg( modrm ) ) {
26114663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
26115663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8_10 = (Int)(getUChar(delta+1) & 3);
26116663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( src_u32, getIReg32( rE ) );
26117663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1+1;
26118663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "vpinsrd $%d,%s,%s,%s\n",
26119663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 imm8_10, nameIReg32(rE), nameXMMReg(rV), nameXMMReg(rG) );
26120663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
26121663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 1 );
26122663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8_10 = (Int)(getUChar(delta+alen) & 3);
26123663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( src_u32, loadLE( Ity_I32, mkexpr(addr) ) );
26124663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen+1;
26125663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "vpinsrd $%d,%s,%s,%s\n",
26126663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 imm8_10, dis_buf, nameXMMReg(rV), nameXMMReg(rG) );
26127663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
26128663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26129663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp src_vec = newTemp(Ity_V128);
26130663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(src_vec, getXMMReg( rV ));
26131663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp res_vec = math_PINSRD_128( src_vec, src_u32, imm8_10 );
26132663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLoAndZU( rG, mkexpr(res_vec) );
26133663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
26134663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
26135663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
26136663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPINSRQ r64/m64, xmm2, xmm1 = VEX.NDS.128.66.0F3A.W1 22 /r ib */
26137663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx)
26138663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && 0==getVexL(pfx)/*128*/ && 1==getRexW(pfx)/*W1*/) {
26139663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm = getUChar(delta);
26140663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG    = gregOfRexRM(pfx, modrm);
26141663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rV    = getVexNvvvv(pfx);
26142663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int    imm8_0;
26143663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp src_u64 = newTemp(Ity_I64);
26144663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26145663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if ( epartIsReg( modrm ) ) {
26146663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
26147663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8_0 = (Int)(getUChar(delta+1) & 1);
26148663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( src_u64, getIReg64( rE ) );
26149663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1+1;
26150663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "vpinsrq $%d,%s,%s,%s\n",
26151663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 imm8_0, nameIReg64(rE), nameXMMReg(rV), nameXMMReg(rG) );
26152663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
26153663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 1 );
26154663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8_0 = (Int)(getUChar(delta+alen) & 1);
26155663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( src_u64, loadLE( Ity_I64, mkexpr(addr) ) );
26156663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen+1;
26157663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "vpinsrd $%d,%s,%s,%s\n",
26158663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 imm8_0, dis_buf, nameXMMReg(rV), nameXMMReg(rG) );
26159663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
26160663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26161663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp src_vec = newTemp(Ity_V128);
26162663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(src_vec, getXMMReg( rV ));
26163663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp res_vec = math_PINSRQ_128( src_vec, src_u64, imm8_0 );
26164663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLoAndZU( rG, mkexpr(res_vec) );
26165663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
26166663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
26167663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
26168663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
26169663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26170663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x40:
26171663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VDPPS imm8, xmm3/m128,xmm2,xmm1 = VEX.NDS.128.66.0F3A.WIG 40 /r ib */
26172663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
26173663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm   = getUChar(delta);
26174663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG      = gregOfRexRM(pfx, modrm);
26175663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rV      = getVexNvvvv(pfx);
26176663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dst_vec = newTemp(Ity_V128);
26177663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int    imm8;
26178663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg( modrm )) {
26179663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
26180663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = (Int)getUChar(delta+1);
26181663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( dst_vec, getXMMReg( rE ) );
26182663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1+1;
26183663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "vdpps $%d,%s,%s,%s\n",
26184663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 imm8, nameXMMReg(rE), nameXMMReg(rV), nameXMMReg(rG) );
26185663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
26186663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 1 );
26187663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = (Int)getUChar(delta+alen);
26188663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( dst_vec, loadLE( Ity_V128, mkexpr(addr) ) );
26189663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen+1;
26190663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "vdpps $%d,%s,%s,%s\n",
26191663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 imm8, dis_buf, nameXMMReg(rV), nameXMMReg(rG) );
26192663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
26193663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26194663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp src_vec = newTemp(Ity_V128);
26195663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(src_vec, getXMMReg( rV ));
26196663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp res_vec = math_DPPS_128( src_vec, dst_vec, imm8 );
26197663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLoAndZU( rG, mkexpr(res_vec) );
26198663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
26199663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
26200663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
26201663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VDPPS imm8, ymm3/m128,ymm2,ymm1 = VEX.NDS.256.66.0F3A.WIG 40 /r ib */
26202663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
26203663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm   = getUChar(delta);
26204663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG      = gregOfRexRM(pfx, modrm);
26205663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rV      = getVexNvvvv(pfx);
26206663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dst_vec = newTemp(Ity_V256);
26207663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int    imm8;
26208663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg( modrm )) {
26209663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
26210663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = (Int)getUChar(delta+1);
26211663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( dst_vec, getYMMReg( rE ) );
26212663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1+1;
26213663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "vdpps $%d,%s,%s,%s\n",
26214663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 imm8, nameYMMReg(rE), nameYMMReg(rV), nameYMMReg(rG) );
26215663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
26216663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 1 );
26217663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = (Int)getUChar(delta+alen);
26218663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( dst_vec, loadLE( Ity_V256, mkexpr(addr) ) );
26219663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen+1;
26220663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "vdpps $%d,%s,%s,%s\n",
26221663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 imm8, dis_buf, nameYMMReg(rV), nameYMMReg(rG) );
26222663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
26223663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26224663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp src_vec = newTemp(Ity_V256);
26225663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(src_vec, getYMMReg( rV ));
26226663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp s0, s1, d0, d1;
26227663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         s0 = s1 = d0 = d1 = IRTemp_INVALID;
26228663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         breakupV256toV128s( dst_vec, &d1, &d0 );
26229663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         breakupV256toV128s( src_vec, &s1, &s0 );
26230663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMReg( rG, binop( Iop_V128HLtoV256,
26231663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               mkexpr( math_DPPS_128(s1, d1, imm8) ),
26232663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               mkexpr( math_DPPS_128(s0, d0, imm8) ) ) );
26233663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
26234663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
26235663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
26236663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
26237663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26238663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x41:
26239663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VDPPD imm8, xmm3/m128,xmm2,xmm1 = VEX.NDS.128.66.0F3A.WIG 41 /r ib */
26240663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
26241663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm   = getUChar(delta);
26242663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG      = gregOfRexRM(pfx, modrm);
26243663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rV      = getVexNvvvv(pfx);
26244663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dst_vec = newTemp(Ity_V128);
26245663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int    imm8;
26246663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (epartIsReg( modrm )) {
26247663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx,modrm);
26248663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = (Int)getUChar(delta+1);
26249663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( dst_vec, getXMMReg( rE ) );
26250663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1+1;
26251663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "vdppd $%d,%s,%s,%s\n",
26252663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 imm8, nameXMMReg(rE), nameXMMReg(rV), nameXMMReg(rG) );
26253663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
26254663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf, 1 );
26255663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = (Int)getUChar(delta+alen);
26256663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( dst_vec, loadLE( Ity_V128, mkexpr(addr) ) );
26257663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen+1;
26258663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "vdppd $%d,%s,%s,%s\n",
26259663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 imm8, dis_buf, nameXMMReg(rV), nameXMMReg(rG) );
26260663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
26261663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26262663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp src_vec = newTemp(Ity_V128);
26263663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(src_vec, getXMMReg( rV ));
26264663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp res_vec = math_DPPD_128( src_vec, dst_vec, imm8 );
26265663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLoAndZU( rG, mkexpr(res_vec) );
26266663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
26267663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
26268663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
26269663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
26270663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26271663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x42:
26272663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMPSADBW imm8, xmm3/m128,xmm2,xmm1 */
26273663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VMPSADBW = VEX.NDS.128.66.0F3A.WIG 42 /r ib */
26274663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
26275663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm   = getUChar(delta);
26276663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int    imm8;
26277663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp src_vec = newTemp(Ity_V128);
26278663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dst_vec = newTemp(Ity_V128);
26279663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG      = gregOfRexRM(pfx, modrm);
26280663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rV      = getVexNvvvv(pfx);
26281663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26282663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( dst_vec, getXMMReg(rV) );
26283663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26284663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if ( epartIsReg( modrm ) ) {
26285663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx, modrm);
26286663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26287663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = (Int)getUChar(delta+1);
26288663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( src_vec, getXMMReg(rE) );
26289663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1+1;
26290663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "vmpsadbw $%d, %s,%s,%s\n", imm8,
26291663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 nameXMMReg(rE), nameXMMReg(rV), nameXMMReg(rG) );
26292663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
26293663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf,
26294663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             1/* imm8 is 1 byte after the amode */ );
26295663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( src_vec, loadLE( Ity_V128, mkexpr(addr) ) );
26296663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = (Int)getUChar(delta+alen);
26297663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen+1;
26298663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "vmpsadbw $%d, %s,%s,%s\n", imm8,
26299663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 dis_buf, nameXMMReg(rV), nameXMMReg(rG) );
26300663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
26301663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26302663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLoAndZU( rG, mkexpr( math_MPSADBW_128(dst_vec,
26303663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                                        src_vec, imm8) ) );
26304663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
26305663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
26306663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
26307663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
26308663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26309663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x44:
26310663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPCLMULQDQ imm8, xmm3/m128,xmm2,xmm1 */
26311663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPCLMULQDQ = VEX.NDS.128.66.0F3A.WIG 44 /r ib */
26312663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 66 0F 3A 44 /r ib = PCLMULQDQ xmm1, xmm2/m128, imm8
26313663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       * Carry-less multiplication of selected XMM quadwords into XMM
26314663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       * registers (a.k.a multiplication of polynomials over GF(2))
26315663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       */
26316663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
26317663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar  modrm = getUChar(delta);
26318663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int imm8;
26319663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp sV    = newTemp(Ity_V128);
26320663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp dV    = newTemp(Ity_V128);
26321663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rG    = gregOfRexRM(pfx, modrm);
26322663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt   rV    = getVexNvvvv(pfx);
26323663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26324663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign( dV, getXMMReg(rV) );
26325663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26326663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if ( epartIsReg( modrm ) ) {
26327663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt rE = eregOfRexRM(pfx, modrm);
26328663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = (Int)getUChar(delta+1);
26329663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, getXMMReg(rE) );
26330663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 1+1;
26331663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "vpclmulqdq $%d, %s,%s,%s\n", imm8,
26332663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 nameXMMReg(rE), nameXMMReg(rV), nameXMMReg(rG) );
26333663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
26334663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addr = disAMode( &alen, vbi, pfx, delta, dis_buf,
26335663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             1/* imm8 is 1 byte after the amode */ );
26336663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign( sV, loadLE( Ity_V128, mkexpr(addr) ) );
26337663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            imm8 = (Int)getUChar(delta+alen);
26338663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += alen+1;
26339663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP( "vpclmulqdq $%d, %s,%s,%s\n",
26340663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 imm8, dis_buf, nameXMMReg(rV), nameXMMReg(rG) );
26341663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
26342663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26343663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putYMMRegLoAndZU( rG, mkexpr( math_PCLMULQDQ(dV, sV, imm8) ) );
26344663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
26345663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
26346663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
26347663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
26348663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26349663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x4A:
26350663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VBLENDVPS xmmG, xmmE/memE, xmmV, xmmIS4
26351663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         ::: xmmG:V128 = PBLEND(xmmE, xmmV, xmmIS4) (RMVR) */
26352663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VBLENDVPS = VEX.NDS.128.66.0F3A.WIG 4A /r /is4 */
26353663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
26354663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VBLENDV_128 ( vbi, pfx, delta,
26355663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   "vblendvps", 4, Iop_SarN32x4 );
26356663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
26357663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
26358663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
26359663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VBLENDVPS ymmG, ymmE/memE, ymmV, ymmIS4
26360663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         ::: ymmG:V256 = PBLEND(ymmE, ymmV, ymmIS4) (RMVR) */
26361663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VBLENDVPS = VEX.NDS.256.66.0F3A.WIG 4A /r /is4 */
26362663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
26363663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VBLENDV_256 ( vbi, pfx, delta,
26364663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   "vblendvps", 4, Iop_SarN32x4 );
26365663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
26366663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
26367663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
26368663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
26369663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26370663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x4B:
26371663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VBLENDVPD xmmG, xmmE/memE, xmmV, xmmIS4
26372663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         ::: xmmG:V128 = PBLEND(xmmE, xmmV, xmmIS4) (RMVR) */
26373663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VBLENDVPD = VEX.NDS.128.66.0F3A.WIG 4B /r /is4 */
26374663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
26375663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VBLENDV_128 ( vbi, pfx, delta,
26376663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   "vblendvpd", 8, Iop_SarN64x2 );
26377663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
26378663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
26379663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
26380663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VBLENDVPD ymmG, ymmE/memE, ymmV, ymmIS4
26381663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         ::: ymmG:V256 = PBLEND(ymmE, ymmV, ymmIS4) (RMVR) */
26382663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VBLENDVPD = VEX.NDS.256.66.0F3A.WIG 4B /r /is4 */
26383663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 1==getVexL(pfx)/*256*/) {
26384663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VBLENDV_256 ( vbi, pfx, delta,
26385663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   "vblendvpd", 8, Iop_SarN64x2 );
26386663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
26387663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
26388663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
26389663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
26390663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26391663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x4C:
26392663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPBLENDVB xmmG, xmmE/memE, xmmV, xmmIS4
26393663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         ::: xmmG:V128 = PBLEND(xmmE, xmmV, xmmIS4) (RMVR) */
26394663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VPBLENDVB = VEX.NDS.128.66.0F3A.WIG 4C /r /is4 */
26395663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
26396663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_VBLENDV_128 ( vbi, pfx, delta,
26397663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   "vpblendvb", 1, Iop_SarN8x16 );
26398663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *uses_vvvv = True;
26399663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
26400663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
26401663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
26402663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26403663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x60:
26404663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x61:
26405663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x62:
26406663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x63:
26407663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VEX.128.66.0F3A.WIG 63 /r ib = VPCMPISTRI imm8, xmm2/m128, xmm1
26408663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         VEX.128.66.0F3A.WIG 62 /r ib = VPCMPISTRM imm8, xmm2/m128, xmm1
26409663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         VEX.128.66.0F3A.WIG 61 /r ib = VPCMPESTRI imm8, xmm2/m128, xmm1
26410663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         VEX.128.66.0F3A.WIG 60 /r ib = VPCMPESTRM imm8, xmm2/m128, xmm1
26411663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         (selected special cases that actually occur in glibc,
26412663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          not by any means a complete implementation.)
26413663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      */
26414663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
26415663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Long delta0 = delta;
26416663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_PCMPxSTRx( vbi, pfx, delta, True/*isAvx*/, opc );
26417663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (delta > delta0) goto decode_success;
26418663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* else fall though; dis_PCMPxSTRx failed to decode it */
26419663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
26420663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
26421663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26422663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xDF:
26423663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VAESKEYGENASSIST imm8, xmm2/m128, xmm1 = VEX.128.66.0F3A.WIG DF /r */
26424663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66noF2noF3(pfx) && 0==getVexL(pfx)/*128*/) {
26425663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_AESKEYGENASSIST( vbi, pfx, delta, True/*!isAvx*/ );
26426663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
26427663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
26428663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
26429663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26430663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   default:
26431663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
26432663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26433663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
26434663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26435663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  //decode_failure:
26436663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return deltaIN;
26437663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26438663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  decode_success:
26439663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return delta;
26440663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
26441663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26442663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26443663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*------------------------------------------------------------*/
26444663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---                                                      ---*/
26445663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*--- Disassemble a single instruction                     ---*/
26446663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---                                                      ---*/
26447663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*------------------------------------------------------------*/
26448663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26449663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Disassemble a single instruction into IR.  The instruction is
26450663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   located in host memory at &guest_code[delta]. */
26451663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26452663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic
26453663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengDisResult disInstr_AMD64_WRK (
26454663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             /*OUT*/Bool* expect_CAS,
26455663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             Bool         (*resteerOkFn) ( /*opaque*/void*, Addr64 ),
26456663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             Bool         resteerCisOk,
26457663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             void*        callback_opaque,
26458663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             Long         delta64,
26459663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             VexArchInfo* archinfo,
26460663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             VexAbiInfo*  vbi
26461663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          )
26462663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
26463663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp    t1, t2, t3, t4, t5, t6;
26464663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar     pre;
26465663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int       n, n_prefixes;
26466663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   DisResult dres;
26467663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26468663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* The running delta */
26469663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Long delta = delta64;
26470663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26471663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Holds eip at the start of the insn, so that we can print
26472663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      consistent error messages for unimplemented insns. */
26473663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Long delta_start = delta;
26474663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26475663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* sz denotes the nominal data-op size of the insn; we change it to
26476663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      2 if an 0x66 prefix is seen and 8 if REX.W is 1.  In case of
26477663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      conflict REX.W takes precedence. */
26478663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int sz = 4;
26479663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26480663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* pfx holds the summary of prefixes. */
26481663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Prefix pfx = PFX_EMPTY;
26482663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26483663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Holds the computed opcode-escape indication. */
26484663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Escape esc = ESC_NONE;
26485663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26486663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Set result defaults. */
26487663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   dres.whatNext    = Dis_Continue;
26488663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   dres.len         = 0;
26489663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   dres.continueAt  = 0;
26490663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   dres.jk_StopHere = Ijk_INVALID;
26491663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *expect_CAS = False;
26492663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26493663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(guest_RIP_next_assumed == 0);
26494663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(guest_RIP_next_mustcheck == False);
26495663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26496663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   t1 = t2 = t3 = t4 = t5 = t6 = IRTemp_INVALID;
26497663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26498663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   DIP("\t0x%llx:  ", guest_RIP_bbstart+delta);
26499663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26500663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Spot "Special" instructions (see comment at top of file). */
26501663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   {
26502663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UChar* code = (UChar*)(guest_code + delta);
26503663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Spot the 16-byte preamble:
26504663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         48C1C703   rolq $3,  %rdi
26505663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         48C1C70D   rolq $13, %rdi
26506663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         48C1C73D   rolq $61, %rdi
26507663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         48C1C733   rolq $51, %rdi
26508663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      */
26509663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (code[ 0] == 0x48 && code[ 1] == 0xC1 && code[ 2] == 0xC7
26510663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                               && code[ 3] == 0x03 &&
26511663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          code[ 4] == 0x48 && code[ 5] == 0xC1 && code[ 6] == 0xC7
26512663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                               && code[ 7] == 0x0D &&
26513663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          code[ 8] == 0x48 && code[ 9] == 0xC1 && code[10] == 0xC7
26514663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                               && code[11] == 0x3D &&
26515663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          code[12] == 0x48 && code[13] == 0xC1 && code[14] == 0xC7
26516663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                               && code[15] == 0x33) {
26517663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Got a "Special" instruction preamble.  Which one is it? */
26518663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (code[16] == 0x48 && code[17] == 0x87
26519663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              && code[18] == 0xDB /* xchgq %rbx,%rbx */) {
26520663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* %RDX = client_request ( %RAX ) */
26521663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("%%rdx = client_request ( %%rax )\n");
26522663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 19;
26523663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            jmp_lit(&dres, Ijk_ClientReq, guest_RIP_bbstart+delta);
26524663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            vassert(dres.whatNext == Dis_StopHere);
26525663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            goto decode_success;
26526663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
26527663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         else
26528663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (code[16] == 0x48 && code[17] == 0x87
26529663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              && code[18] == 0xC9 /* xchgq %rcx,%rcx */) {
26530663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* %RAX = guest_NRADDR */
26531663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("%%rax = guest_NRADDR\n");
26532663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 19;
26533663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putIRegRAX(8, IRExpr_Get( OFFB_NRADDR, Ity_I64 ));
26534663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            goto decode_success;
26535663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
26536663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         else
26537663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (code[16] == 0x48 && code[17] == 0x87
26538663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              && code[18] == 0xD2 /* xchgq %rdx,%rdx */) {
26539663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* call-noredir *%RAX */
26540663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            DIP("call-noredir *%%rax\n");
26541663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta += 19;
26542663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            t1 = newTemp(Ity_I64);
26543663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(t1, getIRegRAX(8));
26544663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            t2 = newTemp(Ity_I64);
26545663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            assign(t2, binop(Iop_Sub64, getIReg64(R_RSP), mkU64(8)));
26546663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            putIReg64(R_RSP, mkexpr(t2));
26547663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            storeLE( mkexpr(t2), mkU64(guest_RIP_bbstart+delta));
26548663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            jmp_treg(&dres, Ijk_NoRedir, t1);
26549663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            vassert(dres.whatNext == Dis_StopHere);
26550663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            goto decode_success;
26551663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
26552663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* We don't know what it is. */
26553663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_failure;
26554663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /*NOTREACHED*/
26555663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
26556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
26557663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26558663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Eat prefixes, summarising the result in pfx and sz, and rejecting
26559663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      as many invalid combinations as possible. */
26560663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   n_prefixes = 0;
26561663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   while (True) {
26562663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (n_prefixes > 7) goto decode_failure;
26563663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      pre = getUChar(delta);
26564663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (pre) {
26565663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case 0x66: pfx |= PFX_66; break;
26566663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case 0x67: pfx |= PFX_ASO; break;
26567663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case 0xF2: pfx |= PFX_F2; break;
26568663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case 0xF3: pfx |= PFX_F3; break;
26569663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case 0xF0: pfx |= PFX_LOCK; *expect_CAS = True; break;
26570663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case 0x2E: pfx |= PFX_CS; break;
26571663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case 0x3E: pfx |= PFX_DS; break;
26572663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case 0x26: pfx |= PFX_ES; break;
26573663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case 0x64: pfx |= PFX_FS; break;
26574663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case 0x65: pfx |= PFX_GS; break;
26575663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case 0x36: pfx |= PFX_SS; break;
26576663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case 0x40 ... 0x4F:
26577663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            pfx |= PFX_REX;
26578663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (pre & (1<<3)) pfx |= PFX_REXW;
26579663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (pre & (1<<2)) pfx |= PFX_REXR;
26580663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (pre & (1<<1)) pfx |= PFX_REXX;
26581663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (pre & (1<<0)) pfx |= PFX_REXB;
26582663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
26583663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         default:
26584663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            goto not_a_legacy_prefix;
26585663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
26586663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      n_prefixes++;
26587663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta++;
26588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
26589663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26590663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   not_a_legacy_prefix:
26591663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* We've used up all the non-VEX prefixes.  Parse and validate a
26592663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      VEX prefix if that's appropriate. */
26593663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (archinfo->hwcaps & VEX_HWCAPS_AMD64_AVX) {
26594663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Used temporarily for holding VEX prefixes. */
26595663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UChar vex0 = getUChar(delta);
26596663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (vex0 == 0xC4) {
26597663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* 3-byte VEX */
26598663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar vex1 = getUChar(delta+1);
26599663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar vex2 = getUChar(delta+2);
26600663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta += 3;
26601663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         pfx |= PFX_VEX;
26602663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Snarf contents of byte 1 */
26603663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* R */ pfx |= (vex1 & (1<<7)) ? 0 : PFX_REXR;
26604663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* X */ pfx |= (vex1 & (1<<6)) ? 0 : PFX_REXX;
26605663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* B */ pfx |= (vex1 & (1<<5)) ? 0 : PFX_REXB;
26606663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* m-mmmm */
26607663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         switch (vex1 & 0x1F) {
26608663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 1: esc = ESC_0F;   break;
26609663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 2: esc = ESC_0F38; break;
26610663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 3: esc = ESC_0F3A; break;
26611663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* Any other m-mmmm field will #UD */
26612663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            default: goto decode_failure;
26613663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
26614663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Snarf contents of byte 2 */
26615663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* W */    pfx |= (vex2 & (1<<7)) ? PFX_REXW : 0;
26616663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* ~v3 */  pfx |= (vex2 & (1<<6)) ? 0 : PFX_VEXnV3;
26617663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* ~v2 */  pfx |= (vex2 & (1<<5)) ? 0 : PFX_VEXnV2;
26618663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* ~v1 */  pfx |= (vex2 & (1<<4)) ? 0 : PFX_VEXnV1;
26619663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* ~v0 */  pfx |= (vex2 & (1<<3)) ? 0 : PFX_VEXnV0;
26620663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* L */    pfx |= (vex2 & (1<<2)) ? PFX_VEXL : 0;
26621663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* pp */
26622663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         switch (vex2 & 3) {
26623663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 0: break;
26624663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 1: pfx |= PFX_66; break;
26625663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 2: pfx |= PFX_F3; break;
26626663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 3: pfx |= PFX_F2; break;
26627663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            default: vassert(0);
26628663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
26629663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
26630663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      else if (vex0 == 0xC5) {
26631663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* 2-byte VEX */
26632663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UChar vex1 = getUChar(delta+1);
26633663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta += 2;
26634663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         pfx |= PFX_VEX;
26635663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Snarf contents of byte 1 */
26636663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* R */    pfx |= (vex1 & (1<<7)) ? 0 : PFX_REXR;
26637663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* ~v3 */  pfx |= (vex1 & (1<<6)) ? 0 : PFX_VEXnV3;
26638663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* ~v2 */  pfx |= (vex1 & (1<<5)) ? 0 : PFX_VEXnV2;
26639663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* ~v1 */  pfx |= (vex1 & (1<<4)) ? 0 : PFX_VEXnV1;
26640663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* ~v0 */  pfx |= (vex1 & (1<<3)) ? 0 : PFX_VEXnV0;
26641663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* L */    pfx |= (vex1 & (1<<2)) ? PFX_VEXL : 0;
26642663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* pp */
26643663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         switch (vex1 & 3) {
26644663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 0: break;
26645663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 1: pfx |= PFX_66; break;
26646663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 2: pfx |= PFX_F3; break;
26647663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 3: pfx |= PFX_F2; break;
26648663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            default: vassert(0);
26649663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
26650663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* implied: */
26651663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         esc = ESC_0F;
26652663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
26653663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Can't have both VEX and REX */
26654663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if ((pfx & PFX_VEX) && (pfx & PFX_REX))
26655663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_failure; /* can't have both */
26656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
26657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26658663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Dump invalid combinations */
26659663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   n = 0;
26660663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (pfx & PFX_F2) n++;
26661663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (pfx & PFX_F3) n++;
26662663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (n > 1)
26663663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      goto decode_failure; /* can't have both */
26664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26665663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   n = 0;
26666663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (pfx & PFX_CS) n++;
26667663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (pfx & PFX_DS) n++;
26668663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (pfx & PFX_ES) n++;
26669663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (pfx & PFX_FS) n++;
26670663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (pfx & PFX_GS) n++;
26671663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (pfx & PFX_SS) n++;
26672663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (n > 1)
26673663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      goto decode_failure; /* multiple seg overrides == illegal */
26674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26675663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* We have a %fs prefix.  Reject it if there's no evidence in 'vbi'
26676663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      that we should accept it. */
26677663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if ((pfx & PFX_FS) && !vbi->guest_amd64_assume_fs_is_zero)
26678663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      goto decode_failure;
26679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26680663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Ditto for %gs prefixes. */
26681663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if ((pfx & PFX_GS) && !vbi->guest_amd64_assume_gs_is_0x60)
26682663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      goto decode_failure;
26683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26684663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Set up sz. */
26685663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   sz = 4;
26686663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (pfx & PFX_66) sz = 2;
26687663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if ((pfx & PFX_REX) && (pfx & PFX_REXW)) sz = 8;
26688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26689663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Now we should be looking at the primary opcode byte or the
26690663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      leading escapes.  Check that any LOCK prefix is actually
26691663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      allowed. */
26692663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (pfx & PFX_LOCK) {
26693663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (can_be_used_with_LOCK_prefix( (UChar*)&guest_code[delta] )) {
26694663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("lock ");
26695663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      } else {
26696663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *expect_CAS = False;
26697663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_failure;
26698663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
26699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
26700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26701663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Eat up opcode escape bytes, until we're really looking at the
26702663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      primary opcode byte.  But only if there's no VEX present. */
26703663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (!(pfx & PFX_VEX)) {
26704663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(esc == ESC_NONE);
26705663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      pre = getUChar(delta);
26706663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (pre == 0x0F) {
26707663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta++;
26708663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         pre = getUChar(delta);
26709663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         switch (pre) {
26710663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 0x38: esc = ESC_0F38; delta++; break;
26711663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 0x3A: esc = ESC_0F3A; delta++; break;
26712663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            default:   esc = ESC_0F; break;
26713663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
26714663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
26715663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
26716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26717663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* So now we're really really looking at the primary opcode
26718663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      byte. */
26719663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Long delta_at_primary_opcode = delta;
26720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26721663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (!(pfx & PFX_VEX)) {
26722663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Handle non-VEX prefixed instructions.  "Legacy" (non-VEX) SSE
26723663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         instructions preserve the upper 128 bits of YMM registers;
26724663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         iow we can simply ignore the presence of the upper halves of
26725663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         these registers. */
26726663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (esc) {
26727663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case ESC_NONE:
26728663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta = dis_ESC_NONE( &dres, expect_CAS,
26729663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  resteerOkFn, resteerCisOk, callback_opaque,
26730663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  archinfo, vbi, pfx, sz, delta );
26731663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
26732663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case ESC_0F:
26733663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta = dis_ESC_0F  ( &dres, expect_CAS,
26734663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  resteerOkFn, resteerCisOk, callback_opaque,
26735663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  archinfo, vbi, pfx, sz, delta );
26736663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
26737663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case ESC_0F38:
26738663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta = dis_ESC_0F38( &dres,
26739663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  resteerOkFn, resteerCisOk, callback_opaque,
26740663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  archinfo, vbi, pfx, sz, delta );
26741663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
26742663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case ESC_0F3A:
26743663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta = dis_ESC_0F3A( &dres,
26744663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  resteerOkFn, resteerCisOk, callback_opaque,
26745663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  archinfo, vbi, pfx, sz, delta );
26746663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
26747663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         default:
26748663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            vassert(0);
26749663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
26750663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
26751663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VEX prefixed instruction */
26752663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Sloppy Intel wording: "An instruction encoded with a VEX.128
26753663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         prefix that loads a YMM register operand ..." zeroes out bits
26754663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         128 and above of the register. */
26755663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Bool uses_vvvv = False;
26756663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (esc) {
26757663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case ESC_0F:
26758663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta = dis_ESC_0F__VEX ( &dres, &uses_vvvv,
26759663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                      resteerOkFn, resteerCisOk,
26760663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                      callback_opaque,
26761663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                      archinfo, vbi, pfx, sz, delta );
26762663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
26763663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case ESC_0F38:
26764663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta = dis_ESC_0F38__VEX ( &dres, &uses_vvvv,
26765663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        resteerOkFn, resteerCisOk,
26766663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        callback_opaque,
26767663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        archinfo, vbi, pfx, sz, delta );
26768663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
26769663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case ESC_0F3A:
26770663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            delta = dis_ESC_0F3A__VEX ( &dres, &uses_vvvv,
26771663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        resteerOkFn, resteerCisOk,
26772663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        callback_opaque,
26773663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        archinfo, vbi, pfx, sz, delta );
26774663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
26775663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case ESC_NONE:
26776663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* The presence of a VEX prefix, by Intel definition,
26777663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               always implies at least an 0F escape. */
26778663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            goto decode_failure;
26779663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         default:
26780663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            vassert(0);
26781663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
26782663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* If the insn doesn't use VEX.vvvv then it must be all ones.
26783663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Check this. */
26784663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (!uses_vvvv) {
26785663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (getVexNvvvv(pfx) != 0)
26786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_failure;
26787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
26788663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
26789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26790663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(delta - delta_at_primary_opcode >= 0);
26791663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(delta - delta_at_primary_opcode < 16/*let's say*/);
26792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26793663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Use delta == delta_at_primary_opcode to denote decode failure.
26794663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      This implies that any successful decode must use at least one
26795663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      byte up. */
26796663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (delta == delta_at_primary_opcode)
26797663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      goto decode_failure;
26798663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   else
26799663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      goto decode_success; /* \o/ */
26800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26801663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#if 0 /* XYZZY */
26802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26803663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ---------------------------------------------------- */
26804663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* --- The SSE/SSE2 decoder.                        --- */
26805663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ---------------------------------------------------- */
26806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26807663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* What did I do to deserve SSE ?  Perhaps I was really bad in a
26808663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      previous life? */
26809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26810663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Note, this doesn't handle SSE3 right now.  All amd64s support
26811663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      SSE2 as a minimum so there is no point distinguishing SSE1 vs
26812663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      SSE2. */
26813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26814663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   insn = (UChar*)&guest_code[delta];
26815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26816663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* FXSAVE is spuriously at the start here only because it is
26817663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      thusly placed in guest-x86/toIR.c. */
26818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26819663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ------ SSE decoder main ------ */
26820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26821663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ---------------------------------------------------- */
26822663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* --- end of the SSE decoder.                      --- */
26823663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ---------------------------------------------------- */
26824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26825663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ---------------------------------------------------- */
26826663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* --- start of the SSE2 decoder.                   --- */
26827663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ---------------------------------------------------- */
26828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26829663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ---------------------------------------------------- */
26830663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* --- end of the SSE/SSE2 decoder.                 --- */
26831663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ---------------------------------------------------- */
26832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26833663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ---------------------------------------------------- */
26834663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* --- start of the SSE3 decoder.                   --- */
26835663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ---------------------------------------------------- */
26836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26837663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ---------------------------------------------------- */
26838663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* --- end of the SSE3 decoder.                     --- */
26839663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ---------------------------------------------------- */
26840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26841663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ---------------------------------------------------- */
26842663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* --- start of the SSSE3 decoder.                  --- */
26843663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ---------------------------------------------------- */
26844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26845663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ---------------------------------------------------- */
26846663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* --- end of the SSSE3 decoder.                    --- */
26847663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ---------------------------------------------------- */
26848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26849663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ---------------------------------------------------- */
26850663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* --- start of the SSE4 decoder                    --- */
26851663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ---------------------------------------------------- */
26852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26853663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ---------------------------------------------------- */
26854663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* --- end of the SSE4 decoder                      --- */
26855663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ---------------------------------------------------- */
26856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26857663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /*after_sse_decoders:*/
26858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26859663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Get the primary opcode. */
26860663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   opc = getUChar(delta); delta++;
26861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26862663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* We get here if the current insn isn't SSE, or this CPU doesn't
26863663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      support SSE. */
26864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26865663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (opc) {
26866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26867663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ------------------------ Control flow --------------- */
26868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26869663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ------------------------ CWD/CDQ -------------------- */
26870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26871663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ------------------------ FPU ops -------------------- */
26872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26873663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ------------------------ INT ------------------------ */
26874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26875663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0xCD: { /* INT imm8 */
26876663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRJumpKind jk = Ijk_Boring;
26877663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (have66orF2orF3(pfx)) goto decode_failure;
26878663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      d64 = getUChar(delta); delta++;
26879663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (d64) {
26880663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case 32: jk = Ijk_Sys_int32; break;
26881663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         default: goto decode_failure;
26882663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
26883663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      guest_RIP_next_mustcheck = True;
26884663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      guest_RIP_next_assumed = guest_RIP_bbstart + delta;
26885663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      jmp_lit(jk, guest_RIP_next_assumed);
26886663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* It's important that all ArchRegs carry their up-to-date value
26887663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         at this point.  So we declare an end-of-block here, which
26888663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         forces any TempRegs caching ArchRegs to be flushed. */
26889663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(dres.whatNext == Dis_StopHere);
26890663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DIP("int $0x%02x\n", (UInt)d64);
26891663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
26892663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
26893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26894663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ------------------------ Jcond, byte offset --------- */
26895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26896663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ------------------------ IMUL ----------------------- */
26897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26898663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ------------------------ MOV ------------------------ */
26899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26900663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ------------------------ MOVx ------------------------ */
26901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26902663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ------------------------ opl imm, A ----------------- */
26903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26904663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ------------------------ opl Ev, Gv ----------------- */
26905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26906663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ------------------------ opl Gv, Ev ----------------- */
26907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26908663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ------------------------ POP ------------------------ */
26909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26910663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ------------------------ PUSH ----------------------- */
26911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26912663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ------ AE: SCAS variants ------ */
26913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26914663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ------ A6, A7: CMPS variants ------ */
26915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26916663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ------ AA, AB: STOS variants ------ */
26917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26918663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ------ A4, A5: MOVS variants ------ */
26919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26920663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ------------------------ XCHG ----------------------- */
26921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26922663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ------------------------ IN / OUT ----------------------- */
26923663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
26924663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ------------------------ (Grp1 extensions) ---------- */
26925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26926663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ------------------------ (Grp2 extensions) ---------- */
26927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26928663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ------------------------ (Grp3 extensions) ---------- */
26929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26930663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ------------------------ (Grp4 extensions) ---------- */
26931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26932663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ------------------------ (Grp5 extensions) ---------- */
26933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26934663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ------------------------ Escapes to 2-byte opcodes -- */
26935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26936663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case 0x0F: {
26937663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      opc = getUChar(delta); delta++;
26938663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (opc) {
26939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26940663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* =-=-=-=-=-=-=-=-=- Grp8 =-=-=-=-=-=-=-=-=-=-=-= */
26941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26942663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* =-=-=-=-=-=-=-=-=- BSF/BSR -=-=-=-=-=-=-=-=-=-= */
26943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26944663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* =-=-=-=-=-=-=-=-=- BSWAP -=-=-=-=-=-=-=-=-=-=-= */
26945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26946663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* =-=-=-=-=-=-=-=-=- BT/BTS/BTR/BTC =-=-=-=-=-=-= */
26947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26948663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* =-=-=-=-=-=-=-=-=- CMOV =-=-=-=-=-=-=-=-=-=-=-= */
26949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26950663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* =-=-=-=-=-=-=-=-=- CMPXCHG -=-=-=-=-=-=-=-=-=-= */
26951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26952663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* =-=-=-=-=-=-=-=-=- CPUID -=-=-=-=-=-=-=-=-=-=-= */
26953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26954663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* =-=-=-=-=-=-=-=-=- MOVZX, MOVSX =-=-=-=-=-=-=-= */
26955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26956663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* =-=-=-=-=-=-=-=-=- MUL/IMUL =-=-=-=-=-=-=-=-=-= */
26957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26958663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* =-=-=-=-=-=-=-=-=- NOPs =-=-=-=-=-=-=-=-=-=-=-= */
26959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26960663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* =-=-=-=-=-=-=-=-=- Jcond d32 -=-=-=-=-=-=-=-=-= */
26961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26962663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* =-=-=-=-=-=-=-=-=- PREFETCH =-=-=-=-=-=-=-=-=-= */
26963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26964663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* =-=-=-=-=-=-=-=-=- RDTSC -=-=-=-=-=-=-=-=-=-=-= */
26965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26966663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* =-=-=-=-=-=-=-=-=- SETcc Eb =-=-=-=-=-=-=-=-=-= */
26967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26968663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* =-=-=-=-=-=-=-=-=- SHLD/SHRD -=-=-=-=-=-=-=-=-= */
26969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26970663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* =-=-=-=-=-=-=-=-=- SYSCALL -=-=-=-=-=-=-=-=-=-= */
26971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26972663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* =-=-=-=-=-=-=-=-=- XADD -=-=-=-=-=-=-=-=-=-= */
26973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26974663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0xC0: { /* XADD Gb,Eb */
26975663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Bool decode_OK = False;
26976663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         delta = dis_xadd_G_E ( &decode_OK, vbi, pfx, 1, delta );
26977663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (!decode_OK)
26978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_failure;
26979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
26980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
26981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* =-=-=-=-=-=-=-=-=- SGDT and SIDT =-=-=-=-=-=-=-=-=-=-= */
26983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* =-=-=-=-=-=-=-=-=- unimp2 =-=-=-=-=-=-=-=-=-=-= */
26985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
26987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
26988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* switch (opc) for the 2-byte opcodes */
26989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   goto decode_success;
26990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* case 0x0F: of primary opcode */
26991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------------------ ??? ------------------------ */
26993663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#endif /* XYZZY */
26994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26995663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     //default:
26996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  decode_failure:
26997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* All decode failures end up here. */
26998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("vex amd64->IR: unhandled instruction bytes: "
26999b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov              "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
27000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              (Int)getUChar(delta_start+0),
27001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              (Int)getUChar(delta_start+1),
27002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              (Int)getUChar(delta_start+2),
27003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              (Int)getUChar(delta_start+3),
27004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              (Int)getUChar(delta_start+4),
27005b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov              (Int)getUChar(delta_start+5),
27006b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov              (Int)getUChar(delta_start+6),
27007b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov              (Int)getUChar(delta_start+7) );
27008663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vex_printf("vex amd64->IR:   REX=%d REX.W=%d REX.R=%d REX.X=%d REX.B=%d\n",
27009663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              haveREX(pfx) ? 1 : 0, getRexW(pfx), getRexR(pfx),
27010663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              getRexX(pfx), getRexB(pfx));
27011663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vex_printf("vex amd64->IR:   VEX=%d VEX.L=%d VEX.nVVVV=0x%x ESC=%s\n",
27012663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              haveVEX(pfx) ? 1 : 0, getVexL(pfx),
27013663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              getVexNvvvv(pfx),
27014663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              esc==ESC_NONE ? "NONE" :
27015663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                esc==ESC_0F ? "0F" :
27016663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                esc==ESC_0F38 ? "0F38" :
27017663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                esc==ESC_0F3A ? "0F3A" : "???");
27018663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vex_printf("vex amd64->IR:   PFX.66=%d PFX.F2=%d PFX.F3=%d\n",
27019663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              have66(pfx) ? 1 : 0, haveF2(pfx) ? 1 : 0,
27020663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              haveF3(pfx) ? 1 : 0);
27021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
27022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Tell the dispatcher that this insn cannot be decoded, and so has
27023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      not been executed, and (is currently) the next to be executed.
27024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      RIP should be up-to-date since it made so at the start of each
27025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      insn, but nevertheless be paranoid and update it again right
27026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      now. */
27027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_RIP, mkU64(guest_RIP_curr_instr) ) );
27028663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   jmp_lit(&dres, Ijk_NoDecode, guest_RIP_curr_instr);
27029663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(dres.whatNext == Dis_StopHere);
27030663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   dres.len = 0;
27031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* We also need to say that a CAS is not expected now, regardless
27032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      of what it might have been set to at the start of the function,
27033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      since the IR that we've emitted just above (to synthesis a
27034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      SIGILL) does not involve any CAS, and presumably no other IR has
27035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      been emitted for this (non-decoded) insn. */
27036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *expect_CAS = False;
27037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return dres;
27038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
27039663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   //   } /* switch (opc) for the main (primary) opcode switch. */
27040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
27041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  decode_success:
27042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* All decode successes end up here. */
27043663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (dres.whatNext) {
27044663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Dis_Continue:
27045663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         stmt( IRStmt_Put( OFFB_RIP, mkU64(guest_RIP_bbstart + delta) ) );
27046663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
27047663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Dis_ResteerU:
27048663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Dis_ResteerC:
27049663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         stmt( IRStmt_Put( OFFB_RIP, mkU64(dres.continueAt) ) );
27050663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
27051663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Dis_StopHere:
27052663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
27053663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default:
27054663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(0);
27055663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
27056663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
27057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DIP("\n");
27058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   dres.len = (Int)toUInt(delta - delta_start);
27059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return dres;
27060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
27061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
27062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef DIP
27063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef DIS
27064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
27065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
27066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
27067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Top-level fn                                         ---*/
27068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
27069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
27070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Disassemble a single instruction into IR.  The instruction
27071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   is located in host memory at &guest_code[delta]. */
27072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
27073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownDisResult disInstr_AMD64 ( IRSB*        irsb_IN,
27074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           Bool         (*resteerOkFn) ( void*, Addr64 ),
27075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           Bool         resteerCisOk,
27076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           void*        callback_opaque,
27077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           UChar*       guest_code_IN,
27078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           Long         delta,
27079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           Addr64       guest_IP,
27080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           VexArch      guest_arch,
27081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           VexArchInfo* archinfo,
27082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           VexAbiInfo*  abiinfo,
27083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           Bool         host_bigendian_IN )
27084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
27085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int       i, x1, x2;
27086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool      expect_CAS, has_CAS;
27087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DisResult dres;
27088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
27089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Set globals (see top of this file) */
27090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(guest_arch == VexArchAMD64);
27091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   guest_code           = guest_code_IN;
27092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   irsb                 = irsb_IN;
27093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   host_is_bigendian    = host_bigendian_IN;
27094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   guest_RIP_curr_instr = guest_IP;
27095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   guest_RIP_bbstart    = guest_IP - delta;
27096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
27097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* We'll consult these after doing disInstr_AMD64_WRK. */
27098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   guest_RIP_next_assumed   = 0;
27099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   guest_RIP_next_mustcheck = False;
27100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
27101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   x1 = irsb_IN->stmts_used;
27102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   expect_CAS = False;
27103663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   dres = disInstr_AMD64_WRK ( &expect_CAS, resteerOkFn,
27104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               resteerCisOk,
27105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               callback_opaque,
27106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               delta, archinfo, abiinfo );
27107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   x2 = irsb_IN->stmts_used;
27108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(x2 >= x1);
27109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
27110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* If disInstr_AMD64_WRK tried to figure out the next rip, check it
27111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      got it right.  Failure of this assertion is serious and denotes
27112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      a bug in disInstr. */
27113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (guest_RIP_next_mustcheck
27114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && guest_RIP_next_assumed != guest_RIP_curr_instr + dres.len) {
27115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\n");
27116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("assumed next %%rip = 0x%llx\n",
27117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 guest_RIP_next_assumed );
27118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf(" actual next %%rip = 0x%llx\n",
27119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 guest_RIP_curr_instr + dres.len );
27120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vpanic("disInstr_AMD64: disInstr miscalculated next %rip");
27121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
27122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
27123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* See comment at the top of disInstr_AMD64_WRK for meaning of
27124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      expect_CAS.  Here, we (sanity-)check for the presence/absence of
27125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRCAS as directed by the returned expect_CAS value. */
27126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   has_CAS = False;
27127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = x1; i < x2; i++) {
27128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (irsb_IN->stmts[i]->tag == Ist_CAS)
27129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         has_CAS = True;
27130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
27131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
27132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (expect_CAS != has_CAS) {
27133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* inconsistency detected.  re-disassemble the instruction so as
27134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         to generate a useful error message; then assert. */
27135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_traceflags |= VEX_TRACE_FE;
27136663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      dres = disInstr_AMD64_WRK ( &expect_CAS, resteerOkFn,
27137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  resteerCisOk,
27138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  callback_opaque,
27139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  delta, archinfo, abiinfo );
27140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = x1; i < x2; i++) {
27141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\t\t");
27142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRStmt(irsb_IN->stmts[i]);
27143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n");
27144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
27145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Failure of this assertion is serious and denotes a bug in
27146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         disInstr. */
27147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vpanic("disInstr_AMD64: inconsistency in LOCK prefix handling");
27148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
27149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
27150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return dres;
27151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
27152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
27153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
27154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
27155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Unused stuff                                         ---*/
27156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
27157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
27158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// A potentially more Memcheck-friendly version of gen_LZCNT, if
27159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// this should ever be needed.
27160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
27161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//static IRTemp gen_LZCNT ( IRType ty, IRTemp src )
27162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//{
27163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   /* Scheme is simple: propagate the most significant 1-bit into all
27164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      lower positions in the word.  This gives a word of the form
27165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      0---01---1.  Now invert it, giving a word of the form
27166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      1---10---0, then do a population-count idiom (to count the 1s,
27167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      which is the number of leading zeroes, or the word size if the
27168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      original word was 0.
27169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   */
27170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   Int i;
27171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   IRTemp t[7];
27172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   for (i = 0; i < 7; i++) {
27173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      t[i] = newTemp(ty);
27174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   }
27175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   if (ty == Ity_I64) {
27176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      assign(t[0], binop(Iop_Or64, mkexpr(src),
27177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                   binop(Iop_Shr64, mkexpr(src),  mkU8(1))));
27178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      assign(t[1], binop(Iop_Or64, mkexpr(t[0]),
27179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                   binop(Iop_Shr64, mkexpr(t[0]), mkU8(2))));
27180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      assign(t[2], binop(Iop_Or64, mkexpr(t[1]),
27181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                   binop(Iop_Shr64, mkexpr(t[1]), mkU8(4))));
27182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      assign(t[3], binop(Iop_Or64, mkexpr(t[2]),
27183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                   binop(Iop_Shr64, mkexpr(t[2]), mkU8(8))));
27184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      assign(t[4], binop(Iop_Or64, mkexpr(t[3]),
27185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                   binop(Iop_Shr64, mkexpr(t[3]), mkU8(16))));
27186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      assign(t[5], binop(Iop_Or64, mkexpr(t[4]),
27187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                   binop(Iop_Shr64, mkexpr(t[4]), mkU8(32))));
27188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      assign(t[6], unop(Iop_Not64, mkexpr(t[5])));
27189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      return gen_POPCOUNT(ty, t[6]);
27190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   }
27191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   if (ty == Ity_I32) {
27192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      assign(t[0], binop(Iop_Or32, mkexpr(src),
27193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                   binop(Iop_Shr32, mkexpr(src),  mkU8(1))));
27194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      assign(t[1], binop(Iop_Or32, mkexpr(t[0]),
27195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                   binop(Iop_Shr32, mkexpr(t[0]), mkU8(2))));
27196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      assign(t[2], binop(Iop_Or32, mkexpr(t[1]),
27197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                   binop(Iop_Shr32, mkexpr(t[1]), mkU8(4))));
27198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      assign(t[3], binop(Iop_Or32, mkexpr(t[2]),
27199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                   binop(Iop_Shr32, mkexpr(t[2]), mkU8(8))));
27200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      assign(t[4], binop(Iop_Or32, mkexpr(t[3]),
27201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                   binop(Iop_Shr32, mkexpr(t[3]), mkU8(16))));
27202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      assign(t[5], unop(Iop_Not32, mkexpr(t[4])));
27203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      return gen_POPCOUNT(ty, t[5]);
27204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   }
27205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   if (ty == Ity_I16) {
27206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      assign(t[0], binop(Iop_Or16, mkexpr(src),
27207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                   binop(Iop_Shr16, mkexpr(src),  mkU8(1))));
27208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      assign(t[1], binop(Iop_Or16, mkexpr(t[0]),
27209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                   binop(Iop_Shr16, mkexpr(t[0]), mkU8(2))));
27210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      assign(t[2], binop(Iop_Or16, mkexpr(t[1]),
27211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                   binop(Iop_Shr16, mkexpr(t[1]), mkU8(4))));
27212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      assign(t[3], binop(Iop_Or16, mkexpr(t[2]),
27213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                   binop(Iop_Shr16, mkexpr(t[2]), mkU8(8))));
27214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      assign(t[4], unop(Iop_Not16, mkexpr(t[3])));
27215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      return gen_POPCOUNT(ty, t[4]);
27216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   }
27217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   vassert(0);
27218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//}
27219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
27220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
27221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
27222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end                                       guest_amd64_toIR.c ---*/
27223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
27224